]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branches 'pxa' and 'orion-fixes1'
authorRussell King <rmk@dyn-67.arm.linux.org.uk>
Tue, 29 Apr 2008 20:31:06 +0000 (21:31 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Tue, 29 Apr 2008 20:31:06 +0000 (21:31 +0100)
1183 files changed:
.gitignore
Documentation/00-INDEX
Documentation/ABI/stable/sysfs-class-ubi [new file with mode: 0644]
Documentation/DocBook/Makefile
Documentation/HOWTO
Documentation/arm/Samsung-S3C24XX/NAND.txt [new file with mode: 0644]
Documentation/arm/Samsung-S3C24XX/Overview.txt
Documentation/device-mapper/dm-crypt.txt [new file with mode: 0644]
Documentation/filesystems/nfs-rdma.txt
Documentation/filesystems/seq_file.txt
Documentation/i386/boot.txt
Documentation/ia64/kvm.txt [new file with mode: 0644]
Documentation/ide/ide-tape.txt
Documentation/ide/ide.txt
Documentation/ioctl-number.txt
Documentation/kbuild/modules.txt
Documentation/kernel-parameters.txt
Documentation/leds-class.txt
Documentation/mips/AU1xxx_IDE.README
Documentation/networking/phy.txt
Documentation/powerpc/booting-without-of.txt
Documentation/powerpc/kvm_440.txt [new file with mode: 0644]
Documentation/s390/kvm.txt [new file with mode: 0644]
Documentation/smart-config.txt [deleted file]
Documentation/usb/anchors.txt [new file with mode: 0644]
Documentation/usb/callbacks.txt [new file with mode: 0644]
Documentation/usb/persist.txt
Documentation/usb/usb-serial.txt
MAINTAINERS
Makefile
arch/arm/configs/am200epdkit_defconfig
arch/arm/mach-at91/at91cap9_devices.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/pm.c
arch/arm/mach-pxa/Makefile
arch/arm/mach-pxa/gumstix.c
arch/arm/mach-pxa/magician.c
arch/arm/mach-pxa/pm.c
arch/arm/mach-pxa/pxa3xx.c
arch/arm/oprofile/op_model_mpcore.c
arch/ia64/Kconfig
arch/ia64/Makefile
arch/ia64/kvm/Kconfig [new file with mode: 0644]
arch/ia64/kvm/Makefile [new file with mode: 0644]
arch/ia64/kvm/asm-offsets.c [new file with mode: 0644]
arch/ia64/kvm/kvm-ia64.c [new file with mode: 0644]
arch/ia64/kvm/kvm_fw.c [new file with mode: 0644]
arch/ia64/kvm/kvm_minstate.h [new file with mode: 0644]
arch/ia64/kvm/lapic.h [new file with mode: 0644]
arch/ia64/kvm/misc.h [new file with mode: 0644]
arch/ia64/kvm/mmio.c [new file with mode: 0644]
arch/ia64/kvm/optvfault.S [new file with mode: 0644]
arch/ia64/kvm/process.c [new file with mode: 0644]
arch/ia64/kvm/trampoline.S [new file with mode: 0644]
arch/ia64/kvm/vcpu.c [new file with mode: 0644]
arch/ia64/kvm/vcpu.h [new file with mode: 0644]
arch/ia64/kvm/vmm.c [new file with mode: 0644]
arch/ia64/kvm/vmm_ivt.S [new file with mode: 0644]
arch/ia64/kvm/vti.h [new file with mode: 0644]
arch/ia64/kvm/vtlb.c [new file with mode: 0644]
arch/powerpc/Kconfig
arch/powerpc/Kconfig.debug
arch/powerpc/Makefile
arch/powerpc/boot/.gitignore
arch/powerpc/boot/Makefile
arch/powerpc/boot/dts/canyonlands.dts
arch/powerpc/boot/dts/glacier.dts
arch/powerpc/boot/ns16550.c
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/cpu_setup_44x.S
arch/powerpc/kernel/cpu_setup_6xx.S
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/head_fsl_booke.S
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/misc_64.S
arch/powerpc/kernel/of_platform.c
arch/powerpc/kernel/paca.c
arch/powerpc/kernel/ppc32.h
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/prom_init_check.sh [new file with mode: 0644]
arch/powerpc/kernel/ptrace32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/stacktrace.c
arch/powerpc/kernel/udbg.c
arch/powerpc/kvm/44x_tlb.c [new file with mode: 0644]
arch/powerpc/kvm/44x_tlb.h [new file with mode: 0644]
arch/powerpc/kvm/Kconfig [new file with mode: 0644]
arch/powerpc/kvm/Makefile [new file with mode: 0644]
arch/powerpc/kvm/booke_guest.c [new file with mode: 0644]
arch/powerpc/kvm/booke_host.c [new file with mode: 0644]
arch/powerpc/kvm/booke_interrupts.S [new file with mode: 0644]
arch/powerpc/kvm/emulate.c [new file with mode: 0644]
arch/powerpc/kvm/powerpc.c [new file with mode: 0644]
arch/powerpc/mm/fsl_booke_mmu.c
arch/powerpc/mm/hash_low_32.S
arch/powerpc/mm/init_32.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/numa.c
arch/powerpc/mm/pgtable_32.c
arch/powerpc/platforms/Kconfig
arch/powerpc/platforms/Kconfig.cputype
arch/powerpc/platforms/Makefile
arch/powerpc/platforms/cell/Kconfig
arch/powerpc/platforms/cell/Makefile
arch/powerpc/platforms/cell/axon_msi.c
arch/powerpc/platforms/cell/beat.c [moved from arch/powerpc/platforms/celleb/beat.c with 99% similarity]
arch/powerpc/platforms/cell/beat.h [moved from arch/powerpc/platforms/celleb/beat.h with 100% similarity]
arch/powerpc/platforms/cell/beat_htab.c [moved from arch/powerpc/platforms/celleb/htab.c with 100% similarity]
arch/powerpc/platforms/cell/beat_hvCall.S [moved from arch/powerpc/platforms/celleb/hvCall.S with 100% similarity]
arch/powerpc/platforms/cell/beat_interrupt.c [moved from arch/powerpc/platforms/celleb/interrupt.c with 99% similarity]
arch/powerpc/platforms/cell/beat_interrupt.h [moved from arch/powerpc/platforms/celleb/interrupt.h with 100% similarity]
arch/powerpc/platforms/cell/beat_iommu.c [moved from arch/powerpc/platforms/celleb/iommu.c with 100% similarity]
arch/powerpc/platforms/cell/beat_smp.c [moved from arch/powerpc/platforms/celleb/smp.c with 99% similarity]
arch/powerpc/platforms/cell/beat_spu_priv1.c [moved from arch/powerpc/platforms/celleb/spu_priv1.c with 100% similarity]
arch/powerpc/platforms/cell/beat_syscall.h [moved from arch/powerpc/platforms/celleb/beat_syscall.h with 100% similarity]
arch/powerpc/platforms/cell/beat_udbg.c [moved from arch/powerpc/platforms/celleb/udbg_beat.c with 100% similarity]
arch/powerpc/platforms/cell/beat_wrapper.h [moved from arch/powerpc/platforms/celleb/beat_wrapper.h with 100% similarity]
arch/powerpc/platforms/cell/celleb_pci.c [moved from arch/powerpc/platforms/celleb/pci.c with 93% similarity]
arch/powerpc/platforms/cell/celleb_pci.h [moved from arch/powerpc/platforms/celleb/pci.h with 73% similarity]
arch/powerpc/platforms/cell/celleb_scc.h [moved from arch/powerpc/platforms/celleb/scc.h with 68% similarity]
arch/powerpc/platforms/cell/celleb_scc_epci.c [moved from arch/powerpc/platforms/celleb/scc_epci.c with 86% similarity]
arch/powerpc/platforms/cell/celleb_scc_pciex.c [new file with mode: 0644]
arch/powerpc/platforms/cell/celleb_scc_sio.c [moved from arch/powerpc/platforms/celleb/scc_sio.c with 100% similarity]
arch/powerpc/platforms/cell/celleb_scc_uhc.c [moved from arch/powerpc/platforms/celleb/scc_uhc.c with 99% similarity]
arch/powerpc/platforms/cell/celleb_setup.c [moved from arch/powerpc/platforms/celleb/setup.c with 97% similarity]
arch/powerpc/platforms/cell/io-workarounds.c
arch/powerpc/platforms/cell/io-workarounds.h [new file with mode: 0644]
arch/powerpc/platforms/cell/setup.c
arch/powerpc/platforms/cell/spider-pci.c [new file with mode: 0644]
arch/powerpc/platforms/celleb/Kconfig [deleted file]
arch/powerpc/platforms/celleb/Makefile [deleted file]
arch/powerpc/platforms/celleb/io-workarounds.c [deleted file]
arch/powerpc/platforms/iseries/exception.S
arch/powerpc/platforms/ps3/os-area.c
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/Makefile
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/eeh_cache.c
arch/powerpc/platforms/pseries/firmware.c
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/platforms/pseries/ras.c
arch/powerpc/platforms/pseries/rtasd.c
arch/powerpc/platforms/pseries/scanlog.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/platforms/pseries/smp.c
arch/powerpc/platforms/pseries/xics.c
arch/powerpc/sysdev/mv64x60_dev.c
arch/powerpc/sysdev/mv64x60_udbg.c
arch/ppc/8260_io/fcc_enet.c
arch/ppc/8xx_io/enet.c
arch/ppc/Kconfig
arch/ppc/configs/ads8272_defconfig [deleted file]
arch/ppc/configs/mpc86x_ads_defconfig [deleted file]
arch/ppc/configs/mpc885ads_defconfig [deleted file]
arch/ppc/kernel/ppc_ksyms.c
arch/ppc/lib/string.S
arch/ppc/platforms/Makefile
arch/ppc/platforms/fads.h
arch/ppc/platforms/mpc8272ads_setup.c [deleted file]
arch/ppc/platforms/mpc885ads.h [deleted file]
arch/ppc/platforms/mpc885ads_setup.c [deleted file]
arch/ppc/platforms/pq2ads.c [deleted file]
arch/ppc/platforms/pq2ads.h [deleted file]
arch/ppc/platforms/pq2ads_pd.h [deleted file]
arch/ppc/syslib/m8260_setup.c
arch/ppc/syslib/m82xx_pci.c
arch/ppc/syslib/m8xx_setup.c
arch/s390/Kconfig
arch/s390/Makefile
arch/s390/kernel/early.c
arch/s390/kernel/setup.c
arch/s390/kernel/vtime.c
arch/s390/kvm/Kconfig [new file with mode: 0644]
arch/s390/kvm/Makefile [new file with mode: 0644]
arch/s390/kvm/diag.c [new file with mode: 0644]
arch/s390/kvm/gaccess.h [new file with mode: 0644]
arch/s390/kvm/intercept.c [new file with mode: 0644]
arch/s390/kvm/interrupt.c [new file with mode: 0644]
arch/s390/kvm/kvm-s390.c [new file with mode: 0644]
arch/s390/kvm/kvm-s390.h [new file with mode: 0644]
arch/s390/kvm/priv.c [new file with mode: 0644]
arch/s390/kvm/sie64a.S [new file with mode: 0644]
arch/s390/kvm/sigp.c [new file with mode: 0644]
arch/s390/mm/pgtable.c
arch/sparc64/kernel/smp.c
arch/sparc64/kernel/sys_sparc.c
arch/um/Kconfig.x86_64
arch/um/os-Linux/helper.c
arch/um/sys-i386/Makefile
arch/um/sys-x86_64/Makefile
arch/x86/Kconfig
arch/x86/Kconfig.cpu
arch/x86/Kconfig.debug
arch/x86/boot/.gitignore
arch/x86/boot/header.S
arch/x86/configs/i386_defconfig
arch/x86/configs/x86_64_defconfig
arch/x86/ia32/ia32_signal.c
arch/x86/ia32/ia32entry.S
arch/x86/kernel/Makefile
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/acpi/realmode/.gitignore [new file with mode: 0644]
arch/x86/kernel/alternative.c
arch/x86/kernel/apic_32.c
arch/x86/kernel/apic_64.c
arch/x86/kernel/apm_32.c
arch/x86/kernel/cpu/Makefile
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/mcheck/mce_64.c
arch/x86/kernel/cpu/nexgen.c [deleted file]
arch/x86/kernel/cpu/perfctr-watchdog.c
arch/x86/kernel/crash.c
arch/x86/kernel/e820_64.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/genapic_64.c
arch/x86/kernel/head64.c
arch/x86/kernel/hpet.c
arch/x86/kernel/i8253.c
arch/x86/kernel/io_apic_32.c
arch/x86/kernel/io_apic_64.c
arch/x86/kernel/irq_32.c
arch/x86/kernel/kdebugfs.c
arch/x86/kernel/kvm.c [new file with mode: 0644]
arch/x86/kernel/kvmclock.c [new file with mode: 0644]
arch/x86/kernel/mfgpt_32.c
arch/x86/kernel/mpparse.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/pci-calgary_64.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/reboot.c
arch/x86/kernel/setup.c
arch/x86/kernel/setup_32.c
arch/x86/kernel/setup_64.c
arch/x86/kernel/signal_32.c
arch/x86/kernel/signal_64.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/summit_32.c
arch/x86/kernel/tlb_64.c
arch/x86/kernel/trampoline_32.S
arch/x86/kernel/traps_32.c
arch/x86/kernel/vmi_32.c
arch/x86/kernel/vsyscall_64.c
arch/x86/kvm/Kconfig
arch/x86/kvm/Makefile
arch/x86/kvm/i8254.c [new file with mode: 0644]
arch/x86/kvm/i8254.h [new file with mode: 0644]
arch/x86/kvm/irq.c
arch/x86/kvm/irq.h
arch/x86/kvm/kvm_svm.h
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/mmu.h
arch/x86/kvm/paging_tmpl.h
arch/x86/kvm/segment_descriptor.h [deleted file]
arch/x86/kvm/svm.c
arch/x86/kvm/svm.h
arch/x86/kvm/tss.h [new file with mode: 0644]
arch/x86/kvm/vmx.c
arch/x86/kvm/vmx.h
arch/x86/kvm/x86.c
arch/x86/kvm/x86_emulate.c
arch/x86/lib/Makefile
arch/x86/lib/bitops_32.c [deleted file]
arch/x86/lib/bitops_64.c [deleted file]
arch/x86/mach-visws/mpparse.c
arch/x86/mach-voyager/voyager_smp.c
arch/x86/mm/Makefile
arch/x86/mm/dump_pagetables.c
arch/x86/mm/init_32.c
arch/x86/mm/init_64.c
arch/x86/mm/ioremap.c
arch/x86/mm/numa_64.c
arch/x86/mm/pageattr.c
arch/x86/mm/pat.c
arch/x86/mm/pgtable.c [new file with mode: 0644]
arch/x86/mm/pgtable_32.c
arch/x86/mm/srat_64.c
arch/x86/xen/Kconfig
arch/x86/xen/Makefile
arch/x86/xen/enlighten.c
arch/x86/xen/grant-table.c [new file with mode: 0644]
arch/x86/xen/mmu.c
arch/x86/xen/setup.c
arch/x86/xen/smp.c
arch/x86/xen/xen-asm.S
arch/x86/xen/xen-ops.h
block/bsg.c
drivers/Kconfig
drivers/acpi/processor_idle.c
drivers/ata/ahci.c
drivers/ata/ata_piix.c
drivers/ata/libata-acpi.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-sff.c
drivers/ata/libata.h
drivers/ata/pata_at32.c
drivers/ata/pata_bf54x.c
drivers/ata/pata_ixp4xx_cf.c
drivers/ata/pata_platform.c
drivers/ata/pata_rb500_cf.c
drivers/ata/sata_mv.c
drivers/ata/sata_nv.c
drivers/ata/sata_sis.c
drivers/block/xen-blkfront.c
drivers/char/agp/amd-k7-agp.c
drivers/char/agp/frontend.c
drivers/char/drm/ati_pcigart.c
drivers/char/drm/drm.h
drivers/char/drm/drmP.h
drivers/char/drm/drm_agpsupport.c
drivers/char/drm/drm_drv.c
drivers/char/drm/drm_fops.c
drivers/char/drm/drm_irq.c
drivers/char/drm/drm_proc.c
drivers/char/drm/drm_stub.c
drivers/char/drm/drm_sysfs.c
drivers/char/drm/drm_vm.c
drivers/char/drm/i810_dma.c
drivers/char/drm/i830_dma.c
drivers/char/drm/i915_dma.c
drivers/char/drm/i915_drm.h
drivers/char/drm/i915_drv.c
drivers/char/drm/i915_drv.h
drivers/char/drm/i915_irq.c
drivers/char/drm/mga_drv.c
drivers/char/drm/mga_drv.h
drivers/char/drm/mga_irq.c
drivers/char/drm/r128_drv.c
drivers/char/drm/r128_drv.h
drivers/char/drm/r128_irq.c
drivers/char/drm/radeon_drv.c
drivers/char/drm/radeon_drv.h
drivers/char/drm/radeon_irq.c
drivers/char/drm/via_drv.c
drivers/char/drm/via_drv.h
drivers/char/drm/via_irq.c
drivers/char/keyboard.c
drivers/char/mem.c
drivers/char/xilinx_hwicap/xilinx_hwicap.c
drivers/hid/usbhid/hid-quirks.c
drivers/ide/Kconfig
drivers/ide/arm/bast-ide.c
drivers/ide/arm/icside.c
drivers/ide/arm/ide_arm.c
drivers/ide/arm/palm_bk3710.c
drivers/ide/arm/rapide.c
drivers/ide/cris/ide-cris.c
drivers/ide/h8300/ide-h8300.c
drivers/ide/ide-acpi.c
drivers/ide/ide-cd.c
drivers/ide/ide-cd.h
drivers/ide/ide-disk.c
drivers/ide/ide-dma.c
drivers/ide/ide-floppy.c
drivers/ide/ide-generic.c
drivers/ide/ide-io.c
drivers/ide/ide-iops.c
drivers/ide/ide-lib.c
drivers/ide/ide-pnp.c
drivers/ide/ide-probe.c
drivers/ide/ide-proc.c
drivers/ide/ide-scan-pci.c
drivers/ide/ide-tape.c
drivers/ide/ide-taskfile.c
drivers/ide/ide.c
drivers/ide/legacy/ali14xx.c
drivers/ide/legacy/buddha.c
drivers/ide/legacy/dtc2278.c
drivers/ide/legacy/falconide.c
drivers/ide/legacy/gayle.c
drivers/ide/legacy/hd.c
drivers/ide/legacy/ht6560b.c
drivers/ide/legacy/ide-4drives.c
drivers/ide/legacy/ide-cs.c
drivers/ide/legacy/ide_platform.c
drivers/ide/legacy/macide.c
drivers/ide/legacy/q40ide.c
drivers/ide/legacy/qd65xx.c
drivers/ide/legacy/qd65xx.h
drivers/ide/legacy/umc8672.c
drivers/ide/mips/au1xxx-ide.c
drivers/ide/mips/swarm.c
drivers/ide/pci/aec62xx.c
drivers/ide/pci/alim15x3.c
drivers/ide/pci/amd74xx.c
drivers/ide/pci/atiixp.c
drivers/ide/pci/cmd640.c
drivers/ide/pci/cmd64x.c
drivers/ide/pci/cs5520.c
drivers/ide/pci/cs5530.c
drivers/ide/pci/cs5535.c
drivers/ide/pci/cy82c693.c
drivers/ide/pci/delkin_cb.c
drivers/ide/pci/generic.c
drivers/ide/pci/hpt34x.c
drivers/ide/pci/hpt366.c
drivers/ide/pci/it8213.c
drivers/ide/pci/it821x.c
drivers/ide/pci/jmicron.c
drivers/ide/pci/ns87415.c
drivers/ide/pci/opti621.c
drivers/ide/pci/pdc202xx_new.c
drivers/ide/pci/pdc202xx_old.c
drivers/ide/pci/piix.c
drivers/ide/pci/rz1000.c
drivers/ide/pci/sc1200.c
drivers/ide/pci/scc_pata.c
drivers/ide/pci/serverworks.c
drivers/ide/pci/sgiioc4.c
drivers/ide/pci/siimage.c
drivers/ide/pci/sis5513.c
drivers/ide/pci/sl82c105.c
drivers/ide/pci/slc90e66.c
drivers/ide/pci/tc86c001.c
drivers/ide/pci/triflex.c
drivers/ide/pci/trm290.c
drivers/ide/pci/via82cxxx.c
drivers/ide/ppc/mpc8xx.c
drivers/ide/ppc/pmac.c
drivers/ide/setup-pci.c
drivers/ieee1394/dv1394.c
drivers/ieee1394/iso.h
drivers/ieee1394/ohci1394.c
drivers/ieee1394/raw1394.c
drivers/ieee1394/video1394.c
drivers/infiniband/hw/ehca/ehca_classes.h
drivers/infiniband/hw/ehca/ehca_irq.c
drivers/infiniband/hw/ehca/ehca_main.c
drivers/infiniband/hw/ehca/ehca_mrmw.c
drivers/infiniband/hw/ehca/ehca_qp.c
drivers/infiniband/hw/ehca/ehca_reqs.c
drivers/infiniband/hw/ehca/ehca_uverbs.c
drivers/infiniband/hw/ehca/hcp_if.c
drivers/infiniband/hw/mlx4/cq.c
drivers/infiniband/hw/mlx4/doorbell.c
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/nes/nes.c
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/hw/nes/nes_hw.c
drivers/infiniband/hw/nes/nes_hw.h
drivers/infiniband/hw/nes/nes_nic.c
drivers/infiniband/hw/nes/nes_utils.c
drivers/infiniband/hw/nes/nes_verbs.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/infiniband/ulp/ipoib/ipoib_verbs.c
drivers/infiniband/ulp/ipoib/ipoib_vlan.c
drivers/input/Kconfig
drivers/input/Makefile
drivers/input/input-polldev.c
drivers/input/joystick/Kconfig
drivers/input/joystick/Makefile
drivers/input/joystick/xpad.c
drivers/input/joystick/zhenhua.c [new file with mode: 0644]
drivers/input/keyboard/aaed2000_kbd.c
drivers/input/keyboard/bf54x-keys.c
drivers/input/keyboard/corgikbd.c
drivers/input/keyboard/gpio_keys.c
drivers/input/keyboard/jornada680_kbd.c
drivers/input/keyboard/jornada720_kbd.c
drivers/input/keyboard/locomokbd.c
drivers/input/keyboard/omap-keypad.c
drivers/input/keyboard/pxa27x_keypad.c
drivers/input/keyboard/spitzkbd.c
drivers/input/keyboard/tosakbd.c
drivers/input/misc/cobalt_btns.c
drivers/input/mouse/gpio_mouse.c
drivers/input/serio/Kconfig
drivers/input/serio/Makefile
drivers/input/serio/at32psif.c [new file with mode: 0644]
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/rpckbd.c
drivers/input/tablet/Kconfig
drivers/input/tablet/aiptek.c
drivers/input/tablet/wacom.h
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_wac.c
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/corgi_ts.c
drivers/input/touchscreen/jornada720_ts.c
drivers/input/touchscreen/mainstone-wm97xx.c [new file with mode: 0644]
drivers/input/touchscreen/ucb1400_ts.c
drivers/input/touchscreen/usbtouchscreen.c
drivers/input/touchscreen/wm9705.c [new file with mode: 0644]
drivers/input/touchscreen/wm9712.c [new file with mode: 0644]
drivers/input/touchscreen/wm9713.c [new file with mode: 0644]
drivers/input/touchscreen/wm97xx-core.c [new file with mode: 0644]
drivers/input/xen-kbdfront.c [new file with mode: 0644]
drivers/leds/Kconfig
drivers/leds/Makefile
drivers/leds/led-class.c
drivers/leds/led-core.c
drivers/leds/led-triggers.c
drivers/leds/leds-clevo-mail.c
drivers/leds/leds-cobalt-qube.c
drivers/leds/leds-cobalt-raq.c
drivers/leds/leds-corgi.c
drivers/leds/leds-fsg.c [new file with mode: 0644]
drivers/leds/leds-gpio.c
drivers/leds/leds-h1940.c
drivers/leds/leds-hp6xx.c
drivers/leds/leds-s3c24xx.c
drivers/leds/leds-spitz.c
drivers/leds/leds.h
drivers/leds/ledtrig-default-on.c [new file with mode: 0644]
drivers/leds/ledtrig-ide-disk.c
drivers/leds/ledtrig-timer.c
drivers/macintosh/mac_hid.c
drivers/macintosh/windfarm_pm112.c
drivers/macintosh/windfarm_pm81.c
drivers/macintosh/windfarm_pm91.c
drivers/md/Makefile
drivers/md/dm-exception-store.c
drivers/md/dm-io.c
drivers/md/dm-kcopyd.c [moved from drivers/md/kcopyd.c with 71% similarity]
drivers/md/dm-log.c
drivers/md/dm-raid1.c
drivers/md/dm-snap.c
drivers/md/dm-snap.h
drivers/md/dm-table.c
drivers/md/dm.c
drivers/md/dm.h
drivers/md/kcopyd.h [deleted file]
drivers/media/dvb/dvb-usb/dib0700_devices.c
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/mt312.h
drivers/media/dvb/frontends/s5h1411.c [new file with mode: 0644]
drivers/media/dvb/frontends/s5h1411.h [new file with mode: 0644]
drivers/media/video/au0828/Kconfig
drivers/media/video/au0828/au0828-cards.c
drivers/media/video/au0828/au0828-core.c
drivers/media/video/au0828/au0828-dvb.c
drivers/media/video/au0828/au0828-i2c.c
drivers/media/video/au0828/au0828.h
drivers/media/video/cx23885/cx23885-dvb.c
drivers/media/video/cx88/Kconfig
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/em28xx/em28xx-core.c
drivers/media/video/ir-kbd-i2c.c
drivers/media/video/pvrusb2/Kconfig
drivers/media/video/pvrusb2/pvrusb2-devattr.c
drivers/media/video/pvrusb2/pvrusb2-devattr.h
drivers/media/video/tuner-core.c
drivers/media/video/tuner-xc2028.c
drivers/media/video/vivi.c
drivers/mfd/htc-pasic3.c
drivers/misc/enclosure.c
drivers/mmc/host/mmci.c
drivers/mtd/Kconfig
drivers/mtd/Makefile
drivers/mtd/ar7part.c [new file with mode: 0644]
drivers/mtd/chips/cfi_cmdset_0001.c
drivers/mtd/chips/cfi_cmdset_0002.c
drivers/mtd/chips/cfi_cmdset_0020.c
drivers/mtd/chips/cfi_probe.c
drivers/mtd/chips/cfi_util.c
drivers/mtd/chips/jedec_probe.c
drivers/mtd/cmdlinepart.c
drivers/mtd/devices/Kconfig
drivers/mtd/devices/block2mtd.c
drivers/mtd/devices/lart.c
drivers/mtd/devices/m25p80.c
drivers/mtd/devices/mtdram.c
drivers/mtd/devices/phram.c
drivers/mtd/ftl.c
drivers/mtd/inftlmount.c
drivers/mtd/maps/Kconfig
drivers/mtd/maps/bast-flash.c
drivers/mtd/maps/ck804xrom.c
drivers/mtd/maps/integrator-flash.c
drivers/mtd/maps/ixp2000.c
drivers/mtd/maps/ixp4xx.c
drivers/mtd/maps/omap_nor.c
drivers/mtd/maps/pcmciamtd.c
drivers/mtd/maps/physmap.c
drivers/mtd/maps/plat-ram.c
drivers/mtd/maps/pmcmsp-flash.c
drivers/mtd/maps/sa1100-flash.c
drivers/mtd/maps/sharpsl-flash.c
drivers/mtd/maps/tqm8xxl.c
drivers/mtd/mtdoops.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/at91_nand.c
drivers/mtd/nand/bf5xx_nand.c
drivers/mtd/nand/cs553x_nand.c
drivers/mtd/nand/fsl_elbc_nand.c
drivers/mtd/nand/fsl_upm.c [new file with mode: 0644]
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/ndfc.c
drivers/mtd/nand/orion_nand.c
drivers/mtd/nand/plat_nand.c
drivers/mtd/nand/pxa3xx_nand.c [new file with mode: 0644]
drivers/mtd/nand/rtc_from4.c
drivers/mtd/nand/s3c2410.c
drivers/mtd/nftlmount.c
drivers/mtd/ofpart.c
drivers/mtd/onenand/onenand_base.c
drivers/mtd/onenand/onenand_bbt.c
drivers/mtd/rfd_ftl.c
drivers/mtd/ubi/Kconfig
drivers/mtd/ubi/build.c
drivers/mtd/ubi/debug.h
drivers/mtd/ubi/gluebi.c
drivers/mtd/ubi/io.c
drivers/mtd/ubi/scan.c
drivers/mtd/ubi/scan.h
drivers/mtd/ubi/ubi-media.h [moved from include/mtd/ubi-header.h with 99% similarity]
drivers/mtd/ubi/ubi.h
drivers/net/Kconfig
drivers/net/arm/am79c961a.c
drivers/net/arm/at91_ether.c
drivers/net/arm/ep93xx_eth.c
drivers/net/atlx/atl1.c
drivers/net/atlx/atlx.c
drivers/net/ax88796.c
drivers/net/bfin_mac.c
drivers/net/cpmac.c
drivers/net/dm9000.c
drivers/net/e1000e/82571.c
drivers/net/e1000e/defines.h
drivers/net/e1000e/e1000.h
drivers/net/e1000e/es2lan.c
drivers/net/e1000e/ethtool.c
drivers/net/e1000e/hw.h
drivers/net/e1000e/netdev.c
drivers/net/e1000e/phy.c
drivers/net/ehea/ehea_main.c
drivers/net/forcedeth.c
drivers/net/gianfar.c
drivers/net/ibm_newemac/core.c
drivers/net/ibm_newemac/core.h
drivers/net/ibm_newemac/mal.c
drivers/net/ibm_newemac/rgmii.c
drivers/net/ibm_newemac/tah.c
drivers/net/ibm_newemac/zmii.c
drivers/net/igb/igb_main.c
drivers/net/irda/ali-ircc.c
drivers/net/irda/pxaficp_ir.c
drivers/net/irda/sa1100_ir.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/jazzsonic.c
drivers/net/korina.c
drivers/net/macb.c
drivers/net/meth.c
drivers/net/mlx4/alloc.c
drivers/net/mlx4/cq.c
drivers/net/mlx4/main.c
drivers/net/mlx4/mlx4.h
drivers/net/mlx4/qp.c
drivers/net/mv643xx_eth.c
drivers/net/netx-eth.c
drivers/net/netxen/netxen_nic_hw.c
drivers/net/niu.c
drivers/net/niu.h
drivers/net/phy/mdio_bus.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/s2io.c
drivers/net/s2io.h
drivers/net/sgiseeq.c
drivers/net/smc911x.c
drivers/net/smc91x.c
drivers/net/sni_82596.c
drivers/net/tehuti.c
drivers/net/tg3.c
drivers/net/tsi108_eth.c
drivers/net/typhoon.c
drivers/net/ucc_geth.c
drivers/net/via-velocity.c
drivers/net/wan/c101.c
drivers/net/wan/hdlc_fr.c
drivers/net/xen-netfront.c
drivers/of/of_i2c.c
drivers/pci/intel-iommu.c
drivers/s390/Makefile
drivers/s390/kvm/Makefile [new file with mode: 0644]
drivers/s390/kvm/kvm_virtio.c [new file with mode: 0644]
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_fsf.h
drivers/s390/scsi/zfcp_scsi.c
drivers/scsi/FlashPoint.c
drivers/scsi/Kconfig
drivers/scsi/Makefile
drivers/scsi/aha152x.c
drivers/scsi/aha1542.c
drivers/scsi/aic7xxx/aic79xx.h
drivers/scsi/aic7xxx/aic79xx.reg
drivers/scsi/aic7xxx/aic79xx_core.c
drivers/scsi/aic7xxx/aic79xx_inline.h
drivers/scsi/aic7xxx/aic79xx_osm.c
drivers/scsi/aic7xxx/aic79xx_osm.h
drivers/scsi/aic7xxx/aic79xx_osm_pci.c
drivers/scsi/aic7xxx/aic79xx_pci.c
drivers/scsi/aic7xxx/aic79xx_proc.c
drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
drivers/scsi/aic7xxx/aic7xxx.h
drivers/scsi/aic7xxx/aic7xxx.reg
drivers/scsi/aic7xxx/aic7xxx_93cx6.c
drivers/scsi/aic7xxx/aic7xxx_core.c
drivers/scsi/aic7xxx/aic7xxx_inline.h
drivers/scsi/aic7xxx/aic7xxx_osm.c
drivers/scsi/aic7xxx/aic7xxx_osm.h
drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
drivers/scsi/aic7xxx/aic7xxx_pci.c
drivers/scsi/aic7xxx/aic7xxx_proc.c
drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
drivers/scsi/aic7xxx/aicasm/aicasm.c
drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c
drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h
drivers/scsi/eata.c
drivers/scsi/esp_scsi.c
drivers/scsi/esp_scsi.h
drivers/scsi/hosts.c
drivers/scsi/ide-scsi.c
drivers/scsi/jazz_esp.c
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/mac_esp.c [new file with mode: 0644]
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_fw.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_gs.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/scsi_priv.h
drivers/scsi/scsi_proc.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_transport_fc.c
drivers/scsi/scsi_transport_sas.c
drivers/scsi/scsi_transport_spi.c
drivers/scsi/sgiwd93.c
drivers/scsi/sni_53c710.c
drivers/scsi/st.c
drivers/scsi/sun3x_esp.c
drivers/scsi/u14-34f.c
drivers/serial/of_serial.c
drivers/serial/s3c2410.c
drivers/usb/atm/cxacru.c
drivers/usb/atm/ueagle-atm.c
drivers/usb/atm/usbatm.c
drivers/usb/atm/usbatm.h
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-acm.h
drivers/usb/core/Kconfig
drivers/usb/core/config.c
drivers/usb/core/devio.c
drivers/usb/core/driver.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/hub.h
drivers/usb/core/inode.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.h
drivers/usb/gadget/Kconfig
drivers/usb/gadget/amd5536udc.c
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/epautoconf.c
drivers/usb/gadget/ether.c
drivers/usb/gadget/file_storage.c
drivers/usb/gadget/fsl_usb2_udc.c
drivers/usb/gadget/fsl_usb2_udc.h
drivers/usb/gadget/gmidi.c
drivers/usb/gadget/goku_udc.c
drivers/usb/gadget/inode.c
drivers/usb/gadget/lh7a40x_udc.c
drivers/usb/gadget/m66592-udc.h
drivers/usb/gadget/net2280.h
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/printer.c
drivers/usb/gadget/pxa2xx_udc.c
drivers/usb/gadget/rndis.c
drivers/usb/gadget/serial.c
drivers/usb/host/Kconfig
drivers/usb/host/ehci-au1xxx.c
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-ixp4xx.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-ppc-soc.c
drivers/usb/host/ehci-ps3.c
drivers/usb/host/ehci-q.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/isp116x-hcd.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-au1xxx.c
drivers/usb/host/ohci-dbg.c
drivers/usb/host/ohci-ep93xx.c
drivers/usb/host/ohci-hub.c
drivers/usb/host/ohci-lh7a404.c
drivers/usb/host/ohci-omap.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/ohci-pnx4008.c
drivers/usb/host/ohci-pnx8550.c
drivers/usb/host/ohci-ppc-of.c
drivers/usb/host/ohci-ppc-soc.c
drivers/usb/host/ohci-ps3.c
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/ohci-s3c2410.c
drivers/usb/host/ohci-sa1111.c
drivers/usb/host/ohci-sh.c
drivers/usb/host/ohci-sm501.c
drivers/usb/host/ohci-ssb.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/r8a66597-hcd.c
drivers/usb/host/r8a66597.h
drivers/usb/host/sl811-hcd.c
drivers/usb/host/u132-hcd.c
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-q.c
drivers/usb/image/Kconfig
drivers/usb/image/microtek.c
drivers/usb/image/microtek.h
drivers/usb/misc/Kconfig
drivers/usb/misc/adutux.c
drivers/usb/misc/appledisplay.c
drivers/usb/misc/auerswald.c
drivers/usb/misc/emi26.c
drivers/usb/misc/emi62.c
drivers/usb/misc/ftdi-elan.c
drivers/usb/misc/iowarrior.c
drivers/usb/misc/ldusb.c
drivers/usb/misc/legousbtower.c
drivers/usb/misc/phidgetkit.c
drivers/usb/misc/phidgetmotorcontrol.c
drivers/usb/misc/phidgetservo.c
drivers/usb/misc/usblcd.c
drivers/usb/misc/usbtest.c
drivers/usb/mon/Makefile
drivers/usb/mon/mon_bin.c
drivers/usb/mon/mon_main.c
drivers/usb/mon/mon_stat.c
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/ch341.c
drivers/usb/serial/console.c
drivers/usb/serial/cp2101.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/ezusb.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/funsoft.c
drivers/usb/serial/garmin_gps.c
drivers/usb/serial/generic.c
drivers/usb/serial/hp4x.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/io_tables.h
drivers/usb/serial/io_ti.c
drivers/usb/serial/ipaq.c
drivers/usb/serial/ipw.c
drivers/usb/serial/ir-usb.c
drivers/usb/serial/iuu_phoenix.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/keyspan.h
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/mct_u232.c
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
drivers/usb/serial/pl2303.c
drivers/usb/serial/safe_serial.c
drivers/usb/serial/sierra.c
drivers/usb/serial/spcp8x5.c [new file with mode: 0644]
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb-serial.c
drivers/usb/serial/usb_debug.c
drivers/usb/serial/visor.c
drivers/usb/serial/whiteheat.c
drivers/usb/storage/Kconfig
drivers/usb/storage/Makefile
drivers/usb/storage/cypress_atacb.c [new file with mode: 0644]
drivers/usb/storage/cypress_atacb.h [new file with mode: 0644]
drivers/usb/storage/libusual.c
drivers/usb/storage/scsiglue.c
drivers/usb/storage/transport.c
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/usb.c
drivers/usb/usb-skeleton.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/xen-fbfront.c [new file with mode: 0644]
drivers/xen/Kconfig [new file with mode: 0644]
drivers/xen/Makefile
drivers/xen/balloon.c [new file with mode: 0644]
drivers/xen/events.c [moved from arch/x86/xen/events.c with 82% similarity]
drivers/xen/features.c [moved from arch/x86/xen/features.c with 100% similarity]
drivers/xen/grant-table.c
drivers/xen/xenbus/xenbus_client.c
drivers/xen/xenbus/xenbus_probe.c
drivers/xen/xencomm.c [new file with mode: 0644]
fs/9p/vfs_super.c
fs/binfmt_elf.c
fs/binfmt_misc.c
fs/binfmt_som.c
fs/cifs/CHANGES
fs/cifs/README
fs/cifs/cifs_dfs_ref.c
fs/cifs/cifsacl.c
fs/cifs/cifsacl.h
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/cifspdu.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/inode.c
fs/cifs/transport.c
fs/exec.c
fs/fcntl.c
fs/fuse/inode.c
fs/jffs2/README.Locking
fs/jffs2/build.c
fs/jffs2/debug.c
fs/jffs2/debug.h
fs/jffs2/dir.c
fs/jffs2/erase.c
fs/jffs2/file.c
fs/jffs2/fs.c
fs/jffs2/gc.c
fs/jffs2/ioctl.c
fs/jffs2/jffs2_fs_i.h
fs/jffs2/jffs2_fs_sb.h
fs/jffs2/nodelist.h
fs/jffs2/nodemgmt.c
fs/jffs2/readinode.c
fs/jffs2/super.c
fs/jffs2/wbuf.c
fs/jffs2/write.c
fs/lockd/svclock.c
fs/lockd/svcsubs.c
fs/locks.c
fs/namespace.c
fs/nfs/super.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfsctl.c
fs/sysfs/file.c
fs/sysfs/group.c
fs/sysfs/sysfs.h
include/asm-alpha/bitops.h
include/asm-arm/arch-pxa/irqs.h
include/asm-arm/arch-pxa/magician.h
include/asm-arm/arch-pxa/pxa3xx_nand.h [new file with mode: 0644]
include/asm-arm/arch-pxa/system.h
include/asm-arm/arch-sa1100/ide.h
include/asm-arm/plat-s3c/nand.h
include/asm-cris/arch-v10/ide.h
include/asm-generic/bitops/__fls.h [new file with mode: 0644]
include/asm-generic/bitops/find.h
include/asm-generic/bitops/fls64.h
include/asm-generic/iomap.h
include/asm-ia64/bitops.h
include/asm-ia64/gcc_intrin.h
include/asm-ia64/kvm.h
include/asm-ia64/kvm_host.h [new file with mode: 0644]
include/asm-ia64/kvm_para.h [new file with mode: 0644]
include/asm-ia64/processor.h
include/asm-mips/bitops.h
include/asm-mips/mach-au1x00/au1xxx_ide.h
include/asm-parisc/bitops.h
include/asm-powerpc/bitops.h
include/asm-powerpc/fixmap.h [new file with mode: 0644]
include/asm-powerpc/highmem.h
include/asm-powerpc/io-defs.h
include/asm-powerpc/io.h
include/asm-powerpc/kdump.h
include/asm-powerpc/kvm.h
include/asm-powerpc/kvm_asm.h [new file with mode: 0644]
include/asm-powerpc/kvm_host.h [new file with mode: 0644]
include/asm-powerpc/kvm_para.h [new file with mode: 0644]
include/asm-powerpc/kvm_ppc.h [new file with mode: 0644]
include/asm-powerpc/mmu-44x.h
include/asm-powerpc/paca.h
include/asm-powerpc/page.h
include/asm-powerpc/page_32.h
include/asm-powerpc/thread_info.h
include/asm-ppc/mmu.h
include/asm-ppc/mpc8260.h
include/asm-ppc/mpc8xx.h
include/asm-s390/Kbuild
include/asm-s390/bitops.h
include/asm-s390/kvm.h
include/asm-s390/kvm_host.h [new file with mode: 0644]
include/asm-s390/kvm_para.h [new file with mode: 0644]
include/asm-s390/kvm_virtio.h [new file with mode: 0644]
include/asm-s390/lowcore.h
include/asm-s390/mmu.h
include/asm-s390/mmu_context.h
include/asm-s390/pgtable.h
include/asm-s390/setup.h
include/asm-sh/bitops.h
include/asm-sparc64/bitops.h
include/asm-x86/bios_ebda.h
include/asm-x86/bitops.h
include/asm-x86/bitops_32.h [deleted file]
include/asm-x86/bitops_64.h [deleted file]
include/asm-x86/bootparam.h
include/asm-x86/e820_64.h
include/asm-x86/fixmap.h
include/asm-x86/fixmap_32.h
include/asm-x86/fixmap_64.h
include/asm-x86/io.h
include/asm-x86/io_32.h
include/asm-x86/io_64.h
include/asm-x86/io_apic.h
include/asm-x86/kvm.h
include/asm-x86/kvm_host.h
include/asm-x86/kvm_para.h
include/asm-x86/mach-default/smpboot_hooks.h
include/asm-x86/page.h
include/asm-x86/paravirt.h
include/asm-x86/pgalloc.h
include/asm-x86/pgalloc_32.h [deleted file]
include/asm-x86/pgalloc_64.h [deleted file]
include/asm-x86/pgtable.h
include/asm-x86/pgtable_32.h
include/asm-x86/pgtable_64.h
include/asm-x86/posix_types.h
include/asm-x86/processor.h
include/asm-x86/ptrace.h
include/asm-x86/reboot.h
include/asm-x86/rio.h
include/asm-x86/smp.h
include/asm-x86/tsc.h
include/asm-x86/unistd.h
include/asm-x86/xen/events.h [new file with mode: 0644]
include/asm-x86/xen/grant_table.h [new file with mode: 0644]
include/asm-x86/xen/hypercall.h
include/asm-x86/xen/interface.h
include/asm-x86/xen/page.h [new file with mode: 0644]
include/linux/Kbuild
include/linux/bitops.h
include/linux/bsg.h
include/linux/compiler-gcc.h
include/linux/device-mapper.h
include/linux/dm-dirty-log.h [moved from drivers/md/dm-log.h with 53% similarity]
include/linux/dm-io.h [moved from drivers/md/dm-io.h with 84% similarity]
include/linux/dm-kcopyd.h [new file with mode: 0644]
include/linux/file.h
include/linux/fs.h
include/linux/hdsmart.h [deleted file]
include/linux/ide.h
include/linux/input.h
include/linux/keyboard.h
include/linux/kvm.h
include/linux/kvm_host.h
include/linux/kvm_para.h
include/linux/kvm_types.h
include/linux/leds.h
include/linux/libata.h
include/linux/lockd/lockd.h
include/linux/mlx4/device.h
include/linux/mlx4/qp.h
include/linux/mm.h
include/linux/mtd/inftl.h
include/linux/mtd/nftl.h
include/linux/mtd/onenand.h
include/linux/mtd/plat-ram.h
include/linux/nfsd/nfsd.h
include/linux/phy.h
include/linux/sched.h
include/linux/seqlock.h
include/linux/serio.h
include/linux/spi/ads7846.h
include/linux/sysfs.h
include/linux/usb.h
include/linux/usb/audio.h
include/linux/usb/cdc.h
include/linux/usb/ch9.h
include/linux/usb/g_printer.h
include/linux/usb/gadget.h
include/linux/usb/gadgetfs.h
include/linux/usb/input.h
include/linux/usb/iowarrior.h
include/linux/usb/isp116x.h
include/linux/usb/midi.h
include/linux/usb/net2280.h
include/linux/usb/otg.h
include/linux/usb/quirks.h
include/linux/usb/rndis_host.h
include/linux/usb/serial.h
include/linux/usb/sl811.h
include/linux/usb/usbnet.h
include/linux/usb_usual.h
include/linux/usbdevice_fs.h
include/linux/wm97xx.h [new file with mode: 0644]
include/linux/xfrm.h
include/mtd/Kbuild
include/scsi/scsi_device.h
include/xen/balloon.h [new file with mode: 0644]
include/xen/events.h
include/xen/grant_table.h
include/xen/interface/callback.h [new file with mode: 0644]
include/xen/interface/grant_table.h
include/xen/interface/io/fbif.h [new file with mode: 0644]
include/xen/interface/io/kbdif.h [new file with mode: 0644]
include/xen/interface/io/protocols.h [new file with mode: 0644]
include/xen/interface/memory.h
include/xen/interface/vcpu.h
include/xen/interface/xen.h
include/xen/interface/xencomm.h [new file with mode: 0644]
include/xen/page.h
include/xen/xen-ops.h [new file with mode: 0644]
include/xen/xenbus.h
include/xen/xencomm.h [new file with mode: 0644]
init/main.c
kernel/exit.c
kernel/fork.c
kernel/sched.c
kernel/time/tick-sched.c
lib/Kconfig
lib/Kconfig.debug
lib/Makefile
lib/find_next_bit.c
mm/bootmem.c
mm/rmap.c
mm/sparse.c
net/can/raw.c
net/core/ethtool.c
net/dccp/probe.c
net/ipv4/tcp_probe.c
net/ipv6/Kconfig
net/ipv6/raw.c
net/key/af_key.c
net/mac80211/mesh.h
net/mac80211/mesh_hwmp.c
net/rxrpc/rxkad.c
net/tipc/socket.c
scripts/Makefile.build
scripts/Makefile.clean
scripts/Makefile.host
scripts/Makefile.modpost
scripts/checkpatch.pl
scripts/kconfig/Makefile
scripts/mod/modpost.c
virt/kvm/kvm_main.c
virt/kvm/kvm_trace.c [new file with mode: 0644]

index fdcce40226d7d4273a08cc4ef84bb25755a710a4..3016ed30526d4296e219d4ea9dc3ef7e23fe9f23 100644 (file)
@@ -27,6 +27,7 @@ TAGS
 vmlinux*
 !vmlinux.lds.S
 System.map
+Module.markers
 Module.symvers
 !.gitignore
 
index a82a113b4a4b1d3aa6aaf2f9815076ab4f5f2627..1977fab386566e23f501bea233f8f487d16f5c38 100644 (file)
@@ -329,8 +329,6 @@ sgi-visws.txt
        - short blurb on the SGI Visual Workstations.
 sh/
        - directory with info on porting Linux to a new architecture.
-smart-config.txt
-       - description of the Smart Config makefile feature.
 sound/
        - directory with info on sound card support.
 sparc/
diff --git a/Documentation/ABI/stable/sysfs-class-ubi b/Documentation/ABI/stable/sysfs-class-ubi
new file mode 100644 (file)
index 0000000..18d471d
--- /dev/null
@@ -0,0 +1,212 @@
+What:          /sys/class/ubi/
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               The ubi/ class sub-directory belongs to the UBI subsystem and
+               provides general UBI information, per-UBI device information
+               and per-UBI volume information.
+
+What:          /sys/class/ubi/version
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               This file contains version of the latest supported UBI on-media
+               format. Currently it is 1, and there is no plan to change this.
+               However, if in the future UBI needs on-flash format changes
+               which cannot be done in a compatible manner, a new format
+               version will be added. So this is a mechanism for possible
+               future backward-compatible (but forward-incompatible)
+               improvements.
+
+What:          /sys/class/ubiX/
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               The /sys/class/ubi0, /sys/class/ubi1, etc directories describe
+               UBI devices (UBI device 0, 1, etc). They contain general UBI
+               device information and per UBI volume information (each UBI
+               device may have many UBI volumes)
+
+What:          /sys/class/ubi/ubiX/avail_eraseblocks
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Amount of available logical eraseblock. For example, one may
+               create a new UBI volume which has this amount of logical
+               eraseblocks.
+
+What:          /sys/class/ubi/ubiX/bad_peb_count
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Count of bad physical eraseblocks on the underlying MTD device.
+
+What:          /sys/class/ubi/ubiX/bgt_enabled
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Contains ASCII "0\n" if the UBI background thread is disabled,
+               and ASCII "1\n" if it is enabled.
+
+What:          /sys/class/ubi/ubiX/dev
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Major and minor numbers of the character device corresponding
+               to this UBI device (in <major>:<minor> format).
+
+What:          /sys/class/ubi/ubiX/eraseblock_size
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Maximum logical eraseblock size this UBI device may provide. UBI
+               volumes may have smaller logical eraseblock size because of their
+               alignment.
+
+What:          /sys/class/ubi/ubiX/max_ec
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Maximum physical eraseblock erase counter value.
+
+What:          /sys/class/ubi/ubiX/max_vol_count
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Maximum number of volumes which this UBI device may have.
+
+What:          /sys/class/ubi/ubiX/min_io_size
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Minimum input/output unit size. All the I/O may only be done
+               in fractions of the contained number.
+
+What:          /sys/class/ubi/ubiX/mtd_num
+Date:          January 2008
+KernelVersion: 2.6.25
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Number of the underlying MTD device.
+
+What:          /sys/class/ubi/ubiX/reserved_for_bad
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Number of physical eraseblocks reserved for bad block handling.
+
+What:          /sys/class/ubi/ubiX/total_eraseblocks
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Total number of good (not marked as bad) physical eraseblocks on
+               the underlying MTD device.
+
+What:          /sys/class/ubi/ubiX/volumes_count
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Count of volumes on this UBI device.
+
+What:          /sys/class/ubi/ubiX/ubiX_Y/
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               The /sys/class/ubi/ubiX/ubiX_0/, /sys/class/ubi/ubiX/ubiX_1/,
+               etc directories describe UBI volumes on UBI device X (volumes
+               0, 1, etc).
+
+What:          /sys/class/ubi/ubiX/ubiX_Y/alignment
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Volume alignment - the value the logical eraseblock size of
+               this volume has to be aligned on. For example, 2048 means that
+               logical eraseblock size is multiple of 2048. In other words,
+               volume logical eraseblock size is UBI device logical eraseblock
+               size aligned to the alignment value.
+
+What:          /sys/class/ubi/ubiX/ubiX_Y/corrupted
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Contains ASCII "0\n" if the UBI volume is OK, and ASCII "1\n"
+               if it is corrupted (e.g., due to an interrupted volume update).
+
+What:          /sys/class/ubi/ubiX/ubiX_Y/data_bytes
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               The amount of data this volume contains. This value makes sense
+               only for static volumes, and for dynamic volume it equivalent
+               to the total volume size in bytes.
+
+What:          /sys/class/ubi/ubiX/ubiX_Y/dev
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Major and minor numbers of the character device corresponding
+               to this UBI volume (in <major>:<minor> format).
+
+What:          /sys/class/ubi/ubiX/ubiX_Y/name
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Volume name.
+
+What:          /sys/class/ubi/ubiX/ubiX_Y/reserved_ebs
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Count of physical eraseblock reserved for this volume.
+               Equivalent to the volume size in logical eraseblocks.
+
+What:          /sys/class/ubi/ubiX/ubiX_Y/type
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Volume type. Contains ASCII "dynamic\n" for dynamic volumes and
+               "static\n" for static volumes.
+
+What:          /sys/class/ubi/ubiX/ubiX_Y/upd_marker
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Contains ASCII "0\n" if the update marker is not set for this
+               volume, and "1\n" if it is set. The update marker is set when
+               volume update starts, and cleaned when it ends. So the presence
+               of the update marker indicates that the volume is being updated
+               at the moment of the update was interrupted. The later may be
+               checked using the "corrupted" sysfs file.
+
+What:          /sys/class/ubi/ubiX/ubiX_Y/usable_eb_size
+Date:          July 2006
+KernelVersion: 2.6.22
+Contact:       Artem Bityutskiy <dedekind@infradead.org>
+Description:
+               Logical eraseblock size of this volume. Equivalent to logical
+               eraseblock size of the device aligned on the volume alignment
+               value.
index b2b6366bba5163628d7d4e4617921dda5d442d0f..83966e94cc32308579b7b6f041c4299fad94fbd5 100644 (file)
@@ -187,8 +187,11 @@ quiet_cmd_fig2png = FIG2PNG $@
 
 ###
 # Rule to convert a .c file to inline XML documentation
+       gen_xml = :
+ quiet_gen_xml = echo '  GEN     $@'
+silent_gen_xml = :
 %.xml: %.c
-       @echo '  GEN     $@'
+       @$($(quiet)gen_xml)
        @(                            \
           echo "<programlisting>";   \
           expand --tabs=8 < $< |     \
index 54835610b3d6564945ac5be5f32077bf07626923..0291ade44c172882087b49cd6069267c12a4df3c 100644 (file)
@@ -249,9 +249,11 @@ process is as follows:
     release a new -rc kernel every week.
   - Process continues until the kernel is considered "ready", the
     process should last around 6 weeks.
-  - A list of known regressions present in each -rc release is
-    tracked at the following URI:
-    http://kernelnewbies.org/known_regressions
+  - Known regressions in each release are periodically posted to the 
+    linux-kernel mailing list.  The goal is to reduce the length of 
+    that list to zero before declaring the kernel to be "ready," but, in
+    the real world, a small number of regressions often remain at 
+    release time.
 
 It is worth mentioning what Andrew Morton wrote on the linux-kernel
 mailing list about kernel releases:
@@ -261,7 +263,7 @@ mailing list about kernel releases:
 
 2.6.x.y -stable kernel tree
 ---------------------------
-Kernels with 4 digit versions are -stable kernels. They contain
+Kernels with 4-part versions are -stable kernels. They contain
 relatively small and critical fixes for security problems or significant
 regressions discovered in a given 2.6.x kernel.
 
@@ -273,7 +275,10 @@ If no 2.6.x.y kernel is available, then the highest numbered 2.6.x
 kernel is the current stable kernel.
 
 2.6.x.y are maintained by the "stable" team <stable@kernel.org>, and are
-released almost every other week.
+released as needs dictate.  The normal release period is approximately 
+two weeks, but it can be longer if there are no pressing problems.  A
+security-related problem, instead, can cause a release to happen almost
+instantly.
 
 The file Documentation/stable_kernel_rules.txt in the kernel tree
 documents what kinds of changes are acceptable for the -stable tree, and
@@ -298,7 +303,9 @@ a while Andrew or the subsystem maintainer pushes it on to Linus for
 inclusion in mainline.
 
 It is heavily encouraged that all new patches get tested in the -mm tree
-before they are sent to Linus for inclusion in the main kernel tree.
+before they are sent to Linus for inclusion in the main kernel tree.  Code
+which does not make an appearance in -mm before the opening of the merge
+window will prove hard to merge into the mainline.
 
 These kernels are not appropriate for use on systems that are supposed
 to be stable and they are more risky to run than any of the other
@@ -354,11 +361,12 @@ Here is a list of some of the different kernel trees available:
     - SCSI, James Bottomley <James.Bottomley@SteelEye.com>
        git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
 
+    - x86, Ingo Molnar <mingo@elte.hu>
+       git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git
+
   quilt trees:
-    - USB, PCI, Driver Core, and I2C, Greg Kroah-Hartman <gregkh@suse.de>
+    - USB, Driver Core, and I2C, Greg Kroah-Hartman <gregkh@suse.de>
        kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
-    - x86-64, partly i386, Andi Kleen <ak@suse.de>
-        ftp.firstfloor.org:/pub/ak/x86_64/quilt/
 
   Other kernel trees can be found listed at http://git.kernel.org/ and in
   the MAINTAINERS file.
@@ -392,8 +400,8 @@ If you want to be advised of the future bug reports, you can subscribe to the
 bugme-new mailing list (only new bug reports are mailed here) or to the
 bugme-janitor mailing list (every change in the bugzilla is mailed here)
 
-       http://lists.osdl.org/mailman/listinfo/bugme-new
-       http://lists.osdl.org/mailman/listinfo/bugme-janitors
+       http://lists.linux-foundation.org/mailman/listinfo/bugme-new
+       http://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
 
 
 
diff --git a/Documentation/arm/Samsung-S3C24XX/NAND.txt b/Documentation/arm/Samsung-S3C24XX/NAND.txt
new file mode 100644 (file)
index 0000000..bc478a3
--- /dev/null
@@ -0,0 +1,30 @@
+                       S3C24XX NAND Support
+                       ====================
+
+Introduction
+------------
+
+Small Page NAND
+---------------
+
+The driver uses a 512 byte (1 page) ECC code for this setup. The
+ECC code is not directly compatible with the default kernel ECC
+code, so the driver enforces its own OOB layout and ECC parameters
+
+Large Page NAND
+---------------
+
+The driver is capable of handling NAND flash with a 2KiB page
+size, with support for hardware ECC generation and correction.
+
+Unlike the 512byte page mode, the driver generates ECC data for
+each 256 byte block in an 2KiB page. This means that more than
+one error in a page can be rectified. It also means that the
+OOB layout remains the default kernel layout for these flashes.
+
+
+Document Author
+---------------
+
+Ben Dooks, Copyright 2007 Simtec Electronics
+
index c31b76fa66c462601a92054221baea08643057da..d04e1e30c47f8ff1a8613a369506e58cf5a41a21 100644 (file)
@@ -156,6 +156,8 @@ NAND
   controller. If there are any problems the latest linux-mtd
   code can be found from http://www.linux-mtd.infradead.org/
 
+  For more information see Documentation/arm/Samsung-S3C24XX/NAND.txt
+
 
 Serial
 ------
diff --git a/Documentation/device-mapper/dm-crypt.txt b/Documentation/device-mapper/dm-crypt.txt
new file mode 100644 (file)
index 0000000..6680cab
--- /dev/null
@@ -0,0 +1,52 @@
+dm-crypt
+=========
+
+Device-Mapper's "crypt" target provides transparent encryption of block devices
+using the kernel crypto API.
+
+Parameters: <cipher> <key> <iv_offset> <device path> <offset>
+
+<cipher>
+    Encryption cipher and an optional IV generation mode.
+    (In format cipher-chainmode-ivopts:ivmode).
+    Examples:
+       des
+       aes-cbc-essiv:sha256
+       twofish-ecb
+
+    /proc/crypto contains supported crypto modes
+
+<key>
+    Key used for encryption. It is encoded as a hexadecimal number.
+    You can only use key sizes that are valid for the selected cipher.
+
+<iv_offset>
+    The IV offset is a sector count that is added to the sector number
+    before creating the IV.
+
+<device path>
+    This is the device that is going to be used as backend and contains the
+    encrypted data.  You can specify it as a path like /dev/xxx or a device
+    number <major>:<minor>.
+
+<offset>
+    Starting sector within the device where the encrypted data begins.
+
+Example scripts
+===============
+LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
+encryption with dm-crypt using the 'cryptsetup' utility, see
+http://luks.endorphin.org/
+
+[[
+#!/bin/sh
+# Create a crypt device using dmsetup
+dmsetup create crypt1 --table "0 `blockdev --getsize $1` crypt aes-cbc-essiv:sha256 babebabebabebabebabebabebabebabe 0 $1 0"
+]]
+
+[[
+#!/bin/sh
+# Create a crypt device using cryptsetup and LUKS header with default cipher
+cryptsetup luksFormat $1
+cryptsetup luksOpen $1 crypt1
+]]
index 1ae34879574b6c616f9de8f1c15851096772502e..d0ec45ae4e7dfa4585fa74c0757be4d80dc02bf5 100644 (file)
@@ -5,7 +5,7 @@
 ################################################################################
 
  Author: NetApp and Open Grid Computing
- Date: February 25, 2008
+ Date: April 15, 2008
 
 Table of Contents
 ~~~~~~~~~~~~~~~~~
@@ -197,12 +197,16 @@ NFS/RDMA Setup
   - On the server system, configure the /etc/exports file and
     start the NFS/RDMA server.
 
-    Exports entries with the following format have been tested:
+    Exports entries with the following formats have been tested:
 
-    /vol0   10.97.103.47(rw,async) 192.168.0.47(rw,async,insecure,no_root_squash)
+    /vol0   192.168.0.47(fsid=0,rw,async,insecure,no_root_squash)
+    /vol0   192.168.0.0/255.255.255.0(fsid=0,rw,async,insecure,no_root_squash)
 
-    Here the first IP address is the client's Ethernet address and the second
-    IP address is the clients IPoIB address.
+    The IP address(es) is(are) the client's IPoIB address for an InfiniBand HCA or the
+    cleint's iWARP address(es) for an RNIC.
+
+    NOTE: The "insecure" option must be used because the NFS/RDMA client does not
+    use a reserved port.
 
  Each time a machine boots:
 
index 7fb8e6dc62bfb596032725264c3b911a0cca2b2b..b843743aa0b5928630771a0ba6e22ec65c206654 100644 (file)
@@ -122,8 +122,7 @@ stop() is the place to free it.
        }
 
 Finally, the show() function should format the object currently pointed to
-by the iterator for output. It should return zero, or an error code if
-something goes wrong. The example module's show() function is:
+by the iterator for output.  The example module's show() function is:
 
        static int ct_seq_show(struct seq_file *s, void *v)
        {
@@ -132,6 +131,12 @@ something goes wrong. The example module's show() function is:
                return 0;
        }
 
+If all is well, the show() function should return zero.  A negative error
+code in the usual manner indicates that something went wrong; it will be
+passed back to user space.  This function can also return SEQ_SKIP, which
+causes the current item to be skipped; if the show() function has already
+generated output before returning SEQ_SKIP, that output will be dropped.
+
 We will look at seq_printf() in a moment. But first, the definition of the
 seq_file iterator is finished by creating a seq_operations structure with
 the four functions we have just defined:
@@ -182,12 +187,18 @@ The first two output a single character and a string, just like one would
 expect. seq_escape() is like seq_puts(), except that any character in s
 which is in the string esc will be represented in octal form in the output.
 
-There is also a function for printing filenames:
+There is also a pair of functions for printing filenames:
 
        int seq_path(struct seq_file *m, struct path *path, char *esc);
+       int seq_path_root(struct seq_file *m, struct path *path,
+                         struct path *root, char *esc)
 
 Here, path indicates the file of interest, and esc is a set of characters
-which should be escaped in the output.
+which should be escaped in the output.  A call to seq_path() will output
+the path relative to the current process's filesystem root.  If a different
+root is desired, it can be used with seq_path_root().  Note that, if it
+turns out that path cannot be reached from root, the value of root will be
+changed in seq_file_root() to a root which *does* work.
 
 
 Making it all work
index 2eb16100bb3fef7658799f5f7f4d259be644b537..0fac3465f2e38e5612a31cfa83e83cdcad95e83e 100644 (file)
@@ -42,6 +42,8 @@ Protocol 2.05:        (Kernel 2.6.20) Make protected mode kernel relocatable.
 Protocol 2.06: (Kernel 2.6.22) Added a field that contains the size of
                the boot command line
 
+Protocol 2.09: (kernel 2.6.26) Added a field of 64-bit physical
+               pointer to single linked list of struct setup_data.
 
 **** MEMORY LAYOUT
 
@@ -172,6 +174,8 @@ Offset      Proto   Name            Meaning
 0240/8 2.07+   hardware_subarch_data Subarchitecture-specific data
 0248/4 2.08+   payload_offset  Offset of kernel payload
 024C/4 2.08+   payload_length  Length of kernel payload
+0250/8 2.09+   setup_data      64-bit physical pointer to linked list
+                               of struct setup_data
 
 (1) For backwards compatibility, if the setup_sects field contains 0, the
     real value is 4.
@@ -572,6 +576,28 @@ command line is entered using the following protocol:
        covered by setup_move_size, so you may need to adjust this
        field.
 
+Field name:    setup_data
+Type:          write (obligatory)
+Offset/size:   0x250/8
+Protocol:      2.09+
+
+  The 64-bit physical pointer to NULL terminated single linked list of
+  struct setup_data. This is used to define a more extensible boot
+  parameters passing mechanism. The definition of struct setup_data is
+  as follow:
+
+  struct setup_data {
+         u64 next;
+         u32 type;
+         u32 len;
+         u8  data[0];
+  };
+
+  Where, the next is a 64-bit physical pointer to the next node of
+  linked list, the next field of the last node is 0; the type is used
+  to identify the contents of data; the len is the length of data
+  field; the data holds the real payload.
+
 
 **** MEMORY LAYOUT OF THE REAL-MODE CODE
 
diff --git a/Documentation/ia64/kvm.txt b/Documentation/ia64/kvm.txt
new file mode 100644 (file)
index 0000000..bec9d81
--- /dev/null
@@ -0,0 +1,82 @@
+Currently, kvm module in EXPERIMENTAL stage on IA64. This means that
+interfaces are not stable enough to use. So, plase had better don't run
+critical applications in virtual machine. We will try our best to make it
+strong in future versions!
+                               Guide: How to boot up guests on kvm/ia64
+
+This guide is to describe how to enable kvm support for IA-64 systems.
+
+1. Get the kvm source from git.kernel.org.
+       Userspace source:
+               git clone git://git.kernel.org/pub/scm/virt/kvm/kvm-userspace.git
+       Kernel Source:
+               git clone git://git.kernel.org/pub/scm/linux/kernel/git/xiantao/kvm-ia64.git
+
+2. Compile the source code.
+       2.1 Compile userspace code:
+               (1)cd ./kvm-userspace
+               (2)./configure
+               (3)cd kernel
+               (4)make sync LINUX= $kernel_dir (kernel_dir is the directory of kernel source.)
+               (5)cd ..
+               (6)make qemu
+               (7)cd qemu; make install
+
+       2.2 Compile kernel source code:
+               (1) cd ./$kernel_dir
+               (2) Make menuconfig
+               (3) Enter into virtualization option, and choose kvm.
+               (4) make
+               (5) Once (4) done, make modules_install
+               (6) Make initrd, and use new kernel to reboot up host machine.
+               (7) Once (6) done, cd $kernel_dir/arch/ia64/kvm
+               (8) insmod kvm.ko; insmod kvm-intel.ko
+
+Note: For step 2, please make sure that host page size == TARGET_PAGE_SIZE of qemu, otherwise, may fail.
+
+3. Get Guest Firmware named as Flash.fd, and put it under right place:
+       (1) If you have the guest firmware (binary) released by Intel Corp for Xen, use it directly.
+
+       (2) If you have no firmware at hand, Please download its source from
+               hg clone http://xenbits.xensource.com/ext/efi-vfirmware.hg
+           you can get the firmware's binary in the directory of efi-vfirmware.hg/binaries.
+
+       (3) Rename the firware you owned to Flash.fd, and copy it to /usr/local/share/qemu
+
+4. Boot up Linux or Windows guests:
+       4.1 Create or install a image for guest boot. If you have xen experience, it should be easy.
+
+       4.2 Boot up guests use the following command.
+               /usr/local/bin/qemu-system-ia64 -smp xx -m 512 -hda $your_image
+               (xx is the number of virtual processors for the guest, now the maximum value is 4)
+
+5. Known possibile issue on some platforms with old Firmware.
+
+If meet strange host crashe issues, try to solve it through either of the following ways:
+
+(1): Upgrade your Firmware to the latest one.
+
+(2): Applying the below patch to kernel source.
+diff --git a/arch/ia64/kernel/pal.S b/arch/ia64/kernel/pal.S
+index 0b53344..f02b0f7 100644
+--- a/arch/ia64/kernel/pal.S
++++ b/arch/ia64/kernel/pal.S
+@@ -84,7 +84,8 @@ GLOBAL_ENTRY(ia64_pal_call_static)
+       mov ar.pfs = loc1
+       mov rp = loc0
+       ;;
+-      srlz.d                          // seralize restoration of psr.l
++      srlz.i                  // seralize restoration of psr.l
++      ;;
+       br.ret.sptk.many b0
+ END(ia64_pal_call_static)
+
+6. Bug report:
+       If you found any issues when use kvm/ia64, Please post the bug info to kvm-ia64-devel mailing list.
+       https://lists.sourceforge.net/lists/listinfo/kvm-ia64-devel/
+
+Thanks for your interest! Let's work together, and make kvm/ia64 stronger and stronger!
+
+
+                                                               Xiantao Zhang <xiantao.zhang@intel.com>
+                                                                                       2008.3.10
index 658f271a373fca8c57dc50a32dc04ad494250fcf..3f348a0b21d83e4f9354d90d47ca61b221543fad 100644 (file)
-/*
- * IDE ATAPI streaming tape driver.
- *
- * This driver is a part of the Linux ide driver.
- *
- * The driver, in co-operation with ide.c, basically traverses the
- * request-list for the block device interface. The character device
- * interface, on the other hand, creates new requests, adds them
- * to the request-list of the block device, and waits for their completion.
- *
- * Pipelined operation mode is now supported on both reads and writes.
- *
- * The block device major and minor numbers are determined from the
- * tape's relative position in the ide interfaces, as explained in ide.c.
- *
- * The character device interface consists of the following devices:
- *
- * ht0         major 37, minor 0       first  IDE tape, rewind on close.
- * ht1         major 37, minor 1       second IDE tape, rewind on close.
- * ...
- * nht0                major 37, minor 128     first  IDE tape, no rewind on close.
- * nht1                major 37, minor 129     second IDE tape, no rewind on close.
- * ...
- *
- * The general magnetic tape commands compatible interface, as defined by
- * include/linux/mtio.h, is accessible through the character device.
- *
- * General ide driver configuration options, such as the interrupt-unmask
- * flag, can be configured by issuing an ioctl to the block device interface,
- * as any other ide device.
- *
- * Our own ide-tape ioctl's can be issued to either the block device or
- * the character device interface.
- *
- * Maximal throughput with minimal bus load will usually be achieved in the
- * following scenario:
- *
- *     1.      ide-tape is operating in the pipelined operation mode.
- *     2.      No buffering is performed by the user backup program.
- *
- * Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive.
- *
- * Here are some words from the first releases of hd.c, which are quoted
- * in ide.c and apply here as well:
- *
- * | Special care is recommended.  Have Fun!
- *
- *
- * An overview of the pipelined operation mode.
- *
- * In the pipelined write mode, we will usually just add requests to our
- * pipeline and return immediately, before we even start to service them. The
- * user program will then have enough time to prepare the next request while
- * we are still busy servicing previous requests. In the pipelined read mode,
- * the situation is similar - we add read-ahead requests into the pipeline,
- * before the user even requested them.
- *
- * The pipeline can be viewed as a "safety net" which will be activated when
- * the system load is high and prevents the user backup program from keeping up
- * with the current tape speed. At this point, the pipeline will get
- * shorter and shorter but the tape will still be streaming at the same speed.
- * Assuming we have enough pipeline stages, the system load will hopefully
- * decrease before the pipeline is completely empty, and the backup program
- * will be able to "catch up" and refill the pipeline again.
- *
- * When using the pipelined mode, it would be best to disable any type of
- * buffering done by the user program, as ide-tape already provides all the
- * benefits in the kernel, where it can be done in a more efficient way.
- * As we will usually not block the user program on a request, the most
- * efficient user code will then be a simple read-write-read-... cycle.
- * Any additional logic will usually just slow down the backup process.
- *
- * Using the pipelined mode, I get a constant over 400 KBps throughput,
- * which seems to be the maximum throughput supported by my tape.
- *
- * However, there are some downfalls:
- *
- *     1.      We use memory (for data buffers) in proportional to the number
- *             of pipeline stages (each stage is about 26 KB with my tape).
- *     2.      In the pipelined write mode, we cheat and postpone error codes
- *             to the user task. In read mode, the actual tape position
- *             will be a bit further than the last requested block.
- *
- * Concerning (1):
- *
- *     1.      We allocate stages dynamically only when we need them. When
- *             we don't need them, we don't consume additional memory. In
- *             case we can't allocate stages, we just manage without them
- *             (at the expense of decreased throughput) so when Linux is
- *             tight in memory, we will not pose additional difficulties.
- *
- *     2.      The maximum number of stages (which is, in fact, the maximum
- *             amount of memory) which we allocate is limited by the compile
- *             time parameter IDETAPE_MAX_PIPELINE_STAGES.
- *
- *     3.      The maximum number of stages is a controlled parameter - We
- *             don't start from the user defined maximum number of stages
- *             but from the lower IDETAPE_MIN_PIPELINE_STAGES (again, we
- *             will not even allocate this amount of stages if the user
- *             program can't handle the speed). We then implement a feedback
- *             loop which checks if the pipeline is empty, and if it is, we
- *             increase the maximum number of stages as necessary until we
- *             reach the optimum value which just manages to keep the tape
- *             busy with minimum allocated memory or until we reach
- *             IDETAPE_MAX_PIPELINE_STAGES.
- *
- * Concerning (2):
- *
- *     In pipelined write mode, ide-tape can not return accurate error codes
- *     to the user program since we usually just add the request to the
- *      pipeline without waiting for it to be serviced. In case an error
- *      occurs, I will report it on the next user request.
- *
- *     In the pipelined read mode, subsequent read requests or forward
- *     filemark spacing will perform correctly, as we preserve all blocks
- *     and filemarks which we encountered during our excess read-ahead.
- *
- *     For accurate tape positioning and error reporting, disabling
- *     pipelined mode might be the best option.
- *
- * You can enable/disable/tune the pipelined operation mode by adjusting
- * the compile time parameters below.
- *
- *
- *     Possible improvements.
- *
- *     1.      Support for the ATAPI overlap protocol.
- *
- *             In order to maximize bus throughput, we currently use the DSC
- *             overlap method which enables ide.c to service requests from the
- *             other device while the tape is busy executing a command. The
- *             DSC overlap method involves polling the tape's status register
- *             for the DSC bit, and servicing the other device while the tape
- *             isn't ready.
- *
- *             In the current QIC development standard (December 1995),
- *             it is recommended that new tape drives will *in addition*
- *             implement the ATAPI overlap protocol, which is used for the
- *             same purpose - efficient use of the IDE bus, but is interrupt
- *             driven and thus has much less CPU overhead.
- *
- *             ATAPI overlap is likely to be supported in most new ATAPI
- *             devices, including new ATAPI cdroms, and thus provides us
- *             a method by which we can achieve higher throughput when
- *             sharing a (fast) ATA-2 disk with any (slow) new ATAPI device.
- */
+IDE ATAPI streaming tape driver.
+
+This driver is a part of the Linux ide driver.
+
+The driver, in co-operation with ide.c, basically traverses the
+request-list for the block device interface. The character device
+interface, on the other hand, creates new requests, adds them
+to the request-list of the block device, and waits for their completion.
+
+The block device major and minor numbers are determined from the
+tape's relative position in the ide interfaces, as explained in ide.c.
+
+The character device interface consists of the following devices:
+
+ht0            major 37, minor 0       first  IDE tape, rewind on close.
+ht1            major 37, minor 1       second IDE tape, rewind on close.
+...
+nht0           major 37, minor 128     first  IDE tape, no rewind on close.
+nht1           major 37, minor 129     second IDE tape, no rewind on close.
+...
+
+The general magnetic tape commands compatible interface, as defined by
+include/linux/mtio.h, is accessible through the character device.
+
+General ide driver configuration options, such as the interrupt-unmask
+flag, can be configured by issuing an ioctl to the block device interface,
+as any other ide device.
+
+Our own ide-tape ioctl's can be issued to either the block device or
+the character device interface.
+
+Maximal throughput with minimal bus load will usually be achieved in the
+following scenario:
+
+     1.        ide-tape is operating in the pipelined operation mode.
+     2.        No buffering is performed by the user backup program.
+
+Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive.
+
+Here are some words from the first releases of hd.c, which are quoted
+in ide.c and apply here as well:
+
+| Special care is recommended.  Have Fun!
+
+Possible improvements:
+
+1. Support for the ATAPI overlap protocol.
+
+In order to maximize bus throughput, we currently use the DSC
+overlap method which enables ide.c to service requests from the
+other device while the tape is busy executing a command. The
+DSC overlap method involves polling the tape's status register
+for the DSC bit, and servicing the other device while the tape
+isn't ready.
+
+In the current QIC development standard (December 1995),
+it is recommended that new tape drives will *in addition*
+implement the ATAPI overlap protocol, which is used for the
+same purpose - efficient use of the IDE bus, but is interrupt
+driven and thus has much less CPU overhead.
+
+ATAPI overlap is likely to be supported in most new ATAPI
+devices, including new ATAPI cdroms, and thus provides us
+a method by which we can achieve higher throughput when
+sharing a (fast) ATA-2 disk with any (slow) new ATAPI device.
index 486c699f4aea4722bb822a7af7ad12053f5c321c..0c78f4b1d9d9f1df5298e9147c058a32aee90353 100644 (file)
@@ -82,27 +82,26 @@ Drives are normally found by auto-probing and/or examining the CMOS/BIOS data.
 For really weird situations, the apparent (fdisk) geometry can also be specified
 on the kernel "command line" using LILO.  The format of such lines is:
 
-       hdx=cyls,heads,sects
-or     hdx=cdrom
+       ide_core.chs=[interface_number.device_number]:cyls,heads,sects
+or     ide_core.cdrom=[interface_number.device_number]
 
-where hdx can be any of hda through hdh, Three values are required
-(cyls,heads,sects).  For example:
+For example:
 
-       hdc=1050,32,64  hdd=cdrom
+       ide_core.chs=1.0:1050,32,64  ide_core.cdrom=1.1
 
-either {hda,hdb} or {hdc,hdd}.  The results of successful auto-probing may
-override the physical geometry/irq specified, though the "original" geometry
-may be retained as the "logical" geometry for partitioning purposes (fdisk).
+The results of successful auto-probing may override the physical geometry/irq
+specified, though the "original" geometry may be retained as the "logical"
+geometry for partitioning purposes (fdisk).
 
 If the auto-probing during boot time confuses a drive (ie. the drive works
 with hd.c but not with ide.c), then an command line option may be specified
 for each drive for which you'd like the drive to skip the hardware
 probe/identification sequence.  For example:
 
-       hdb=noprobe
+       ide_core.noprobe=0.1
 or
-       hdc=768,16,32
-       hdc=noprobe
+       ide_core.chs=1.0:768,16,32
+       ide_core.noprobe=1.0
 
 Note that when only one IDE device is attached to an interface, it should be
 jumpered as "single" or "master", *not* "slave".  Many folks have had
@@ -118,9 +117,9 @@ If for some reason your cdrom drive is *not* found at boot time, you can force
 the probe to look harder by supplying a kernel command line parameter
 via LILO, such as:
 
-       hdc=cdrom       /* hdc = "master" on second interface */
+       ide_core.cdrom=1.0      /* "master" on second interface (hdc) */
 or
-       hdd=cdrom       /* hdd = "slave" on second interface */
+       ide_core.cdrom=1.1      /* "slave" on second interface (hdd) */
 
 For example, a GW2000 system might have a hard drive on the primary
 interface (/dev/hda) and an IDE cdrom drive on the secondary interface
@@ -174,9 +173,7 @@ to /etc/modprobe.conf.
 
 When ide.c is used as a module, you can pass command line parameters to the
 driver using the "options=" keyword to insmod, while replacing any ',' with
-';'.  For example:
-
-       insmod ide.o options="hda=nodma hdb=nodma"
+';'.
 
 
 ================================================================================
@@ -184,57 +181,6 @@ driver using the "options=" keyword to insmod, while replacing any ',' with
 Summary of ide driver parameters for kernel command line
 --------------------------------------------------------
 
- "hdx="  is recognized for all "x" from "a" to "u", such as "hdc".
-
- "idex=" is recognized for all "x" from "0" to "9", such as "ide1".
-
- "hdx=noprobe"         : drive may be present, but do not probe for it
-
- "hdx=none"            : drive is NOT present, ignore cmos and do not probe
-
- "hdx=nowerr"          : ignore the WRERR_STAT bit on this drive
-
- "hdx=cdrom"           : drive is present, and is a cdrom drive
-
- "hdx=cyl,head,sect"   : disk drive is present, with specified geometry
-
- "hdx=autotune"                : driver will attempt to tune interface speed
-                         to the fastest PIO mode supported,
-                         if possible for this drive only.
-                         Not fully supported by all chipset types,
-                         and quite likely to cause trouble with
-                         older/odd IDE drives.
-
- "hdx=nodma"           : disallow DMA
-
- "idebus=xx"           : inform IDE driver of VESA/PCI bus speed in MHz,
-                         where "xx" is between 20 and 66 inclusive,
-                         used when tuning chipset PIO modes.
-                         For PCI bus, 25 is correct for a P75 system,
-                         30 is correct for P90,P120,P180 systems,
-                         and 33 is used for P100,P133,P166 systems.
-                         If in doubt, use idebus=33 for PCI.
-                         As for VLB, it is safest to not specify it.
-                         Bigger values are safer than smaller ones.
-
- "idex=serialize"      : do not overlap operations on idex. Please note
-                         that you will have to specify this option for
-                         both the respective primary and secondary channel
-                         to take effect.
-
- "idex=reset"          : reset interface after probe
-
- "idex=ata66"          : informs the interface that it has an 80c cable
-                         for chipsets that are ATA-66 capable, but the
-                         ability to bit test for detection is currently
-                         unknown.
-
- "ide=doubler"         : probe/support IDE doublers on Amiga
-
-There may be more options than shown -- use the source, Luke!
-
-Everything else is rejected with a "BAD OPTION" message.
-
 For legacy IDE VLB host drivers (ali14xx/dtc2278/ht6560b/qd65xx/umc8672)
 you need to explicitly enable probing by using "probe" kernel parameter,
 i.e. to enable probing for ALI M14xx chipsets (ali14xx host driver) use:
@@ -251,6 +197,33 @@ are detected automatically).
 You also need to use "probe" kernel parameter for ide-4drives driver
 (support for IDE generic chipset with four drives on one port).
 
+To enable support for IDE doublers on Amiga use "doubler" kernel parameter
+for gayle host driver (i.e. "gayle.doubler" if the driver is built-in).
+
+To force ignoring cable detection (this should be needed only if you're using
+short 40-wires cable which cannot be automatically detected - if this is not
+a case please report it as a bug instead) use "ignore_cable" kernel parameter:
+
+* "ide_core.ignore_cable=[interface_number]" boot option if IDE is built-in
+  (i.e. "ide_core.ignore_cable=1" to force ignoring cable for "ide1")
+
+* "ignore_cable=[interface_number]" module parameter (for ide_core module)
+  if IDE is compiled as module
+
+Other kernel parameters for ide_core are:
+
+* "nodma=[interface_number.device_number]" to disallow DMA for a device
+
+* "noflush=[interface_number.device_number]" to disable flush requests
+
+* "noprobe=[interface_number.device_number]" to skip probing
+
+* "nowerr=[interface_number.device_number]" to ignore the WRERR_STAT bit
+
+* "cdrom=[interface_number.device_number]" to force device as a CD-ROM
+
+* "chs=[interface_number.device_number]" to force device as a disk (using CHS)
+
 ================================================================================
 
 Some Terminology
index c18363bd8d11b1f8b3c725c7c12639568033a115..240ce7a56c40c9edfd141468ef2f2f1cf40dfab5 100644 (file)
@@ -183,6 +183,8 @@ Code        Seq#    Include File            Comments
 0xAC   00-1F   linux/raw.h
 0xAD   00      Netfilter device        in development:
                                        <mailto:rusty@rustcorp.com.au>  
+0xAE   all     linux/kvm.h             Kernel-based Virtual Machine
+                                       <mailto:kvm-devel@lists.sourceforge.net>
 0xB0   all     RATIO devices           in development:
                                        <mailto:vgo@ratio.de>
 0xB1   00-1F   PPPoX                   <mailto:mostrows@styx.uwaterloo.ca>
index 1d247d59ad56fd57254c3bc5ec5e8c7b3291ed58..1821c077b435cd64eac847dc1ec69d5386dc6ad6 100644 (file)
@@ -486,7 +486,7 @@ Module.symvers contains a list of all exported symbols from a kernel build.
        Sometimes, an external module uses exported symbols from another
        external module. Kbuild needs to have full knowledge on all symbols
        to avoid spitting out warnings about undefined symbols.
-       Two solutions exist to let kbuild know all symbols of more than
+       Three solutions exist to let kbuild know all symbols of more than
        one external module.
        The method with a top-level kbuild file is recommended but may be
        impractical in certain situations.
@@ -523,6 +523,13 @@ Module.symvers contains a list of all exported symbols from a kernel build.
                containing the sum of all symbols defined and not part of the
                kernel.
 
+       Use make variable KBUILD_EXTRA_SYMBOLS in the Makefile
+               If it is impractical to copy Module.symvers from another
+               module, you can assign a space separated list of files to
+               KBUILD_EXTRA_SYMBOLS in your Makfile. These files will be
+               loaded by modpost during the initialisation of its symbol
+               tables.
+
 === 8. Tips & Tricks
 
 --- 8.1 Testing for CONFIG_FOO_BAR
index bf6303ec0bde4784b71370457eb8510c6198ed05..e5f3d918316f5d421cafc88da6b9baf005c929ac 100644 (file)
@@ -772,10 +772,6 @@ and is between 256 and 4096 characters. It is defined in the file
                        Format: ide=nodma or ide=doubler
                        See Documentation/ide/ide.txt.
 
-       ide?=           [HW] (E)IDE subsystem
-                       Format: ide?=ata66 or chipset specific parameters.
-                       See Documentation/ide/ide.txt.
-
        idebus=         [HW] (E)IDE subsystem - VLB/PCI bus speed
                        See Documentation/ide/ide.txt.
 
index 56757c751d6fc5611b181f6d79302a195b3fe8c7..18860ad9935a7876746c00660f36b9fd90529499 100644 (file)
@@ -19,6 +19,12 @@ optimises away.
 
 Complex triggers whilst available to all LEDs have LED specific
 parameters and work on a per LED basis. The timer trigger is an example.
+The timer trigger will periodically change the LED brightness between
+LED_OFF and the current brightness setting. The "on" and "off" time can
+be specified via /sys/class/leds/<device>/delay_{on,off} in milliseconds.
+You can change the brightness value of a LED independently of the timer
+trigger. However, if you set the brightness value to LED_OFF it will
+also disable the timer trigger.
 
 You can change triggers in a similar manner to the way an IO scheduler
 is chosen (via /sys/class/leds/<device>/trigger). Trigger specific
@@ -63,9 +69,9 @@ value if it is called with *delay_on==0 && *delay_off==0 parameters. In
 this case the driver should give back the chosen value through delay_on
 and delay_off parameters to the leds subsystem.
 
-Any call to the brightness_set() callback function should cancel the
-previously programmed hardware blinking function so setting the brightness
-to 0 can also cancel the blinking of the LED.
+Setting the brightness to zero with brightness_set() callback function
+should completely turn off the LED and cancel the previously programmed
+hardware blinking function, if any.
 
 
 Known Issues
index 5c8334123f4f7b6f29d41c6129ecd511a7e03d10..25a6ed1aaa5b1e3e7aa2e774a7beab34f78001f9 100644 (file)
@@ -46,8 +46,6 @@ Two files are introduced:
 
   a) 'include/asm-mips/mach-au1x00/au1xxx_ide.h'
      containes : struct _auide_hwif
-                 struct drive_list_entry dma_white_list
-                 struct drive_list_entry dma_black_list
                  timing parameters for PIO mode 0/1/2/3/4
                  timing parameters for MWDMA 0/1/2
 
@@ -63,12 +61,6 @@ Four configs variables are introduced:
   CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ - maximum transfer size
                                            per descriptor
 
-If MWDMA is enabled and the connected hard disc is not on the white list, the
-kernel switches to a "safe mwdma mode" at boot time. In this mode the IDE
-performance is substantial slower then in full speed mwdma. In this case
-please add your hard disc to the white list (follow instruction from 'ADD NEW
-HARD DISC TO WHITE OR BLACK LIST' section).
-
 
 SUPPORTED IDE MODES
 -------------------
@@ -120,44 +112,6 @@ CONFIG_IDEDMA_AUTO=y
 Also undefine 'IDE_AU1XXX_BURSTMODE' in 'drivers/ide/mips/au1xxx-ide.c' to
 disable the burst support on DBDMA controller.
 
-ADD NEW HARD DISC TO WHITE OR BLACK LIST
-----------------------------------------
-
-Step 1 : detect the model name of your hard disc
-
-  a) connect your hard disc to the AU1XXX
-
-  b) boot your kernel and get the hard disc model.
-
-     Example boot log:
-
-     --snipped--
-     Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2
-     ide: Assuming 50MHz system bus speed for PIO modes; override with idebus=xx
-     Au1xxx IDE(builtin) configured for MWDMA2
-     Probing IDE interface ide0...
-     hda: Maxtor 6E040L0, ATA DISK drive
-     ide0 at 0xac800000-0xac800007,0xac8001c0 on irq 64
-     hda: max request size: 64KiB
-     hda: 80293248 sectors (41110 MB) w/2048KiB Cache, CHS=65535/16/63, (U)DMA
-     --snipped--
-
-     In this example 'Maxtor 6E040L0'.
-
-Step  2 : edit 'include/asm-mips/mach-au1x00/au1xxx_ide.h'
-
-  Add your hard disc to the dma_white_list or dma_black_list structur.
-
-Step 3 : Recompile the kernel
-
-  Enable MWDMA support in the kernel configuration. Recompile the kernel and
-  reboot.
-
-Step 4 : Tests
-
-  If you have add a hard disc to the white list, please run some stress tests
-  for verification.
-
 
 ACKNOWLEDGMENTS
 ---------------
index 0bc95eab151288d5ba11c2bca8fdc24c2d0c56c8..8df6a7b0e66cdfd3b1de96ed038a062b71be8008 100644 (file)
@@ -1,7 +1,7 @@
 
 -------
 PHY Abstraction Layer
-(Updated 2006-11-30)
+(Updated 2008-04-08)
 
 Purpose
 
@@ -291,3 +291,39 @@ Writing a PHY driver
  Feel free to look at the Marvell, Cicada, and Davicom drivers in
  drivers/net/phy/ for examples (the lxt and qsemi drivers have
  not been tested as of this writing)
+
+Board Fixups
+
+ Sometimes the specific interaction between the platform and the PHY requires
+ special handling.  For instance, to change where the PHY's clock input is,
+ or to add a delay to account for latency issues in the data path.  In order
+ to support such contingencies, the PHY Layer allows platform code to register
+ fixups to be run when the PHY is brought up (or subsequently reset).
+
+ When the PHY Layer brings up a PHY it checks to see if there are any fixups
+ registered for it, matching based on UID (contained in the PHY device's phy_id
+ field) and the bus identifier (contained in phydev->dev.bus_id).  Both must
+ match, however two constants, PHY_ANY_ID and PHY_ANY_UID, are provided as
+ wildcards for the bus ID and UID, respectively.
+
+ When a match is found, the PHY layer will invoke the run function associated
+ with the fixup.  This function is passed a pointer to the phy_device of
+ interest.  It should therefore only operate on that PHY.
+
+ The platform code can either register the fixup using phy_register_fixup():
+
+       int phy_register_fixup(const char *phy_id,
+               u32 phy_uid, u32 phy_uid_mask,
+               int (*run)(struct phy_device *));
+
+ Or using one of the two stubs, phy_register_fixup_for_uid() and
+ phy_register_fixup_for_id():
+
+ int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
+               int (*run)(struct phy_device *));
+ int phy_register_fixup_for_id(const char *phy_id,
+               int (*run)(struct phy_device *));
+
+ The stubs set one of the two matching criteria, and set the other one to
+ match anything.
+
index 4cc780024e6c81b02cb3ccc6720655da85e33064..cf89e8cfd5bfe1ce59632dad01f374a78c9d6c88 100644 (file)
@@ -2601,6 +2601,17 @@ platforms are moved over to use the flattened-device-tree model.
                       differ between different families.  May be
                       'virtex2p', 'virtex4', or 'virtex5'.
 
+      vi) Xilinx Uart 16550
+
+      Xilinx UART 16550 devices are very similar to the NS16550 but with
+      different register spacing and an offset from the base address.
+
+      Requred properties:
+       - clock-frequency : Frequency of the clock input
+       - reg-offset : A value of 3 is required
+       - reg-shift : A value of 2 is required
+
+
     p) Freescale Synchronous Serial Interface
 
        The SSI is a serial device that communicates with audio codecs.  It can
diff --git a/Documentation/powerpc/kvm_440.txt b/Documentation/powerpc/kvm_440.txt
new file mode 100644 (file)
index 0000000..c02a003
--- /dev/null
@@ -0,0 +1,41 @@
+Hollis Blanchard <hollisb@us.ibm.com>
+15 Apr 2008
+
+Various notes on the implementation of KVM for PowerPC 440:
+
+To enforce isolation, host userspace, guest kernel, and guest userspace all
+run at user privilege level. Only the host kernel runs in supervisor mode.
+Executing privileged instructions in the guest traps into KVM (in the host
+kernel), where we decode and emulate them. Through this technique, unmodified
+440 Linux kernels can be run (slowly) as guests. Future performance work will
+focus on reducing the overhead and frequency of these traps.
+
+The usual code flow is started from userspace invoking an "run" ioctl, which
+causes KVM to switch into guest context. We use IVPR to hijack the host
+interrupt vectors while running the guest, which allows us to direct all
+interrupts to kvmppc_handle_interrupt(). At this point, we could either
+- handle the interrupt completely (e.g. emulate "mtspr SPRG0"), or
+- let the host interrupt handler run (e.g. when the decrementer fires), or
+- return to host userspace (e.g. when the guest performs device MMIO)
+
+Address spaces: We take advantage of the fact that Linux doesn't use the AS=1
+address space (in host or guest), which gives us virtual address space to use
+for guest mappings. While the guest is running, the host kernel remains mapped
+in AS=0, but the guest can only use AS=1 mappings.
+
+TLB entries: The TLB entries covering the host linear mapping remain
+present while running the guest. This reduces the overhead of lightweight
+exits, which are handled by KVM running in the host kernel. We keep three
+copies of the TLB:
+ - guest TLB: contents of the TLB as the guest sees it
+ - shadow TLB: the TLB that is actually in hardware while guest is running
+ - host TLB: to restore TLB state when context switching guest -> host
+When a TLB miss occurs because a mapping was not present in the shadow TLB,
+but was present in the guest TLB, KVM handles the fault without invoking the
+guest. Large guest pages are backed by multiple 4KB shadow pages through this
+mechanism.
+
+IO: MMIO and DCR accesses are emulated by userspace. We use virtio for network
+and block IO, so those drivers must be enabled in the guest. It's possible
+that some qemu device emulation (e.g. e1000 or rtl8139) may also work with
+little effort.
diff --git a/Documentation/s390/kvm.txt b/Documentation/s390/kvm.txt
new file mode 100644 (file)
index 0000000..6f5ceb0
--- /dev/null
@@ -0,0 +1,125 @@
+*** BIG FAT WARNING ***
+The kvm module is currently in EXPERIMENTAL state for s390. This means that
+the interface to the module is not yet considered to remain stable. Thus, be
+prepared that we keep breaking your userspace application and guest
+compatibility over and over again until we feel happy with the result. Make sure
+your guest kernel, your host kernel, and your userspace launcher are in a
+consistent state.
+
+This Documentation describes the unique ioctl calls to /dev/kvm, the resulting
+kvm-vm file descriptors, and the kvm-vcpu file descriptors that differ from x86.
+
+1. ioctl calls to /dev/kvm
+KVM does support the following ioctls on s390 that are common with other
+architectures and do behave the same:
+KVM_GET_API_VERSION
+KVM_CREATE_VM          (*) see note
+KVM_CHECK_EXTENSION
+KVM_GET_VCPU_MMAP_SIZE
+
+Notes:
+* KVM_CREATE_VM may fail on s390, if the calling process has multiple
+threads and has not called KVM_S390_ENABLE_SIE before.
+
+In addition, on s390 the following architecture specific ioctls are supported:
+ioctl:         KVM_S390_ENABLE_SIE
+args:          none
+see also:      include/linux/kvm.h
+This call causes the kernel to switch on PGSTE in the user page table. This
+operation is needed in order to run a virtual machine, and it requires the
+calling process to be single-threaded. Note that the first call to KVM_CREATE_VM
+will implicitly try to switch on PGSTE if the user process has not called
+KVM_S390_ENABLE_SIE before. User processes that want to launch multiple threads
+before creating a virtual machine have to call KVM_S390_ENABLE_SIE, or will
+observe an error calling KVM_CREATE_VM. Switching on PGSTE is a one-time
+operation, is not reversible, and will persist over the entire lifetime of
+the calling process. It does not have any user-visible effect other than a small
+performance penalty.
+
+2. ioctl calls to the kvm-vm file descriptor
+KVM does support the following ioctls on s390 that are common with other
+architectures and do behave the same:
+KVM_CREATE_VCPU
+KVM_SET_USER_MEMORY_REGION      (*) see note
+KVM_GET_DIRTY_LOG              (**) see note
+
+Notes:
+*  kvm does only allow exactly one memory slot on s390, which has to start
+   at guest absolute address zero and at a user address that is aligned on any
+   page boundary. This hardware "limitation" allows us to have a few unique
+   optimizations. The memory slot doesn't have to be filled
+   with memory actually, it may contain sparse holes. That said, with different
+   user memory layout this does still allow a large flexibility when
+   doing the guest memory setup.
+** KVM_GET_DIRTY_LOG doesn't work properly yet. The user will receive an empty
+log. This ioctl call is only needed for guest migration, and we intend to
+implement this one in the future.
+
+In addition, on s390 the following architecture specific ioctls for the kvm-vm
+file descriptor are supported:
+ioctl:         KVM_S390_INTERRUPT
+args:          struct kvm_s390_interrupt *
+see also:      include/linux/kvm.h
+This ioctl is used to submit a floating interrupt for a virtual machine.
+Floating interrupts may be delivered to any virtual cpu in the configuration.
+Only some interrupt types defined in include/linux/kvm.h make sense when
+submitted as floating interrupts. The following interrupts are not considered
+to be useful as floating interrupts, and a call to inject them will result in
+-EINVAL error code: program interrupts and interprocessor signals. Valid
+floating interrupts are:
+KVM_S390_INT_VIRTIO
+KVM_S390_INT_SERVICE
+
+3. ioctl calls to the kvm-vcpu file descriptor
+KVM does support the following ioctls on s390 that are common with other
+architectures and do behave the same:
+KVM_RUN
+KVM_GET_REGS
+KVM_SET_REGS
+KVM_GET_SREGS
+KVM_SET_SREGS
+KVM_GET_FPU
+KVM_SET_FPU
+
+In addition, on s390 the following architecture specific ioctls for the
+kvm-vcpu file descriptor are supported:
+ioctl:         KVM_S390_INTERRUPT
+args:          struct kvm_s390_interrupt *
+see also:      include/linux/kvm.h
+This ioctl is used to submit an interrupt for a specific virtual cpu.
+Only some interrupt types defined in include/linux/kvm.h make sense when
+submitted for a specific cpu. The following interrupts are not considered
+to be useful, and a call to inject them will result in -EINVAL error code:
+service processor calls and virtio interrupts. Valid interrupt types are:
+KVM_S390_PROGRAM_INT
+KVM_S390_SIGP_STOP
+KVM_S390_RESTART
+KVM_S390_SIGP_SET_PREFIX
+KVM_S390_INT_EMERGENCY
+
+ioctl:         KVM_S390_STORE_STATUS
+args:          unsigned long
+see also:      include/linux/kvm.h
+This ioctl stores the state of the cpu at the guest real address given as
+argument, unless one of the following values defined in include/linux/kvm.h
+is given as arguement:
+KVM_S390_STORE_STATUS_NOADDR - the CPU stores its status to the save area in
+absolute lowcore as defined by the principles of operation
+KVM_S390_STORE_STATUS_PREFIXED - the CPU stores its status to the save area in
+its prefix page just like the dump tool that comes with zipl. This is useful
+to create a system dump for use with lkcdutils or crash.
+
+ioctl:         KVM_S390_SET_INITIAL_PSW
+args:          struct kvm_s390_psw *
+see also:      include/linux/kvm.h
+This ioctl can be used to set the processor status word (psw) of a stopped cpu
+prior to running it with KVM_RUN. Note that this call is not required to modify
+the psw during sie intercepts that fall back to userspace because struct kvm_run
+does contain the psw, and this value is evaluated during reentry of KVM_RUN
+after the intercept exit was recognized.
+
+ioctl:         KVM_S390_INITIAL_RESET
+args:          none
+see also:      include/linux/kvm.h
+This ioctl can be used to perform an initial cpu reset as defined by the
+principles of operation. The target cpu has to be in stopped state.
diff --git a/Documentation/smart-config.txt b/Documentation/smart-config.txt
deleted file mode 100644 (file)
index 8467447..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-Smart CONFIG_* Dependencies
-1 August 1999
-
-Michael Chastain   <mec@shout.net>
-Werner Almesberger <almesber@lrc.di.epfl.ch>
-Martin von Loewis  <martin@mira.isdn.cs.tu-berlin.de>
-
-Here is the problem:
-
-    Suppose that drivers/net/foo.c has the following lines:
-
-       #include <linux/config.h>
-
-       ...
-
-       #ifdef CONFIG_FOO_AUTOFROB
-           /* Code for auto-frobbing */
-       #else
-           /* Manual frobbing only */
-       #endif
-
-       ...
-
-       #ifdef CONFIG_FOO_MODEL_TWO
-           /* Code for model two */
-       #endif
-
-    Now suppose the user (the person building kernels) reconfigures the
-    kernel to change some unrelated setting.  This will regenerate the
-    file include/linux/autoconf.h, which will cause include/linux/config.h
-    to be out of date, which will cause drivers/net/foo.c to be recompiled.
-
-    Most kernel sources, perhaps 80% of them, have at least one CONFIG_*
-    dependency somewhere.  So changing _any_ CONFIG_* setting requires
-    almost _all_ of the kernel to be recompiled.
-
-Here is the solution:
-
-    We've made the dependency generator, mkdep.c, smarter.  Instead of
-    generating this dependency:
-
-       drivers/net/foo.c: include/linux/config.h
-
-    It now generates these dependencies:
-
-       drivers/net/foo.c: \
-           include/config/foo/autofrob.h \
-           include/config/foo/model/two.h
-
-    So drivers/net/foo.c depends only on the CONFIG_* lines that
-    it actually uses.
-
-    A new program, split-include.c, runs at the beginning of
-    compilation (make bzImage or make zImage).  split-include reads
-    include/linux/autoconf.h and updates the include/config/ tree,
-    writing one file per option.  It updates only the files for options
-    that have changed.
-
-Flag Dependencies
-
-    Martin Von Loewis contributed another feature to this patch:
-    'flag dependencies'.  The idea is that a .o file depends on
-    the compilation flags used to build it.  The file foo.o has
-    its flags stored in .flags.foo.o.
-
-    Suppose the user changes the foo driver from resident to modular.
-    'make' will notice that the current foo.o was not compiled with
-    -DMODULE and will recompile foo.c.
-
-    All .o files made from C source have flag dependencies.  So do .o
-    files made with ld, and .a files made with ar.  However, .o files
-    made from assembly source do not have flag dependencies (nobody
-    needs this yet, but it would be good to fix).
-
-Per-source-file Flags
-
-    Flag dependencies also work with per-source-file flags.
-    You can specify compilation flags for individual source files
-    like this:
-
-       CFLAGS_foo.o = -DSPECIAL_FOO_DEFINE
-
-    This helps clean up drivers/net/Makefile, drivers/scsi/Makefile,
-    and several other Makefiles.
-
-Credit
-
-    Werner Almesberger had the original idea and wrote the first
-    version of this patch.
-    
-    Michael Chastain picked it up and continued development.  He is
-    now the principal author and maintainer.  Please report any bugs
-    to him.
-
-    Martin von Loewis wrote flag dependencies, with some modifications
-    by Michael Chastain.
-
-    Thanks to all of the beta testers.
diff --git a/Documentation/usb/anchors.txt b/Documentation/usb/anchors.txt
new file mode 100644 (file)
index 0000000..7304bcf
--- /dev/null
@@ -0,0 +1,50 @@
+What is anchor?
+===============
+
+A USB driver needs to support some callbacks requiring
+a driver to cease all IO to an interface. To do so, a
+driver has to keep track of the URBs it has submitted
+to know they've all completed or to call usb_kill_urb
+for them. The anchor is a data structure takes care of
+keeping track of URBs and provides methods to deal with
+multiple URBs.
+
+Allocation and Initialisation
+=============================
+
+There's no API to allocate an anchor. It is simply declared
+as struct usb_anchor. init_usb_anchor() must be called to
+initialise the data structure.
+
+Deallocation
+============
+
+Once it has no more URBs associated with it, the anchor can be
+freed with normal memory management operations.
+
+Association and disassociation of URBs with anchors
+===================================================
+
+An association of URBs to an anchor is made by an explicit
+call to usb_anchor_urb(). The association is maintained until
+an URB is finished by (successfull) completion. Thus disassociation
+is automatic. A function is provided to forcibly finish (kill)
+all URBs associated with an anchor.
+Furthermore, disassociation can be made with usb_unanchor_urb()
+
+Operations on multitudes of URBs
+================================
+
+usb_kill_anchored_urbs()
+------------------------
+
+This function kills all URBs associated with an anchor. The URBs
+are called in the reverse temporal order they were submitted.
+This way no data can be reordered.
+
+usb_wait_anchor_empty_timeout()
+-------------------------------
+
+This function waits for all URBs associated with an anchor to finish
+or a timeout, whichever comes first. Its return value will tell you
+whether the timeout was reached.
diff --git a/Documentation/usb/callbacks.txt b/Documentation/usb/callbacks.txt
new file mode 100644 (file)
index 0000000..7c81241
--- /dev/null
@@ -0,0 +1,132 @@
+What callbacks will usbcore do?
+===============================
+
+Usbcore will call into a driver through callbacks defined in the driver
+structure and through the completion handler of URBs a driver submits.
+Only the former are in the scope of this document. These two kinds of
+callbacks are completely independent of each other. Information on the
+completion callback can be found in Documentation/usb/URB.txt.
+
+The callbacks defined in the driver structure are:
+
+1. Hotplugging callbacks:
+
+ * @probe: Called to see if the driver is willing to manage a particular
+ *     interface on a device.
+ * @disconnect: Called when the interface is no longer accessible, usually
+ *     because its device has been (or is being) disconnected or the
+ *     driver module is being unloaded.
+
+2. Odd backdoor through usbfs:
+
+ * @ioctl: Used for drivers that want to talk to userspace through
+ *     the "usbfs" filesystem.  This lets devices provide ways to
+ *     expose information to user space regardless of where they
+ *     do (or don't) show up otherwise in the filesystem.
+
+3. Power management (PM) callbacks:
+
+ * @suspend: Called when the device is going to be suspended.
+ * @resume: Called when the device is being resumed.
+ * @reset_resume: Called when the suspended device has been reset instead
+ *     of being resumed.
+
+4. Device level operations:
+
+ * @pre_reset: Called when the device is about to be reset.
+ * @post_reset: Called after the device has been reset
+
+The ioctl interface (2) should be used only if you have a very good
+reason. Sysfs is preferred these days. The PM callbacks are covered
+separately in Documentation/usb/power-management.txt.
+
+Calling conventions
+===================
+
+All callbacks are mutually exclusive. There's no need for locking
+against other USB callbacks. All callbacks are called from a task
+context. You may sleep. However, it is important that all sleeps have a
+small fixed upper limit in time. In particular you must not call out to
+user space and await results.
+
+Hotplugging callbacks
+=====================
+
+These callbacks are intended to associate and disassociate a driver with
+an interface. A driver's bond to an interface is exclusive.
+
+The probe() callback
+--------------------
+
+int (*probe) (struct usb_interface *intf,
+               const struct usb_device_id *id);
+
+Accept or decline an interface. If you accept the device return 0,
+otherwise -ENODEV or -ENXIO. Other error codes should be used only if a
+genuine error occurred during initialisation which prevented a driver
+from accepting a device that would else have been accepted.
+You are strongly encouraged to use usbcore'sfacility,
+usb_set_intfdata(), to associate a data structure with an interface, so
+that you know which internal state and identity you associate with a
+particular interface. The device will not be suspended and you may do IO
+to the interface you are called for and endpoint 0 of the device. Device
+initialisation that doesn't take too long is a good idea here.
+
+The disconnect() callback
+-------------------------
+
+void (*disconnect) (struct usb_interface *intf);
+
+This callback is a signal to break any connection with an interface.
+You are not allowed any IO to a device after returning from this
+callback. You also may not do any other operation that may interfere
+with another driver bound the interface, eg. a power management
+operation.
+If you are called due to a physical disconnection, all your URBs will be
+killed by usbcore. Note that in this case disconnect will be called some
+time after the physical disconnection. Thus your driver must be prepared
+to deal with failing IO even prior to the callback.
+
+Device level callbacks
+======================
+
+pre_reset
+---------
+
+int (*pre_reset)(struct usb_interface *intf);
+
+Another driver or user space is triggering a reset on the device which
+contains the interface passed as an argument. Cease IO and save any
+device state you need to restore.
+
+If you need to allocate memory here, use GFP_NOIO or GFP_ATOMIC, if you
+are in atomic context.
+
+post_reset
+----------
+
+int (*post_reset)(struct usb_interface *intf);
+
+The reset has completed.  Restore any saved device state and begin
+using the device again.
+
+If you need to allocate memory here, use GFP_NOIO or GFP_ATOMIC, if you
+are in atomic context.
+
+Call sequences
+==============
+
+No callbacks other than probe will be invoked for an interface
+that isn't bound to your driver.
+
+Probe will never be called for an interface bound to a driver.
+Hence following a successful probe, disconnect will be called
+before there is another probe for the same interface.
+
+Once your driver is bound to an interface, disconnect can be
+called at any time except in between pre_reset and post_reset.
+pre_reset is always followed by post_reset, even if the reset
+failed or the device has been unplugged.
+
+suspend is always followed by one of: resume, reset_resume, or
+disconnect.
index df54d645cbb5d651d52aaeecbf945dcd21b71044..d56cb1a1155073987fc2ca108c766f03100d35cf 100644 (file)
@@ -2,7 +2,7 @@
 
                   Alan Stern <stern@rowland.harvard.edu>
 
-                September 2, 2006 (Updated May 29, 2007)
+               September 2, 2006 (Updated February 25, 2008)
 
 
        What is the problem?
@@ -65,9 +65,10 @@ 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.
+The kernel includes a feature called USB-persist.  It tries to work
+around these issues by allowing the core USB device data structures 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
@@ -80,28 +81,30 @@ 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.
+unplugged.  The same thing happens if the host controller is in the
+expected state but a USB device was unplugged and then replugged.
 
 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.
+plugged in.
 
 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):
+Note that the "USB-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.
+automatically and permanently enabled and the power/persist file
+doesn't even exist, so you only have to worry about setting it for
+devices where it really matters.
 
 
        Is this the best solution?
@@ -112,19 +115,19 @@ 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.
+it would be more far-reaching than 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
+Furthermore, the USB-persist feature 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!!
+       WARNING: 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
@@ -133,10 +136,10 @@ 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.
+kernel won't detect the change.  The serial number string and other
+descriptors are compared with the kernel's stored values, but this
+might not help since 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
@@ -152,5 +155,5 @@ 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.
+at all.  The USB-persist feature can be extremely useful.  Make the
+most of it.
index 8b077e43eee7168c0a6594e88911636301c72c56..ff2c1ff57ba2768242acb1b7587c96af1eb3bb8a 100644 (file)
@@ -192,12 +192,9 @@ Keyspan USA-series Serial Adapters
 
 FTDI Single Port Serial Driver
 
-  This is a single port DB-25 serial adapter. More information about this
-  device and the Linux driver can be found at:
-       http://reality.sgi.com/bryder_wellington/ftdi_sio/
+  This is a single port DB-25 serial adapter.
 
-  For any questions or problems with this driver, please contact Bill Ryder
-  at bryder@sgi.com
+  For any questions or problems with this driver, please contact Bill Ryder.
 
 
 ZyXEL omni.net lcd plus ISDN TA
index f50e927a118992e8d69953675c65a87998a63231..c1dd1ae7b1335d9de927e6a7731d72066424660d 100644 (file)
@@ -1106,6 +1106,12 @@ M:       kernel@wantstofly.org
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 
+CIRRUS LOGIC CS4270 SOUND DRIVER
+P:     Timur Tabi
+M:     timur@freescale.com
+L:     alsa-devel@alsa-project.org
+S:     Supported
+
 CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER
 P:     Cirrus Logic Corporation (kernel 2.2 driver)
 M:     Cirrus Logic Corporation, Thomas Woller <twoller@crystal.cirrus.com>
@@ -1628,6 +1634,12 @@ L:       linuxppc-dev@ozlabs.org
 L:     netdev@vger.kernel.org
 S:     Maintained
 
+FREESCALE QUICC ENGINE LIBRARY
+P:     Timur Tabi
+M:     timur@freescale.com
+L:     linuxppc-dev@ozlabs.org
+S:     Supported
+
 FREESCALE HIGHSPEED USB DEVICE DRIVER
 P:     Li Yang
 M:     leoli@freescale.com
@@ -1642,6 +1654,19 @@ L:       netdev@vger.kernel.org
 L:     linuxppc-dev@ozlabs.org
 S:     Maintained
 
+FREESCALE QUICC ENGINE UCC UART DRIVER
+P:     Timur Tabi
+M:     timur@freescale.com
+L:     linuxppc-dev@ozlabs.org
+S:     Supported
+
+FREESCALE SOC SOUND DRIVERS
+P:     Timur Tabi
+M:     timur@freescale.com
+L:     alsa-devel@alsa-project.org
+L:     linuxppc-dev@ozlabs.org
+S:     Supported
+
 FILE LOCKING (flock() and fcntl()/lockf())
 P:     Matthew Wilcox
 M:     matthew@wil.cx
@@ -2304,6 +2329,13 @@ L:       kvm-devel@lists.sourceforge.net
 W:     kvm.sourceforge.net
 S:     Supported
 
+KERNEL VIRTUAL MACHINE (KVM) FOR POWERPC
+P:     Hollis Blanchard
+M:     hollisb@us.ibm.com
+L:     kvm-ppc-devel@lists.sourceforge.net
+W:     kvm.sourceforge.net
+S:     Supported
+
 KERNEL VIRTUAL MACHINE For Itanium(KVM/IA64)
 P:     Anthony Xu
 M:     anthony.xu@intel.com
@@ -2313,6 +2345,16 @@ L:       kvm-ia64-devel@lists.sourceforge.net
 W:     kvm.sourceforge.net
 S:     Supported
 
+KERNEL VIRTUAL MACHINE for s390 (KVM/s390)
+P:     Carsten Otte
+M:     cotte@de.ibm.com
+P:     Christian Borntraeger
+M:     borntraeger@de.ibm.com
+M:     linux390@de.ibm.com
+L:     linux-s390@vger.kernel.org
+W:     http://www.ibm.com/developerworks/linux/linux390/
+S:     Supported
+
 KEXEC
 P:     Eric Biederman
 M:     ebiederm@xmission.com
@@ -4356,6 +4398,16 @@ L:       linux-wireless@vger.kernel.org
 W:     http://oops.ghostprotocols.net:81/blog
 S:     Maintained
 
+WM97XX TOUCHSCREEN DRIVERS
+P:     Mark Brown
+M:     broonie@opensource.wolfsonmicro.com
+P:     Liam Girdwood
+M:     liam.girdwood@wolfsonmicro.com
+L:     linux-input@vger.kernel.org
+T:     git git://opensource.wolfsonmicro.com/linux-2.6-touch
+W:     http://opensource.wolfsonmicro.com/node/7
+S:     Supported
+
 X.25 NETWORK LAYER
 P:     Henner Eisen
 M:     eis@baty.hanse.de
index d35c5246fce5b338f1781ba2b2ae4c0224ad902e..fc3411e6f071fb34be17e7bd937e38634ab78cfd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 25
-EXTRAVERSION = -numa
+EXTRAVERSION =
 NAME = Funky Weasel is Jiggy wit it
 
 # *DOCUMENTATION*
@@ -507,6 +507,10 @@ else
 KBUILD_CFLAGS  += -O2
 endif
 
+ifneq (CONFIG_FRAME_WARN,0)
+KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
+endif
+
 # Force gcc to behave correct even for buggy distributions
 # Arch Makefiles may override this setting
 KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
@@ -1396,7 +1400,7 @@ define xtags
            $(all-kconfigs) | xargs $1 -a \
                --langdef=kconfig \
                --language-force=kconfig \
-               --regex-kconfig='/^[[:blank:]]*config[[:blank:]]+([[:alnum:]_]+)/\1/'; \
+               --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/\2/'; \
            $(all-defconfigs) | xargs -r $1 -a \
                --langdef=dotconfig \
                --language-force=dotconfig \
@@ -1404,7 +1408,7 @@ define xtags
        elif $1 --version 2>&1 | grep -iq emacs; then \
            $(all-sources) | xargs $1 -a; \
            $(all-kconfigs) | xargs $1 -a \
-               --regex='/^[ \t]*config[ \t]+\([a-zA-Z0-9_]+\)/\1/'; \
+               --regex='/^[ \t]*(menu|)config[ \t]+\([a-zA-Z0-9_]+\)/\2/'; \
            $(all-defconfigs) | xargs -r $1 -a \
                --regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/'; \
        else \
@@ -1539,7 +1543,6 @@ quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN   $(wildcard $(rm-files))
       cmd_rmfiles = rm -f $(rm-files)
 
 # Run depmod only if we have System.map and depmod is executable
-# and we build for the host arch
 quiet_cmd_depmod = DEPMOD  $(KERNELRELEASE)
       cmd_depmod = \
        if [ -r System.map -a -x $(DEPMOD) ]; then                              \
index dc030cfe5009640c1a7891f2ce632fea9cf3f816..5e68420f468046c306386e1f05275d0902ae3aea 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25-rc3
-# Sun Mar  9 06:33:33 2008
+# Linux kernel version: 2.6.25
+# Sun Apr 20 00:29:49 2008
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -51,7 +51,8 @@ CONFIG_FAIR_GROUP_SCHED=y
 # CONFIG_RT_GROUP_SCHED is not set
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
-# CONFIG_SYSFS_DEPRECATED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 # CONFIG_BLK_DEV_INITRD is not set
@@ -85,6 +86,7 @@ CONFIG_SLAB=y
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
 CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -115,7 +117,6 @@ CONFIG_IOSCHED_NOOP=y
 CONFIG_DEFAULT_NOOP=y
 CONFIG_DEFAULT_IOSCHED="noop"
 CONFIG_CLASSIC_RCU=y
-# CONFIG_PREEMPT_RCU is not set
 
 #
 # System Type
@@ -320,8 +321,6 @@ CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
@@ -383,7 +382,6 @@ CONFIG_IEEE80211=m
 CONFIG_IEEE80211_CRYPT_WEP=m
 # CONFIG_IEEE80211_CRYPT_CCMP is not set
 # CONFIG_IEEE80211_CRYPT_TKIP is not set
-# CONFIG_IEEE80211_SOFTMAC is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -503,7 +501,7 @@ CONFIG_IDE_MAX_HWIFS=2
 CONFIG_BLK_DEV_IDE=m
 
 #
-# Please see Documentation/ide.txt for help/info on IDE drives
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
 #
 # CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=m
@@ -518,10 +516,9 @@ CONFIG_IDE_PROC_FS=y
 #
 # IDE chipset support/bugfixes
 #
-CONFIG_IDE_GENERIC=m
 # CONFIG_BLK_DEV_PLATFORM is not set
 # CONFIG_BLK_DEV_IDEDMA is not set
-CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+# CONFIG_BLK_DEV_HD_ONLY is not set
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -562,6 +559,7 @@ CONFIG_NETDEV_10000=y
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
 # CONFIG_NET_PCMCIA is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
@@ -707,6 +705,8 @@ CONFIG_SSB_POSSIBLE=y
 #
 # CONFIG_MFD_SM501 is not set
 # CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
 
 #
 # Multimedia devices
@@ -745,6 +745,7 @@ CONFIG_FB_TILEBLITTING=y
 CONFIG_FB_PXA=y
 CONFIG_FB_PXA_PARAMETERS=y
 CONFIG_FB_MBX=m
+# CONFIG_FB_METRONOME is not set
 CONFIG_FB_VIRTUAL=m
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
@@ -891,7 +892,6 @@ CONFIG_RTC_LIB=y
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY=y
index f1a80d74a4b659bde31a4402453f0bfa0232c19b..be526746e01e496d46a3e49db1b06494c7f9b1bf 100644 (file)
@@ -246,7 +246,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
                }
 
                mmc0_data = *data;
-               at91_clock_associate("mci0_clk", &at91cap9_mmc1_device.dev, "mci_clk");
+               at91_clock_associate("mci0_clk", &at91cap9_mmc0_device.dev, "mci_clk");
                platform_device_register(&at91cap9_mmc0_device);
        } else {                        /* MCI1 */
                /* CLK */
index b6454c52596227a640c77b15ec3699d05fcd1b3e..719667e25c981f01f8261e37746d3f5cdbb22d65 100644 (file)
@@ -308,7 +308,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
                }
 
                mmc0_data = *data;
-               at91_clock_associate("mci0_clk", &at91sam9263_mmc1_device.dev, "mci_clk");
+               at91_clock_associate("mci0_clk", &at91sam9263_mmc0_device.dev, "mci_clk");
                platform_device_register(&at91sam9263_mmc0_device);
        } else {                        /* MCI1 */
                /* CLK */
index 39733b6992aa3126ee5e715dbaa0ef97faceefd3..aa863c1577087fa1bb0ba8ea5d26d8b37572c96b 100644 (file)
@@ -61,6 +61,15 @@ static inline void sdram_selfrefresh_enable(void)
 #else
 #include <asm/arch/at91sam9_sdramc.h>
 
+#ifdef CONFIG_ARCH_AT91SAM9263
+/*
+ * FIXME either or both the SDRAM controllers (EB0, EB1) might be in use;
+ * handle those cases both here and in the Suspend-To-RAM support.
+ */
+#define        AT91_SDRAMC     AT91_SDRAMC0
+#warning Assuming EB1 SDRAM controller is *NOT* used
+#endif
+
 static u32 saved_lpr;
 
 static inline void sdram_selfrefresh_enable(void)
@@ -75,11 +84,6 @@ static inline void sdram_selfrefresh_enable(void)
 
 #define sdram_selfrefresh_disable()    at91_sys_write(AT91_SDRAMC_LPR, saved_lpr)
 
-/*
- * FIXME: The AT91SAM9263 has a second EBI controller which may have
- *        additional SDRAM.  pm_slowclock.S will require a similar fix.
- */
-
 #endif
 
 
index 7cdcb459ea9dd266d1bb9c076bb19127144ec276..6a830853aa6a610e532c33040f0ab96544dc8c3e 100644 (file)
@@ -5,9 +5,9 @@
 # Common support (must be linked before board specific support)
 obj-y                          += clock.o devices.o generic.o irq.o dma.o \
                                   time.o gpio.o
-obj-$(CONFIG_PXA25x)           += pxa25x.o mfp-pxa2xx.o
-obj-$(CONFIG_PXA27x)           += pxa27x.o mfp-pxa2xx.o
-obj-$(CONFIG_PXA3xx)           += pxa3xx.o mfp-pxa3xx.o smemc.o
+obj-$(CONFIG_PXA25x)           += mfp-pxa2xx.o pxa25x.o
+obj-$(CONFIG_PXA27x)           += mfp-pxa2xx.o pxa27x.o
+obj-$(CONFIG_PXA3xx)           += mfp-pxa3xx.o pxa3xx.o smemc.o
 obj-$(CONFIG_CPU_PXA300)       += pxa300.o
 obj-$(CONFIG_CPU_PXA320)       += pxa320.o
 
index f01d18544133e435be54466468b3ead8eab08006..bdf2397540373e8d9f2047cc1cb45bb81c5a1cae 100644 (file)
@@ -40,6 +40,7 @@
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/pxa2xx-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 
 #include "generic.h"
 
index d70be75bd199552d63cbc7d851d9fbd39f87d4c4..badba064dc0400326e74a3e874d9366aa6519c52 100644 (file)
@@ -114,6 +114,14 @@ static unsigned long magician_pin_config[] = {
        GPIO82_CIF_DD_5,
        GPIO84_CIF_FV,
        GPIO85_CIF_LV,
+
+       /* Magician specific input GPIOs */
+       GPIO9_GPIO,     /* unknown */
+       GPIO10_GPIO,    /* GSM_IRQ */
+       GPIO13_GPIO,    /* CPLD_IRQ */
+       GPIO107_GPIO,   /* DS1WM_IRQ */
+       GPIO108_GPIO,   /* GSM_READY */
+       GPIO115_GPIO,   /* nPEN_IRQ */
 };
 
 /*
@@ -438,7 +446,7 @@ static struct pasic3_led pasic3_leds[] = {
 
 static struct platform_device pasic3;
 
-static struct pasic3_leds_machinfo __devinit pasic3_leds_info = {
+static struct pasic3_leds_machinfo pasic3_leds_info = {
        .num_leds   = ARRAY_SIZE(pasic3_leds),
        .power_gpio = EGPIO_MAGICIAN_LED_POWER,
        .leds       = pasic3_leds,
@@ -543,9 +551,28 @@ static struct platform_device power_supply = {
 static int magician_mci_init(struct device *dev,
                                irq_handler_t detect_irq, void *data)
 {
-       return request_irq(IRQ_MAGICIAN_SD, detect_irq,
+       int err;
+
+       err = request_irq(IRQ_MAGICIAN_SD, detect_irq,
                                IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
                                "MMC card detect", data);
+       if (err)
+               goto err_request_irq;
+       err = gpio_request(EGPIO_MAGICIAN_SD_POWER, "SD_POWER");
+       if (err)
+               goto err_request_power;
+       err = gpio_request(EGPIO_MAGICIAN_nSD_READONLY, "nSD_READONLY");
+       if (err)
+               goto err_request_readonly;
+
+       return 0;
+
+err_request_readonly:
+       gpio_free(EGPIO_MAGICIAN_SD_POWER);
+err_request_power:
+       free_irq(IRQ_MAGICIAN_SD, data);
+err_request_irq:
+       return err;
 }
 
 static void magician_mci_setpower(struct device *dev, unsigned int vdd)
@@ -562,6 +589,8 @@ static int magician_mci_get_ro(struct device *dev)
 
 static void magician_mci_exit(struct device *dev, void *data)
 {
+       gpio_free(EGPIO_MAGICIAN_nSD_READONLY);
+       gpio_free(EGPIO_MAGICIAN_SD_POWER);
        free_irq(IRQ_MAGICIAN_SD, data);
 }
 
@@ -643,28 +672,42 @@ static void __init magician_init(void)
 {
        void __iomem *cpld;
        int lcd_select;
+       int err;
+
+       gpio_request(GPIO13_MAGICIAN_CPLD_IRQ, "CPLD_IRQ");
+       gpio_request(GPIO107_MAGICIAN_DS1WM_IRQ, "DS1WM_IRQ");
 
        pxa2xx_mfp_config(ARRAY_AND_SIZE(magician_pin_config));
 
        platform_add_devices(devices, ARRAY_SIZE(devices));
+
+       err = gpio_request(GPIO83_MAGICIAN_nIR_EN, "nIR_EN");
+       if (!err) {
+               gpio_direction_output(GPIO83_MAGICIAN_nIR_EN, 1);
+               pxa_set_ficp_info(&magician_ficp_info);
+       }
        pxa_set_i2c_info(NULL);
        pxa_set_mci_info(&magician_mci_info);
        pxa_set_ohci_info(&magician_ohci_info);
-       pxa_set_ficp_info(&magician_ficp_info);
 
        /* Check LCD type we have */
        cpld = ioremap_nocache(PXA_CS3_PHYS, 0x1000);
        if (cpld) {
                u8 board_id = __raw_readb(cpld+0x14);
+               iounmap(cpld);
                system_rev = board_id & 0x7;
                lcd_select = board_id & 0x8;
-               iounmap(cpld);
                pr_info("LCD type: %s\n", lcd_select ? "Samsung" : "Toppoly");
-               if (lcd_select && (system_rev < 3))
-                       pxa_gpio_mode(GPIO75_MAGICIAN_SAMSUNG_POWER_MD);
-               pxa_gpio_mode(GPIO104_MAGICIAN_LCD_POWER_1_MD);
-               pxa_gpio_mode(GPIO105_MAGICIAN_LCD_POWER_2_MD);
-               pxa_gpio_mode(GPIO106_MAGICIAN_LCD_POWER_3_MD);
+               if (lcd_select && (system_rev < 3)) {
+                       gpio_request(GPIO75_MAGICIAN_SAMSUNG_POWER, "SAMSUNG_POWER");
+                       gpio_direction_output(GPIO75_MAGICIAN_SAMSUNG_POWER, 0);
+               }
+               gpio_request(GPIO104_MAGICIAN_LCD_POWER_1, "LCD_POWER_1");
+               gpio_request(GPIO105_MAGICIAN_LCD_POWER_2, "LCD_POWER_2");
+               gpio_request(GPIO106_MAGICIAN_LCD_POWER_3, "LCD_POWER_3");
+               gpio_direction_output(GPIO104_MAGICIAN_LCD_POWER_1, 0);
+               gpio_direction_output(GPIO105_MAGICIAN_LCD_POWER_2, 0);
+               gpio_direction_output(GPIO106_MAGICIAN_LCD_POWER_3, 0);
                set_pxa_fb_info(lcd_select ? &samsung_info : &toppoly_info);
        } else
                pr_err("LCD detection: CPLD mapping failed\n");
index 039194cbe477fd90eaacaa613dd87e1417040d65..ec1bbf333a3ad5a74c8c1cb06c2b0c6613fa277b 100644 (file)
@@ -46,8 +46,8 @@ int pxa_pm_enter(suspend_state_t state)
                        sleep_save_checksum += sleep_save[i];
        }
 
-       /* Clear sleep reset status */
-       RCSR = RCSR_SMR;
+       /* Clear reset status */
+       RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
 
        /* *** go zzz *** */
        pxa_cpu_pm_fns->enter(state);
index dde355e88fa1574d3760a778a4cb7bf8297d166a..b6a6f5fcc77ad56158bbd01b061c973ca4700285 100644 (file)
@@ -486,6 +486,8 @@ static int pxa3xx_set_wake(unsigned int irq, unsigned int on)
        case IRQ_MMC3:
                mask = ADXER_MFP_GEN12;
                break;
+       default:
+               return -EINVAL;
        }
 
        local_irq_save(flags);
index 75bae067922d1c55fdef728f67e8f952062009be..74fae6045650409bdd4dc44a343d60887b540443 100644 (file)
@@ -51,7 +51,7 @@
 /*
  * MPCore SCU event monitor support
  */
-#define SCU_EVENTMONITORS_VA_BASE __io_address(REALVIEW_MPCORE_SCU_BASE + 0x10)
+#define SCU_EVENTMONITORS_VA_BASE __io_address(REALVIEW_EB11MP_SCU_BASE + 0x10)
 
 /*
  * Bitmask of used SCU counters
@@ -80,7 +80,7 @@ static irqreturn_t scu_em_interrupt(int irq, void *arg)
        struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE;
        unsigned int cnt;
 
-       cnt = irq - IRQ_PMU_SCU0;
+       cnt = irq - IRQ_EB11MP_PMU_SCU0;
        oprofile_add_sample(get_irq_regs(), SCU_COUNTER(cnt));
        scu_reset_counter(emc, cnt);
 
@@ -119,10 +119,10 @@ static int scu_start(void)
         */
        for (i = 0; i < NUM_SCU_COUNTERS; i++) {
                if (scu_em_used & (1 << i)) {
-                       ret = request_irq(IRQ_PMU_SCU0 + i, scu_em_interrupt, IRQF_DISABLED, "SCU PMU", NULL);
+                       ret = request_irq(IRQ_EB11MP_PMU_SCU0 + i, scu_em_interrupt, IRQF_DISABLED, "SCU PMU", NULL);
                        if (ret) {
                                printk(KERN_ERR "oprofile: unable to request IRQ%u for SCU Event Monitor\n",
-                                      IRQ_PMU_SCU0 + i);
+                                      IRQ_EB11MP_PMU_SCU0 + i);
                                goto err_free_scu;
                        }
                }
@@ -153,7 +153,7 @@ static int scu_start(void)
 
  err_free_scu:
        while (i--)
-               free_irq(IRQ_PMU_SCU0 + i, NULL);
+               free_irq(IRQ_EB11MP_PMU_SCU0 + i, NULL);
        return ret;
 }
 
@@ -175,7 +175,7 @@ static void scu_stop(void)
        for (i = 0; i < NUM_SCU_COUNTERS; i++) {
                if (scu_em_used & (1 << i)) {
                        scu_reset_counter(emc, i);
-                       free_irq(IRQ_PMU_SCU0 + i, NULL);
+                       free_irq(IRQ_EB11MP_PMU_SCU0 + i, NULL);
                }
        }
 }
@@ -225,10 +225,10 @@ static int em_setup_ctrs(void)
 }
 
 static int arm11_irqs[] = {
-       [0]     = IRQ_PMU_CPU0,
-       [1]     = IRQ_PMU_CPU1,
-       [2]     = IRQ_PMU_CPU2,
-       [3]     = IRQ_PMU_CPU3
+       [0]     = IRQ_EB11MP_PMU_CPU0,
+       [1]     = IRQ_EB11MP_PMU_CPU1,
+       [2]     = IRQ_EB11MP_PMU_CPU2,
+       [3]     = IRQ_EB11MP_PMU_CPU3
 };
 
 static int em_start(void)
@@ -273,22 +273,22 @@ static int em_setup(void)
        /*
         * Send SCU PMU interrupts to the "owner" CPU.
         */
-       em_route_irq(IRQ_PMU_SCU0, 0);
-       em_route_irq(IRQ_PMU_SCU1, 0);
-       em_route_irq(IRQ_PMU_SCU2, 1);
-       em_route_irq(IRQ_PMU_SCU3, 1);
-       em_route_irq(IRQ_PMU_SCU4, 2);
-       em_route_irq(IRQ_PMU_SCU5, 2);
-       em_route_irq(IRQ_PMU_SCU6, 3);
-       em_route_irq(IRQ_PMU_SCU7, 3);
+       em_route_irq(IRQ_EB11MP_PMU_SCU0, 0);
+       em_route_irq(IRQ_EB11MP_PMU_SCU1, 0);
+       em_route_irq(IRQ_EB11MP_PMU_SCU2, 1);
+       em_route_irq(IRQ_EB11MP_PMU_SCU3, 1);
+       em_route_irq(IRQ_EB11MP_PMU_SCU4, 2);
+       em_route_irq(IRQ_EB11MP_PMU_SCU5, 2);
+       em_route_irq(IRQ_EB11MP_PMU_SCU6, 3);
+       em_route_irq(IRQ_EB11MP_PMU_SCU7, 3);
 
        /*
         * Send CP15 PMU interrupts to the owner CPU.
         */
-       em_route_irq(IRQ_PMU_CPU0, 0);
-       em_route_irq(IRQ_PMU_CPU1, 1);
-       em_route_irq(IRQ_PMU_CPU2, 2);
-       em_route_irq(IRQ_PMU_CPU3, 3);
+       em_route_irq(IRQ_EB11MP_PMU_CPU0, 0);
+       em_route_irq(IRQ_EB11MP_PMU_CPU1, 1);
+       em_route_irq(IRQ_EB11MP_PMU_CPU2, 2);
+       em_route_irq(IRQ_EB11MP_PMU_CPU3, 3);
 
        return 0;
 }
index cd13e138bd03800edd9ab5cc935d8e8c5418bb0e..3aa6c821449a90fd43d0169fb3bbcf410140602d 100644 (file)
@@ -19,6 +19,7 @@ config IA64
        select HAVE_OPROFILE
        select HAVE_KPROBES
        select HAVE_KRETPROBES
+       select HAVE_KVM
        default y
        help
          The Itanium Processor Family is Intel's 64-bit successor to
@@ -589,6 +590,8 @@ config MSPEC
 
 source "fs/Kconfig"
 
+source "arch/ia64/kvm/Kconfig"
+
 source "lib/Kconfig"
 
 #
index f1645c4f70393c5294ecc9148300c8368178d5f5..ec4cca477f491c31cf74b79f184e1fce812cf4dc 100644 (file)
@@ -57,6 +57,7 @@ core-$(CONFIG_IA64_GENERIC)   += arch/ia64/dig/
 core-$(CONFIG_IA64_HP_ZX1)     += arch/ia64/dig/
 core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/
 core-$(CONFIG_IA64_SGI_SN2)    += arch/ia64/sn/
+core-$(CONFIG_KVM)             += arch/ia64/kvm/
 
 drivers-$(CONFIG_PCI)          += arch/ia64/pci/
 drivers-$(CONFIG_IA64_HP_SIM)  += arch/ia64/hp/sim/
diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig
new file mode 100644 (file)
index 0000000..7914e48
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# KVM configuration
+#
+config HAVE_KVM
+       bool
+
+menuconfig VIRTUALIZATION
+       bool "Virtualization"
+       depends on HAVE_KVM || IA64
+       default y
+       ---help---
+         Say Y here to get to see options for using your Linux host to run other
+         operating systems inside virtual machines (guests).
+         This option alone does not add any kernel code.
+
+         If you say N, all options in this submenu will be skipped and disabled.
+
+if VIRTUALIZATION
+
+config KVM
+       tristate "Kernel-based Virtual Machine (KVM) support"
+       depends on HAVE_KVM && EXPERIMENTAL
+       select PREEMPT_NOTIFIERS
+       select ANON_INODES
+       ---help---
+         Support hosting fully virtualized guest machines using hardware
+         virtualization extensions.  You will need a fairly recent
+         processor equipped with virtualization extensions. You will also
+         need to select one or more of the processor modules below.
+
+         This module provides access to the hardware capabilities through
+         a character device node named /dev/kvm.
+
+         To compile this as a module, choose M here: the module
+         will be called kvm.
+
+         If unsure, say N.
+
+config KVM_INTEL
+       tristate "KVM for Intel Itanium 2 processors support"
+       depends on KVM && m
+       ---help---
+         Provides support for KVM on Itanium 2 processors equipped with the VT
+         extensions.
+
+config KVM_TRACE
+       bool
+
+endif # VIRTUALIZATION
diff --git a/arch/ia64/kvm/Makefile b/arch/ia64/kvm/Makefile
new file mode 100644 (file)
index 0000000..41b034f
--- /dev/null
@@ -0,0 +1,61 @@
+#This Make file is to generate asm-offsets.h and build source.
+#
+
+#Generate asm-offsets.h for vmm module build
+offsets-file := asm-offsets.h
+
+always  := $(offsets-file)
+targets := $(offsets-file)
+targets += arch/ia64/kvm/asm-offsets.s
+clean-files := $(addprefix $(objtree)/,$(targets) $(obj)/memcpy.S $(obj)/memset.S)
+
+# Default sed regexp - multiline due to syntax constraints
+define sed-y
+       "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"
+endef
+
+quiet_cmd_offsets = GEN     $@
+define cmd_offsets
+       (set -e; \
+        echo "#ifndef __ASM_KVM_OFFSETS_H__"; \
+        echo "#define __ASM_KVM_OFFSETS_H__"; \
+        echo "/*"; \
+        echo " * DO NOT MODIFY."; \
+        echo " *"; \
+        echo " * This file was generated by Makefile"; \
+        echo " *"; \
+        echo " */"; \
+        echo ""; \
+        sed -ne $(sed-y) $<; \
+        echo ""; \
+        echo "#endif" ) > $@
+endef
+# We use internal rules to avoid the "is up to date" message from make
+arch/ia64/kvm/asm-offsets.s: arch/ia64/kvm/asm-offsets.c
+       $(call if_changed_dep,cc_s_c)
+
+$(obj)/$(offsets-file): arch/ia64/kvm/asm-offsets.s
+       $(call cmd,offsets)
+
+#
+# Makefile for Kernel-based Virtual Machine module
+#
+
+EXTRA_CFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/
+
+$(addprefix $(objtree)/,$(obj)/memcpy.S $(obj)/memset.S):
+       $(shell ln -snf ../lib/memcpy.S $(src)/memcpy.S)
+       $(shell ln -snf ../lib/memset.S $(src)/memset.S)
+
+common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o)
+
+kvm-objs := $(common-objs) kvm-ia64.o kvm_fw.o
+obj-$(CONFIG_KVM) += kvm.o
+
+FORCE : $(obj)/$(offsets-file)
+EXTRA_CFLAGS_vcpu.o += -mfixed-range=f2-f5,f12-f127
+kvm-intel-objs = vmm.o vmm_ivt.o trampoline.o vcpu.o optvfault.o mmio.o \
+       vtlb.o process.o
+#Add link memcpy and memset to avoid possible structure assignment error
+kvm-intel-objs += memset.o memcpy.o
+obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
diff --git a/arch/ia64/kvm/asm-offsets.c b/arch/ia64/kvm/asm-offsets.c
new file mode 100644 (file)
index 0000000..4e3dc13
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * asm-offsets.c Generate definitions needed by assembly language modules.
+ * This code generates raw asm output which is post-processed
+ * to extract and format the required data.
+ *
+ * Anthony Xu    <anthony.xu@intel.com>
+ * Xiantao Zhang <xiantao.zhang@intel.com>
+ * Copyright (c) 2007 Intel Corporation  KVM support.
+ *
+ * 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., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <linux/autoconf.h>
+#include <linux/kvm_host.h>
+
+#include "vcpu.h"
+
+#define task_struct kvm_vcpu
+
+#define DEFINE(sym, val) \
+       asm volatile("\n->" #sym " (%0) " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : :)
+
+#define OFFSET(_sym, _str, _mem) \
+    DEFINE(_sym, offsetof(_str, _mem));
+
+void foo(void)
+{
+       DEFINE(VMM_TASK_SIZE, sizeof(struct kvm_vcpu));
+       DEFINE(VMM_PT_REGS_SIZE, sizeof(struct kvm_pt_regs));
+
+       BLANK();
+
+       DEFINE(VMM_VCPU_META_RR0_OFFSET,
+                       offsetof(struct kvm_vcpu, arch.metaphysical_rr0));
+       DEFINE(VMM_VCPU_META_SAVED_RR0_OFFSET,
+                       offsetof(struct kvm_vcpu,
+                               arch.metaphysical_saved_rr0));
+       DEFINE(VMM_VCPU_VRR0_OFFSET,
+                       offsetof(struct kvm_vcpu, arch.vrr[0]));
+       DEFINE(VMM_VPD_IRR0_OFFSET,
+                       offsetof(struct vpd, irr[0]));
+       DEFINE(VMM_VCPU_ITC_CHECK_OFFSET,
+                       offsetof(struct kvm_vcpu, arch.itc_check));
+       DEFINE(VMM_VCPU_IRQ_CHECK_OFFSET,
+                       offsetof(struct kvm_vcpu, arch.irq_check));
+       DEFINE(VMM_VPD_VHPI_OFFSET,
+                       offsetof(struct vpd, vhpi));
+       DEFINE(VMM_VCPU_VSA_BASE_OFFSET,
+                       offsetof(struct kvm_vcpu, arch.vsa_base));
+       DEFINE(VMM_VCPU_VPD_OFFSET,
+                       offsetof(struct kvm_vcpu, arch.vpd));
+       DEFINE(VMM_VCPU_IRQ_CHECK,
+                       offsetof(struct kvm_vcpu, arch.irq_check));
+       DEFINE(VMM_VCPU_TIMER_PENDING,
+                       offsetof(struct kvm_vcpu, arch.timer_pending));
+       DEFINE(VMM_VCPU_META_SAVED_RR0_OFFSET,
+                       offsetof(struct kvm_vcpu, arch.metaphysical_saved_rr0));
+       DEFINE(VMM_VCPU_MODE_FLAGS_OFFSET,
+                       offsetof(struct kvm_vcpu, arch.mode_flags));
+       DEFINE(VMM_VCPU_ITC_OFS_OFFSET,
+                       offsetof(struct kvm_vcpu, arch.itc_offset));
+       DEFINE(VMM_VCPU_LAST_ITC_OFFSET,
+                       offsetof(struct kvm_vcpu, arch.last_itc));
+       DEFINE(VMM_VCPU_SAVED_GP_OFFSET,
+                       offsetof(struct kvm_vcpu, arch.saved_gp));
+
+       BLANK();
+
+       DEFINE(VMM_PT_REGS_B6_OFFSET,
+                               offsetof(struct kvm_pt_regs, b6));
+       DEFINE(VMM_PT_REGS_B7_OFFSET,
+                               offsetof(struct kvm_pt_regs, b7));
+       DEFINE(VMM_PT_REGS_AR_CSD_OFFSET,
+                               offsetof(struct kvm_pt_regs, ar_csd));
+       DEFINE(VMM_PT_REGS_AR_SSD_OFFSET,
+                               offsetof(struct kvm_pt_regs, ar_ssd));
+       DEFINE(VMM_PT_REGS_R8_OFFSET,
+                               offsetof(struct kvm_pt_regs, r8));
+       DEFINE(VMM_PT_REGS_R9_OFFSET,
+                               offsetof(struct kvm_pt_regs, r9));
+       DEFINE(VMM_PT_REGS_R10_OFFSET,
+                               offsetof(struct kvm_pt_regs, r10));
+       DEFINE(VMM_PT_REGS_R11_OFFSET,
+                               offsetof(struct kvm_pt_regs, r11));
+       DEFINE(VMM_PT_REGS_CR_IPSR_OFFSET,
+                               offsetof(struct kvm_pt_regs, cr_ipsr));
+       DEFINE(VMM_PT_REGS_CR_IIP_OFFSET,
+                               offsetof(struct kvm_pt_regs, cr_iip));
+       DEFINE(VMM_PT_REGS_CR_IFS_OFFSET,
+                               offsetof(struct kvm_pt_regs, cr_ifs));
+       DEFINE(VMM_PT_REGS_AR_UNAT_OFFSET,
+                               offsetof(struct kvm_pt_regs, ar_unat));
+       DEFINE(VMM_PT_REGS_AR_PFS_OFFSET,
+                               offsetof(struct kvm_pt_regs, ar_pfs));
+       DEFINE(VMM_PT_REGS_AR_RSC_OFFSET,
+                               offsetof(struct kvm_pt_regs, ar_rsc));
+       DEFINE(VMM_PT_REGS_AR_RNAT_OFFSET,
+                               offsetof(struct kvm_pt_regs, ar_rnat));
+
+       DEFINE(VMM_PT_REGS_AR_BSPSTORE_OFFSET,
+                               offsetof(struct kvm_pt_regs, ar_bspstore));
+       DEFINE(VMM_PT_REGS_PR_OFFSET,
+                               offsetof(struct kvm_pt_regs, pr));
+       DEFINE(VMM_PT_REGS_B0_OFFSET,
+                               offsetof(struct kvm_pt_regs, b0));
+       DEFINE(VMM_PT_REGS_LOADRS_OFFSET,
+                               offsetof(struct kvm_pt_regs, loadrs));
+       DEFINE(VMM_PT_REGS_R1_OFFSET,
+                               offsetof(struct kvm_pt_regs, r1));
+       DEFINE(VMM_PT_REGS_R12_OFFSET,
+                               offsetof(struct kvm_pt_regs, r12));
+       DEFINE(VMM_PT_REGS_R13_OFFSET,
+                               offsetof(struct kvm_pt_regs, r13));
+       DEFINE(VMM_PT_REGS_AR_FPSR_OFFSET,
+                               offsetof(struct kvm_pt_regs, ar_fpsr));
+       DEFINE(VMM_PT_REGS_R15_OFFSET,
+                               offsetof(struct kvm_pt_regs, r15));
+       DEFINE(VMM_PT_REGS_R14_OFFSET,
+                               offsetof(struct kvm_pt_regs, r14));
+       DEFINE(VMM_PT_REGS_R2_OFFSET,
+                               offsetof(struct kvm_pt_regs, r2));
+       DEFINE(VMM_PT_REGS_R3_OFFSET,
+                               offsetof(struct kvm_pt_regs, r3));
+       DEFINE(VMM_PT_REGS_R16_OFFSET,
+                               offsetof(struct kvm_pt_regs, r16));
+       DEFINE(VMM_PT_REGS_R17_OFFSET,
+                               offsetof(struct kvm_pt_regs, r17));
+       DEFINE(VMM_PT_REGS_R18_OFFSET,
+                               offsetof(struct kvm_pt_regs, r18));
+       DEFINE(VMM_PT_REGS_R19_OFFSET,
+                               offsetof(struct kvm_pt_regs, r19));
+       DEFINE(VMM_PT_REGS_R20_OFFSET,
+                               offsetof(struct kvm_pt_regs, r20));
+       DEFINE(VMM_PT_REGS_R21_OFFSET,
+                               offsetof(struct kvm_pt_regs, r21));
+       DEFINE(VMM_PT_REGS_R22_OFFSET,
+                               offsetof(struct kvm_pt_regs, r22));
+       DEFINE(VMM_PT_REGS_R23_OFFSET,
+                               offsetof(struct kvm_pt_regs, r23));
+       DEFINE(VMM_PT_REGS_R24_OFFSET,
+                               offsetof(struct kvm_pt_regs, r24));
+       DEFINE(VMM_PT_REGS_R25_OFFSET,
+                               offsetof(struct kvm_pt_regs, r25));
+       DEFINE(VMM_PT_REGS_R26_OFFSET,
+                               offsetof(struct kvm_pt_regs, r26));
+       DEFINE(VMM_PT_REGS_R27_OFFSET,
+                               offsetof(struct kvm_pt_regs, r27));
+       DEFINE(VMM_PT_REGS_R28_OFFSET,
+                               offsetof(struct kvm_pt_regs, r28));
+       DEFINE(VMM_PT_REGS_R29_OFFSET,
+                               offsetof(struct kvm_pt_regs, r29));
+       DEFINE(VMM_PT_REGS_R30_OFFSET,
+                               offsetof(struct kvm_pt_regs, r30));
+       DEFINE(VMM_PT_REGS_R31_OFFSET,
+                               offsetof(struct kvm_pt_regs, r31));
+       DEFINE(VMM_PT_REGS_AR_CCV_OFFSET,
+                               offsetof(struct kvm_pt_regs, ar_ccv));
+       DEFINE(VMM_PT_REGS_F6_OFFSET,
+                               offsetof(struct kvm_pt_regs, f6));
+       DEFINE(VMM_PT_REGS_F7_OFFSET,
+                               offsetof(struct kvm_pt_regs, f7));
+       DEFINE(VMM_PT_REGS_F8_OFFSET,
+                               offsetof(struct kvm_pt_regs, f8));
+       DEFINE(VMM_PT_REGS_F9_OFFSET,
+                               offsetof(struct kvm_pt_regs, f9));
+       DEFINE(VMM_PT_REGS_F10_OFFSET,
+                               offsetof(struct kvm_pt_regs, f10));
+       DEFINE(VMM_PT_REGS_F11_OFFSET,
+                               offsetof(struct kvm_pt_regs, f11));
+       DEFINE(VMM_PT_REGS_R4_OFFSET,
+                               offsetof(struct kvm_pt_regs, r4));
+       DEFINE(VMM_PT_REGS_R5_OFFSET,
+                               offsetof(struct kvm_pt_regs, r5));
+       DEFINE(VMM_PT_REGS_R6_OFFSET,
+                               offsetof(struct kvm_pt_regs, r6));
+       DEFINE(VMM_PT_REGS_R7_OFFSET,
+                               offsetof(struct kvm_pt_regs, r7));
+       DEFINE(VMM_PT_REGS_EML_UNAT_OFFSET,
+                               offsetof(struct kvm_pt_regs, eml_unat));
+       DEFINE(VMM_VCPU_IIPA_OFFSET,
+                               offsetof(struct kvm_vcpu, arch.cr_iipa));
+       DEFINE(VMM_VCPU_OPCODE_OFFSET,
+                               offsetof(struct kvm_vcpu, arch.opcode));
+       DEFINE(VMM_VCPU_CAUSE_OFFSET, offsetof(struct kvm_vcpu, arch.cause));
+       DEFINE(VMM_VCPU_ISR_OFFSET,
+                               offsetof(struct kvm_vcpu, arch.cr_isr));
+       DEFINE(VMM_PT_REGS_R16_SLOT,
+                               (((offsetof(struct kvm_pt_regs, r16)
+                               - sizeof(struct kvm_pt_regs)) >> 3) & 0x3f));
+       DEFINE(VMM_VCPU_MODE_FLAGS_OFFSET,
+                               offsetof(struct kvm_vcpu, arch.mode_flags));
+       DEFINE(VMM_VCPU_GP_OFFSET, offsetof(struct kvm_vcpu, arch.__gp));
+       BLANK();
+
+       DEFINE(VMM_VPD_BASE_OFFSET, offsetof(struct kvm_vcpu, arch.vpd));
+       DEFINE(VMM_VPD_VIFS_OFFSET, offsetof(struct vpd, ifs));
+       DEFINE(VMM_VLSAPIC_INSVC_BASE_OFFSET,
+                       offsetof(struct kvm_vcpu, arch.insvc[0]));
+       DEFINE(VMM_VPD_VPTA_OFFSET, offsetof(struct vpd, pta));
+       DEFINE(VMM_VPD_VPSR_OFFSET, offsetof(struct vpd, vpsr));
+
+       DEFINE(VMM_CTX_R4_OFFSET, offsetof(union context, gr[4]));
+       DEFINE(VMM_CTX_R5_OFFSET, offsetof(union context, gr[5]));
+       DEFINE(VMM_CTX_R12_OFFSET, offsetof(union context, gr[12]));
+       DEFINE(VMM_CTX_R13_OFFSET, offsetof(union context, gr[13]));
+       DEFINE(VMM_CTX_KR0_OFFSET, offsetof(union context, ar[0]));
+       DEFINE(VMM_CTX_KR1_OFFSET, offsetof(union context, ar[1]));
+       DEFINE(VMM_CTX_B0_OFFSET, offsetof(union context, br[0]));
+       DEFINE(VMM_CTX_B1_OFFSET, offsetof(union context, br[1]));
+       DEFINE(VMM_CTX_B2_OFFSET, offsetof(union context, br[2]));
+       DEFINE(VMM_CTX_RR0_OFFSET, offsetof(union context, rr[0]));
+       DEFINE(VMM_CTX_RSC_OFFSET, offsetof(union context, ar[16]));
+       DEFINE(VMM_CTX_BSPSTORE_OFFSET, offsetof(union context, ar[18]));
+       DEFINE(VMM_CTX_RNAT_OFFSET, offsetof(union context, ar[19]));
+       DEFINE(VMM_CTX_FCR_OFFSET, offsetof(union context, ar[21]));
+       DEFINE(VMM_CTX_EFLAG_OFFSET, offsetof(union context, ar[24]));
+       DEFINE(VMM_CTX_CFLG_OFFSET, offsetof(union context, ar[27]));
+       DEFINE(VMM_CTX_FSR_OFFSET, offsetof(union context, ar[28]));
+       DEFINE(VMM_CTX_FIR_OFFSET, offsetof(union context, ar[29]));
+       DEFINE(VMM_CTX_FDR_OFFSET, offsetof(union context, ar[30]));
+       DEFINE(VMM_CTX_UNAT_OFFSET, offsetof(union context, ar[36]));
+       DEFINE(VMM_CTX_FPSR_OFFSET, offsetof(union context, ar[40]));
+       DEFINE(VMM_CTX_PFS_OFFSET, offsetof(union context, ar[64]));
+       DEFINE(VMM_CTX_LC_OFFSET, offsetof(union context, ar[65]));
+       DEFINE(VMM_CTX_DCR_OFFSET, offsetof(union context, cr[0]));
+       DEFINE(VMM_CTX_IVA_OFFSET, offsetof(union context, cr[2]));
+       DEFINE(VMM_CTX_PTA_OFFSET, offsetof(union context, cr[8]));
+       DEFINE(VMM_CTX_IBR0_OFFSET, offsetof(union context, ibr[0]));
+       DEFINE(VMM_CTX_DBR0_OFFSET, offsetof(union context, dbr[0]));
+       DEFINE(VMM_CTX_F2_OFFSET, offsetof(union context, fr[2]));
+       DEFINE(VMM_CTX_F3_OFFSET, offsetof(union context, fr[3]));
+       DEFINE(VMM_CTX_F32_OFFSET, offsetof(union context, fr[32]));
+       DEFINE(VMM_CTX_F33_OFFSET, offsetof(union context, fr[33]));
+       DEFINE(VMM_CTX_PKR0_OFFSET, offsetof(union context, pkr[0]));
+       DEFINE(VMM_CTX_PSR_OFFSET, offsetof(union context, psr));
+       BLANK();
+}
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
new file mode 100644 (file)
index 0000000..6df0732
--- /dev/null
@@ -0,0 +1,1806 @@
+
+/*
+ * kvm_ia64.c: Basic KVM suppport On Itanium series processors
+ *
+ *
+ *     Copyright (C) 2007, Intel Corporation.
+ *     Xiantao Zhang  (xiantao.zhang@intel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/percpu.h>
+#include <linux/gfp.h>
+#include <linux/fs.h>
+#include <linux/smp.h>
+#include <linux/kvm_host.h>
+#include <linux/kvm.h>
+#include <linux/bitops.h>
+#include <linux/hrtimer.h>
+#include <linux/uaccess.h>
+
+#include <asm/pgtable.h>
+#include <asm/gcc_intrin.h>
+#include <asm/pal.h>
+#include <asm/cacheflush.h>
+#include <asm/div64.h>
+#include <asm/tlb.h>
+
+#include "misc.h"
+#include "vti.h"
+#include "iodev.h"
+#include "ioapic.h"
+#include "lapic.h"
+
+static unsigned long kvm_vmm_base;
+static unsigned long kvm_vsa_base;
+static unsigned long kvm_vm_buffer;
+static unsigned long kvm_vm_buffer_size;
+unsigned long kvm_vmm_gp;
+
+static long vp_env_info;
+
+static struct kvm_vmm_info *kvm_vmm_info;
+
+static DEFINE_PER_CPU(struct kvm_vcpu *, last_vcpu);
+
+struct kvm_stats_debugfs_item debugfs_entries[] = {
+       { NULL }
+};
+
+
+struct fdesc{
+    unsigned long ip;
+    unsigned long gp;
+};
+
+static void kvm_flush_icache(unsigned long start, unsigned long len)
+{
+       int l;
+
+       for (l = 0; l < (len + 32); l += 32)
+               ia64_fc(start + l);
+
+       ia64_sync_i();
+       ia64_srlz_i();
+}
+
+static void kvm_flush_tlb_all(void)
+{
+       unsigned long i, j, count0, count1, stride0, stride1, addr;
+       long flags;
+
+       addr    = local_cpu_data->ptce_base;
+       count0  = local_cpu_data->ptce_count[0];
+       count1  = local_cpu_data->ptce_count[1];
+       stride0 = local_cpu_data->ptce_stride[0];
+       stride1 = local_cpu_data->ptce_stride[1];
+
+       local_irq_save(flags);
+       for (i = 0; i < count0; ++i) {
+               for (j = 0; j < count1; ++j) {
+                       ia64_ptce(addr);
+                       addr += stride1;
+               }
+               addr += stride0;
+       }
+       local_irq_restore(flags);
+       ia64_srlz_i();                  /* srlz.i implies srlz.d */
+}
+
+long ia64_pal_vp_create(u64 *vpd, u64 *host_iva, u64 *opt_handler)
+{
+       struct ia64_pal_retval iprv;
+
+       PAL_CALL_STK(iprv, PAL_VP_CREATE, (u64)vpd, (u64)host_iva,
+                       (u64)opt_handler);
+
+       return iprv.status;
+}
+
+static  DEFINE_SPINLOCK(vp_lock);
+
+void kvm_arch_hardware_enable(void *garbage)
+{
+       long  status;
+       long  tmp_base;
+       unsigned long pte;
+       unsigned long saved_psr;
+       int slot;
+
+       pte = pte_val(mk_pte_phys(__pa(kvm_vmm_base),
+                               PAGE_KERNEL));
+       local_irq_save(saved_psr);
+       slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
+       if (slot < 0)
+               return;
+       local_irq_restore(saved_psr);
+
+       spin_lock(&vp_lock);
+       status = ia64_pal_vp_init_env(kvm_vsa_base ?
+                               VP_INIT_ENV : VP_INIT_ENV_INITALIZE,
+                       __pa(kvm_vm_buffer), KVM_VM_BUFFER_BASE, &tmp_base);
+       if (status != 0) {
+               printk(KERN_WARNING"kvm: Failed to Enable VT Support!!!!\n");
+               return ;
+       }
+
+       if (!kvm_vsa_base) {
+               kvm_vsa_base = tmp_base;
+               printk(KERN_INFO"kvm: kvm_vsa_base:0x%lx\n", kvm_vsa_base);
+       }
+       spin_unlock(&vp_lock);
+       ia64_ptr_entry(0x3, slot);
+}
+
+void kvm_arch_hardware_disable(void *garbage)
+{
+
+       long status;
+       int slot;
+       unsigned long pte;
+       unsigned long saved_psr;
+       unsigned long host_iva = ia64_getreg(_IA64_REG_CR_IVA);
+
+       pte = pte_val(mk_pte_phys(__pa(kvm_vmm_base),
+                               PAGE_KERNEL));
+
+       local_irq_save(saved_psr);
+       slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
+       if (slot < 0)
+               return;
+       local_irq_restore(saved_psr);
+
+       status = ia64_pal_vp_exit_env(host_iva);
+       if (status)
+               printk(KERN_DEBUG"kvm: Failed to disable VT support! :%ld\n",
+                               status);
+       ia64_ptr_entry(0x3, slot);
+}
+
+void kvm_arch_check_processor_compat(void *rtn)
+{
+       *(int *)rtn = 0;
+}
+
+int kvm_dev_ioctl_check_extension(long ext)
+{
+
+       int r;
+
+       switch (ext) {
+       case KVM_CAP_IRQCHIP:
+       case KVM_CAP_USER_MEMORY:
+
+               r = 1;
+               break;
+       default:
+               r = 0;
+       }
+       return r;
+
+}
+
+static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu,
+                                       gpa_t addr)
+{
+       struct kvm_io_device *dev;
+
+       dev = kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr);
+
+       return dev;
+}
+
+static int handle_vm_error(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
+       kvm_run->hw.hardware_exit_reason = 1;
+       return 0;
+}
+
+static int handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       struct kvm_mmio_req *p;
+       struct kvm_io_device *mmio_dev;
+
+       p = kvm_get_vcpu_ioreq(vcpu);
+
+       if ((p->addr & PAGE_MASK) == IOAPIC_DEFAULT_BASE_ADDRESS)
+               goto mmio;
+       vcpu->mmio_needed = 1;
+       vcpu->mmio_phys_addr = kvm_run->mmio.phys_addr = p->addr;
+       vcpu->mmio_size = kvm_run->mmio.len = p->size;
+       vcpu->mmio_is_write = kvm_run->mmio.is_write = !p->dir;
+
+       if (vcpu->mmio_is_write)
+               memcpy(vcpu->mmio_data, &p->data, p->size);
+       memcpy(kvm_run->mmio.data, &p->data, p->size);
+       kvm_run->exit_reason = KVM_EXIT_MMIO;
+       return 0;
+mmio:
+       mmio_dev = vcpu_find_mmio_dev(vcpu, p->addr);
+       if (mmio_dev) {
+               if (!p->dir)
+                       kvm_iodevice_write(mmio_dev, p->addr, p->size,
+                                               &p->data);
+               else
+                       kvm_iodevice_read(mmio_dev, p->addr, p->size,
+                                               &p->data);
+
+       } else
+               printk(KERN_ERR"kvm: No iodevice found! addr:%lx\n", p->addr);
+       p->state = STATE_IORESP_READY;
+
+       return 1;
+}
+
+static int handle_pal_call(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       struct exit_ctl_data *p;
+
+       p = kvm_get_exit_data(vcpu);
+
+       if (p->exit_reason == EXIT_REASON_PAL_CALL)
+               return kvm_pal_emul(vcpu, kvm_run);
+       else {
+               kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
+               kvm_run->hw.hardware_exit_reason = 2;
+               return 0;
+       }
+}
+
+static int handle_sal_call(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       struct exit_ctl_data *p;
+
+       p = kvm_get_exit_data(vcpu);
+
+       if (p->exit_reason == EXIT_REASON_SAL_CALL) {
+               kvm_sal_emul(vcpu);
+               return 1;
+       } else {
+               kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
+               kvm_run->hw.hardware_exit_reason = 3;
+               return 0;
+       }
+
+}
+
+/*
+ *  offset: address offset to IPI space.
+ *  value:  deliver value.
+ */
+static void vcpu_deliver_ipi(struct kvm_vcpu *vcpu, uint64_t dm,
+                               uint64_t vector)
+{
+       switch (dm) {
+       case SAPIC_FIXED:
+               kvm_apic_set_irq(vcpu, vector, 0);
+               break;
+       case SAPIC_NMI:
+               kvm_apic_set_irq(vcpu, 2, 0);
+               break;
+       case SAPIC_EXTINT:
+               kvm_apic_set_irq(vcpu, 0, 0);
+               break;
+       case SAPIC_INIT:
+       case SAPIC_PMI:
+       default:
+               printk(KERN_ERR"kvm: Unimplemented Deliver reserved IPI!\n");
+               break;
+       }
+}
+
+static struct kvm_vcpu *lid_to_vcpu(struct kvm *kvm, unsigned long id,
+                       unsigned long eid)
+{
+       union ia64_lid lid;
+       int i;
+
+       for (i = 0; i < KVM_MAX_VCPUS; i++) {
+               if (kvm->vcpus[i]) {
+                       lid.val = VCPU_LID(kvm->vcpus[i]);
+                       if (lid.id == id && lid.eid == eid)
+                               return kvm->vcpus[i];
+               }
+       }
+
+       return NULL;
+}
+
+static int handle_ipi(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       struct exit_ctl_data *p = kvm_get_exit_data(vcpu);
+       struct kvm_vcpu *target_vcpu;
+       struct kvm_pt_regs *regs;
+       union ia64_ipi_a addr = p->u.ipi_data.addr;
+       union ia64_ipi_d data = p->u.ipi_data.data;
+
+       target_vcpu = lid_to_vcpu(vcpu->kvm, addr.id, addr.eid);
+       if (!target_vcpu)
+               return handle_vm_error(vcpu, kvm_run);
+
+       if (!target_vcpu->arch.launched) {
+               regs = vcpu_regs(target_vcpu);
+
+               regs->cr_iip = vcpu->kvm->arch.rdv_sal_data.boot_ip;
+               regs->r1 = vcpu->kvm->arch.rdv_sal_data.boot_gp;
+
+               target_vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+               if (waitqueue_active(&target_vcpu->wq))
+                       wake_up_interruptible(&target_vcpu->wq);
+       } else {
+               vcpu_deliver_ipi(target_vcpu, data.dm, data.vector);
+               if (target_vcpu != vcpu)
+                       kvm_vcpu_kick(target_vcpu);
+       }
+
+       return 1;
+}
+
+struct call_data {
+       struct kvm_ptc_g ptc_g_data;
+       struct kvm_vcpu *vcpu;
+};
+
+static void vcpu_global_purge(void *info)
+{
+       struct call_data *p = (struct call_data *)info;
+       struct kvm_vcpu *vcpu = p->vcpu;
+
+       if (test_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests))
+               return;
+
+       set_bit(KVM_REQ_PTC_G, &vcpu->requests);
+       if (vcpu->arch.ptc_g_count < MAX_PTC_G_NUM) {
+               vcpu->arch.ptc_g_data[vcpu->arch.ptc_g_count++] =
+                                                       p->ptc_g_data;
+       } else {
+               clear_bit(KVM_REQ_PTC_G, &vcpu->requests);
+               vcpu->arch.ptc_g_count = 0;
+               set_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests);
+       }
+}
+
+static int handle_global_purge(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       struct exit_ctl_data *p = kvm_get_exit_data(vcpu);
+       struct kvm *kvm = vcpu->kvm;
+       struct call_data call_data;
+       int i;
+       call_data.ptc_g_data = p->u.ptc_g_data;
+
+       for (i = 0; i < KVM_MAX_VCPUS; i++) {
+               if (!kvm->vcpus[i] || kvm->vcpus[i]->arch.mp_state ==
+                                               KVM_MP_STATE_UNINITIALIZED ||
+                                       vcpu == kvm->vcpus[i])
+                       continue;
+
+               if (waitqueue_active(&kvm->vcpus[i]->wq))
+                       wake_up_interruptible(&kvm->vcpus[i]->wq);
+
+               if (kvm->vcpus[i]->cpu != -1) {
+                       call_data.vcpu = kvm->vcpus[i];
+                       smp_call_function_single(kvm->vcpus[i]->cpu,
+                                       vcpu_global_purge, &call_data, 0, 1);
+               } else
+                       printk(KERN_WARNING"kvm: Uninit vcpu received ipi!\n");
+
+       }
+       return 1;
+}
+
+static int handle_switch_rr6(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       return 1;
+}
+
+int kvm_emulate_halt(struct kvm_vcpu *vcpu)
+{
+
+       ktime_t kt;
+       long itc_diff;
+       unsigned long vcpu_now_itc;
+
+       unsigned long expires;
+       struct hrtimer *p_ht = &vcpu->arch.hlt_timer;
+       unsigned long cyc_per_usec = local_cpu_data->cyc_per_usec;
+       struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
+
+       vcpu_now_itc = ia64_getreg(_IA64_REG_AR_ITC) + vcpu->arch.itc_offset;
+
+       if (time_after(vcpu_now_itc, vpd->itm)) {
+               vcpu->arch.timer_check = 1;
+               return 1;
+       }
+       itc_diff = vpd->itm - vcpu_now_itc;
+       if (itc_diff < 0)
+               itc_diff = -itc_diff;
+
+       expires = div64_64(itc_diff, cyc_per_usec);
+       kt = ktime_set(0, 1000 * expires);
+       vcpu->arch.ht_active = 1;
+       hrtimer_start(p_ht, kt, HRTIMER_MODE_ABS);
+
+       if (irqchip_in_kernel(vcpu->kvm)) {
+               vcpu->arch.mp_state = KVM_MP_STATE_HALTED;
+               kvm_vcpu_block(vcpu);
+               hrtimer_cancel(p_ht);
+               vcpu->arch.ht_active = 0;
+
+               if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
+                       return -EINTR;
+               return 1;
+       } else {
+               printk(KERN_ERR"kvm: Unsupported userspace halt!");
+               return 0;
+       }
+}
+
+static int handle_vm_shutdown(struct kvm_vcpu *vcpu,
+               struct kvm_run *kvm_run)
+{
+       kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
+       return 0;
+}
+
+static int handle_external_interrupt(struct kvm_vcpu *vcpu,
+               struct kvm_run *kvm_run)
+{
+       return 1;
+}
+
+static int (*kvm_vti_exit_handlers[])(struct kvm_vcpu *vcpu,
+               struct kvm_run *kvm_run) = {
+       [EXIT_REASON_VM_PANIC]              = handle_vm_error,
+       [EXIT_REASON_MMIO_INSTRUCTION]      = handle_mmio,
+       [EXIT_REASON_PAL_CALL]              = handle_pal_call,
+       [EXIT_REASON_SAL_CALL]              = handle_sal_call,
+       [EXIT_REASON_SWITCH_RR6]            = handle_switch_rr6,
+       [EXIT_REASON_VM_DESTROY]            = handle_vm_shutdown,
+       [EXIT_REASON_EXTERNAL_INTERRUPT]    = handle_external_interrupt,
+       [EXIT_REASON_IPI]                   = handle_ipi,
+       [EXIT_REASON_PTC_G]                 = handle_global_purge,
+
+};
+
+static const int kvm_vti_max_exit_handlers =
+               sizeof(kvm_vti_exit_handlers)/sizeof(*kvm_vti_exit_handlers);
+
+static void kvm_prepare_guest_switch(struct kvm_vcpu *vcpu)
+{
+}
+
+static uint32_t kvm_get_exit_reason(struct kvm_vcpu *vcpu)
+{
+       struct exit_ctl_data *p_exit_data;
+
+       p_exit_data = kvm_get_exit_data(vcpu);
+       return p_exit_data->exit_reason;
+}
+
+/*
+ * The guest has exited.  See if we can fix it or if we need userspace
+ * assistance.
+ */
+static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+{
+       u32 exit_reason = kvm_get_exit_reason(vcpu);
+       vcpu->arch.last_exit = exit_reason;
+
+       if (exit_reason < kvm_vti_max_exit_handlers
+                       && kvm_vti_exit_handlers[exit_reason])
+               return kvm_vti_exit_handlers[exit_reason](vcpu, kvm_run);
+       else {
+               kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
+               kvm_run->hw.hardware_exit_reason = exit_reason;
+       }
+       return 0;
+}
+
+static inline void vti_set_rr6(unsigned long rr6)
+{
+       ia64_set_rr(RR6, rr6);
+       ia64_srlz_i();
+}
+
+static int kvm_insert_vmm_mapping(struct kvm_vcpu *vcpu)
+{
+       unsigned long pte;
+       struct kvm *kvm = vcpu->kvm;
+       int r;
+
+       /*Insert a pair of tr to map vmm*/
+       pte = pte_val(mk_pte_phys(__pa(kvm_vmm_base), PAGE_KERNEL));
+       r = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
+       if (r < 0)
+               goto out;
+       vcpu->arch.vmm_tr_slot = r;
+       /*Insert a pairt of tr to map data of vm*/
+       pte = pte_val(mk_pte_phys(__pa(kvm->arch.vm_base), PAGE_KERNEL));
+       r = ia64_itr_entry(0x3, KVM_VM_DATA_BASE,
+                                       pte, KVM_VM_DATA_SHIFT);
+       if (r < 0)
+               goto out;
+       vcpu->arch.vm_tr_slot = r;
+       r = 0;
+out:
+       return r;
+
+}
+
+static void kvm_purge_vmm_mapping(struct kvm_vcpu *vcpu)
+{
+
+       ia64_ptr_entry(0x3, vcpu->arch.vmm_tr_slot);
+       ia64_ptr_entry(0x3, vcpu->arch.vm_tr_slot);
+
+}
+
+static int kvm_vcpu_pre_transition(struct kvm_vcpu *vcpu)
+{
+       int cpu = smp_processor_id();
+
+       if (vcpu->arch.last_run_cpu != cpu ||
+                       per_cpu(last_vcpu, cpu) != vcpu) {
+               per_cpu(last_vcpu, cpu) = vcpu;
+               vcpu->arch.last_run_cpu = cpu;
+               kvm_flush_tlb_all();
+       }
+
+       vcpu->arch.host_rr6 = ia64_get_rr(RR6);
+       vti_set_rr6(vcpu->arch.vmm_rr);
+       return kvm_insert_vmm_mapping(vcpu);
+}
+static void kvm_vcpu_post_transition(struct kvm_vcpu *vcpu)
+{
+       kvm_purge_vmm_mapping(vcpu);
+       vti_set_rr6(vcpu->arch.host_rr6);
+}
+
+static int  vti_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       union context *host_ctx, *guest_ctx;
+       int r;
+
+       /*Get host and guest context with guest address space.*/
+       host_ctx = kvm_get_host_context(vcpu);
+       guest_ctx = kvm_get_guest_context(vcpu);
+
+       r = kvm_vcpu_pre_transition(vcpu);
+       if (r < 0)
+               goto out;
+       kvm_vmm_info->tramp_entry(host_ctx, guest_ctx);
+       kvm_vcpu_post_transition(vcpu);
+       r = 0;
+out:
+       return r;
+}
+
+static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       int r;
+
+again:
+       preempt_disable();
+
+       kvm_prepare_guest_switch(vcpu);
+       local_irq_disable();
+
+       if (signal_pending(current)) {
+               local_irq_enable();
+               preempt_enable();
+               r = -EINTR;
+               kvm_run->exit_reason = KVM_EXIT_INTR;
+               goto out;
+       }
+
+       vcpu->guest_mode = 1;
+       kvm_guest_enter();
+
+       r = vti_vcpu_run(vcpu, kvm_run);
+       if (r < 0) {
+               local_irq_enable();
+               preempt_enable();
+               kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+               goto out;
+       }
+
+       vcpu->arch.launched = 1;
+       vcpu->guest_mode = 0;
+       local_irq_enable();
+
+       /*
+        * We must have an instruction between local_irq_enable() and
+        * kvm_guest_exit(), so the timer interrupt isn't delayed by
+        * the interrupt shadow.  The stat.exits increment will do nicely.
+        * But we need to prevent reordering, hence this barrier():
+        */
+       barrier();
+
+       kvm_guest_exit();
+
+       preempt_enable();
+
+       r = kvm_handle_exit(kvm_run, vcpu);
+
+       if (r > 0) {
+               if (!need_resched())
+                       goto again;
+       }
+
+out:
+       if (r > 0) {
+               kvm_resched(vcpu);
+               goto again;
+       }
+
+       return r;
+}
+
+static void kvm_set_mmio_data(struct kvm_vcpu *vcpu)
+{
+       struct kvm_mmio_req *p = kvm_get_vcpu_ioreq(vcpu);
+
+       if (!vcpu->mmio_is_write)
+               memcpy(&p->data, vcpu->mmio_data, 8);
+       p->state = STATE_IORESP_READY;
+}
+
+int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       int r;
+       sigset_t sigsaved;
+
+       vcpu_load(vcpu);
+
+       if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)) {
+               kvm_vcpu_block(vcpu);
+               vcpu_put(vcpu);
+               return -EAGAIN;
+       }
+
+       if (vcpu->sigset_active)
+               sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
+
+       if (vcpu->mmio_needed) {
+               memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8);
+               kvm_set_mmio_data(vcpu);
+               vcpu->mmio_read_completed = 1;
+               vcpu->mmio_needed = 0;
+       }
+       r = __vcpu_run(vcpu, kvm_run);
+
+       if (vcpu->sigset_active)
+               sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+       vcpu_put(vcpu);
+       return r;
+}
+
+/*
+ * Allocate 16M memory for every vm to hold its specific data.
+ * Its memory map is defined in kvm_host.h.
+ */
+static struct kvm *kvm_alloc_kvm(void)
+{
+
+       struct kvm *kvm;
+       uint64_t  vm_base;
+
+       vm_base = __get_free_pages(GFP_KERNEL, get_order(KVM_VM_DATA_SIZE));
+
+       if (!vm_base)
+               return ERR_PTR(-ENOMEM);
+       printk(KERN_DEBUG"kvm: VM data's base Address:0x%lx\n", vm_base);
+
+       /* Zero all pages before use! */
+       memset((void *)vm_base, 0, KVM_VM_DATA_SIZE);
+
+       kvm = (struct kvm *)(vm_base + KVM_VM_OFS);
+       kvm->arch.vm_base = vm_base;
+
+       return kvm;
+}
+
+struct kvm_io_range {
+       unsigned long start;
+       unsigned long size;
+       unsigned long type;
+};
+
+static const struct kvm_io_range io_ranges[] = {
+       {VGA_IO_START, VGA_IO_SIZE, GPFN_FRAME_BUFFER},
+       {MMIO_START, MMIO_SIZE, GPFN_LOW_MMIO},
+       {LEGACY_IO_START, LEGACY_IO_SIZE, GPFN_LEGACY_IO},
+       {IO_SAPIC_START, IO_SAPIC_SIZE, GPFN_IOSAPIC},
+       {PIB_START, PIB_SIZE, GPFN_PIB},
+};
+
+static void kvm_build_io_pmt(struct kvm *kvm)
+{
+       unsigned long i, j;
+
+       /* Mark I/O ranges */
+       for (i = 0; i < (sizeof(io_ranges) / sizeof(struct kvm_io_range));
+                                                       i++) {
+               for (j = io_ranges[i].start;
+                               j < io_ranges[i].start + io_ranges[i].size;
+                               j += PAGE_SIZE)
+                       kvm_set_pmt_entry(kvm, j >> PAGE_SHIFT,
+                                       io_ranges[i].type, 0);
+       }
+
+}
+
+/*Use unused rids to virtualize guest rid.*/
+#define GUEST_PHYSICAL_RR0     0x1739
+#define GUEST_PHYSICAL_RR4     0x2739
+#define VMM_INIT_RR            0x1660
+
+static void kvm_init_vm(struct kvm *kvm)
+{
+       long vm_base;
+
+       BUG_ON(!kvm);
+
+       kvm->arch.metaphysical_rr0 = GUEST_PHYSICAL_RR0;
+       kvm->arch.metaphysical_rr4 = GUEST_PHYSICAL_RR4;
+       kvm->arch.vmm_init_rr = VMM_INIT_RR;
+
+       vm_base = kvm->arch.vm_base;
+       if (vm_base) {
+               kvm->arch.vhpt_base = vm_base + KVM_VHPT_OFS;
+               kvm->arch.vtlb_base = vm_base + KVM_VTLB_OFS;
+               kvm->arch.vpd_base  = vm_base + KVM_VPD_OFS;
+       }
+
+       /*
+        *Fill P2M entries for MMIO/IO ranges
+        */
+       kvm_build_io_pmt(kvm);
+
+}
+
+struct  kvm *kvm_arch_create_vm(void)
+{
+       struct kvm *kvm = kvm_alloc_kvm();
+
+       if (IS_ERR(kvm))
+               return ERR_PTR(-ENOMEM);
+       kvm_init_vm(kvm);
+
+       return kvm;
+
+}
+
+static int kvm_vm_ioctl_get_irqchip(struct kvm *kvm,
+                                       struct kvm_irqchip *chip)
+{
+       int r;
+
+       r = 0;
+       switch (chip->chip_id) {
+       case KVM_IRQCHIP_IOAPIC:
+               memcpy(&chip->chip.ioapic, ioapic_irqchip(kvm),
+                               sizeof(struct kvm_ioapic_state));
+               break;
+       default:
+               r = -EINVAL;
+               break;
+       }
+       return r;
+}
+
+static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, struct kvm_irqchip *chip)
+{
+       int r;
+
+       r = 0;
+       switch (chip->chip_id) {
+       case KVM_IRQCHIP_IOAPIC:
+               memcpy(ioapic_irqchip(kvm),
+                               &chip->chip.ioapic,
+                               sizeof(struct kvm_ioapic_state));
+               break;
+       default:
+               r = -EINVAL;
+               break;
+       }
+       return r;
+}
+
+#define RESTORE_REGS(_x) vcpu->arch._x = regs->_x
+
+int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+       int i;
+       struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
+       int r;
+
+       vcpu_load(vcpu);
+
+       for (i = 0; i < 16; i++) {
+               vpd->vgr[i] = regs->vpd.vgr[i];
+               vpd->vbgr[i] = regs->vpd.vbgr[i];
+       }
+       for (i = 0; i < 128; i++)
+               vpd->vcr[i] = regs->vpd.vcr[i];
+       vpd->vhpi = regs->vpd.vhpi;
+       vpd->vnat = regs->vpd.vnat;
+       vpd->vbnat = regs->vpd.vbnat;
+       vpd->vpsr = regs->vpd.vpsr;
+
+       vpd->vpr = regs->vpd.vpr;
+
+       r = -EFAULT;
+       r = copy_from_user(&vcpu->arch.guest, regs->saved_guest,
+                                               sizeof(union context));
+       if (r)
+               goto out;
+       r = copy_from_user(vcpu + 1, regs->saved_stack +
+                       sizeof(struct kvm_vcpu),
+                       IA64_STK_OFFSET - sizeof(struct kvm_vcpu));
+       if (r)
+               goto out;
+       vcpu->arch.exit_data =
+               ((struct kvm_vcpu *)(regs->saved_stack))->arch.exit_data;
+
+       RESTORE_REGS(mp_state);
+       RESTORE_REGS(vmm_rr);
+       memcpy(vcpu->arch.itrs, regs->itrs, sizeof(struct thash_data) * NITRS);
+       memcpy(vcpu->arch.dtrs, regs->dtrs, sizeof(struct thash_data) * NDTRS);
+       RESTORE_REGS(itr_regions);
+       RESTORE_REGS(dtr_regions);
+       RESTORE_REGS(tc_regions);
+       RESTORE_REGS(irq_check);
+       RESTORE_REGS(itc_check);
+       RESTORE_REGS(timer_check);
+       RESTORE_REGS(timer_pending);
+       RESTORE_REGS(last_itc);
+       for (i = 0; i < 8; i++) {
+               vcpu->arch.vrr[i] = regs->vrr[i];
+               vcpu->arch.ibr[i] = regs->ibr[i];
+               vcpu->arch.dbr[i] = regs->dbr[i];
+       }
+       for (i = 0; i < 4; i++)
+               vcpu->arch.insvc[i] = regs->insvc[i];
+       RESTORE_REGS(xtp);
+       RESTORE_REGS(metaphysical_rr0);
+       RESTORE_REGS(metaphysical_rr4);
+       RESTORE_REGS(metaphysical_saved_rr0);
+       RESTORE_REGS(metaphysical_saved_rr4);
+       RESTORE_REGS(fp_psr);
+       RESTORE_REGS(saved_gp);
+
+       vcpu->arch.irq_new_pending = 1;
+       vcpu->arch.itc_offset = regs->saved_itc - ia64_getreg(_IA64_REG_AR_ITC);
+       set_bit(KVM_REQ_RESUME, &vcpu->requests);
+
+       vcpu_put(vcpu);
+       r = 0;
+out:
+       return r;
+}
+
+long kvm_arch_vm_ioctl(struct file *filp,
+               unsigned int ioctl, unsigned long arg)
+{
+       struct kvm *kvm = filp->private_data;
+       void __user *argp = (void __user *)arg;
+       int r = -EINVAL;
+
+       switch (ioctl) {
+       case KVM_SET_MEMORY_REGION: {
+               struct kvm_memory_region kvm_mem;
+               struct kvm_userspace_memory_region kvm_userspace_mem;
+
+               r = -EFAULT;
+               if (copy_from_user(&kvm_mem, argp, sizeof kvm_mem))
+                       goto out;
+               kvm_userspace_mem.slot = kvm_mem.slot;
+               kvm_userspace_mem.flags = kvm_mem.flags;
+               kvm_userspace_mem.guest_phys_addr =
+                                       kvm_mem.guest_phys_addr;
+               kvm_userspace_mem.memory_size = kvm_mem.memory_size;
+               r = kvm_vm_ioctl_set_memory_region(kvm,
+                                       &kvm_userspace_mem, 0);
+               if (r)
+                       goto out;
+               break;
+               }
+       case KVM_CREATE_IRQCHIP:
+               r = -EFAULT;
+               r = kvm_ioapic_init(kvm);
+               if (r)
+                       goto out;
+               break;
+       case KVM_IRQ_LINE: {
+               struct kvm_irq_level irq_event;
+
+               r = -EFAULT;
+               if (copy_from_user(&irq_event, argp, sizeof irq_event))
+                       goto out;
+               if (irqchip_in_kernel(kvm)) {
+                       mutex_lock(&kvm->lock);
+                       kvm_ioapic_set_irq(kvm->arch.vioapic,
+                                               irq_event.irq,
+                                               irq_event.level);
+                       mutex_unlock(&kvm->lock);
+                       r = 0;
+               }
+               break;
+               }
+       case KVM_GET_IRQCHIP: {
+               /* 0: PIC master, 1: PIC slave, 2: IOAPIC */
+               struct kvm_irqchip chip;
+
+               r = -EFAULT;
+               if (copy_from_user(&chip, argp, sizeof chip))
+                               goto out;
+               r = -ENXIO;
+               if (!irqchip_in_kernel(kvm))
+                       goto out;
+               r = kvm_vm_ioctl_get_irqchip(kvm, &chip);
+               if (r)
+                       goto out;
+               r = -EFAULT;
+               if (copy_to_user(argp, &chip, sizeof chip))
+                               goto out;
+               r = 0;
+               break;
+               }
+       case KVM_SET_IRQCHIP: {
+               /* 0: PIC master, 1: PIC slave, 2: IOAPIC */
+               struct kvm_irqchip chip;
+
+               r = -EFAULT;
+               if (copy_from_user(&chip, argp, sizeof chip))
+                               goto out;
+               r = -ENXIO;
+               if (!irqchip_in_kernel(kvm))
+                       goto out;
+               r = kvm_vm_ioctl_set_irqchip(kvm, &chip);
+               if (r)
+                       goto out;
+               r = 0;
+               break;
+               }
+       default:
+               ;
+       }
+out:
+       return r;
+}
+
+int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
+               struct kvm_sregs *sregs)
+{
+       return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
+               struct kvm_sregs *sregs)
+{
+       return -EINVAL;
+
+}
+int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
+               struct kvm_translation *tr)
+{
+
+       return -EINVAL;
+}
+
+static int kvm_alloc_vmm_area(void)
+{
+       if (!kvm_vmm_base && (kvm_vm_buffer_size < KVM_VM_BUFFER_SIZE)) {
+               kvm_vmm_base = __get_free_pages(GFP_KERNEL,
+                               get_order(KVM_VMM_SIZE));
+               if (!kvm_vmm_base)
+                       return -ENOMEM;
+
+               memset((void *)kvm_vmm_base, 0, KVM_VMM_SIZE);
+               kvm_vm_buffer = kvm_vmm_base + VMM_SIZE;
+
+               printk(KERN_DEBUG"kvm:VMM's Base Addr:0x%lx, vm_buffer:0x%lx\n",
+                               kvm_vmm_base, kvm_vm_buffer);
+       }
+
+       return 0;
+}
+
+static void kvm_free_vmm_area(void)
+{
+       if (kvm_vmm_base) {
+               /*Zero this area before free to avoid bits leak!!*/
+               memset((void *)kvm_vmm_base, 0, KVM_VMM_SIZE);
+               free_pages(kvm_vmm_base, get_order(KVM_VMM_SIZE));
+               kvm_vmm_base  = 0;
+               kvm_vm_buffer = 0;
+               kvm_vsa_base = 0;
+       }
+}
+
+/*
+ * Make sure that a cpu that is being hot-unplugged does not have any vcpus
+ * cached on it. Leave it as blank for IA64.
+ */
+void decache_vcpus_on_cpu(int cpu)
+{
+}
+
+static void vti_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+}
+
+static int vti_init_vpd(struct kvm_vcpu *vcpu)
+{
+       int i;
+       union cpuid3_t cpuid3;
+       struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
+
+       if (IS_ERR(vpd))
+               return PTR_ERR(vpd);
+
+       /* CPUID init */
+       for (i = 0; i < 5; i++)
+               vpd->vcpuid[i] = ia64_get_cpuid(i);
+
+       /* Limit the CPUID number to 5 */
+       cpuid3.value = vpd->vcpuid[3];
+       cpuid3.number = 4;      /* 5 - 1 */
+       vpd->vcpuid[3] = cpuid3.value;
+
+       /*Set vac and vdc fields*/
+       vpd->vac.a_from_int_cr = 1;
+       vpd->vac.a_to_int_cr = 1;
+       vpd->vac.a_from_psr = 1;
+       vpd->vac.a_from_cpuid = 1;
+       vpd->vac.a_cover = 1;
+       vpd->vac.a_bsw = 1;
+       vpd->vac.a_int = 1;
+       vpd->vdc.d_vmsw = 1;
+
+       /*Set virtual buffer*/
+       vpd->virt_env_vaddr = KVM_VM_BUFFER_BASE;
+
+       return 0;
+}
+
+static int vti_create_vp(struct kvm_vcpu *vcpu)
+{
+       long ret;
+       struct vpd *vpd = vcpu->arch.vpd;
+       unsigned long  vmm_ivt;
+
+       vmm_ivt = kvm_vmm_info->vmm_ivt;
+
+       printk(KERN_DEBUG "kvm: vcpu:%p,ivt: 0x%lx\n", vcpu, vmm_ivt);
+
+       ret = ia64_pal_vp_create((u64 *)vpd, (u64 *)vmm_ivt, 0);
+
+       if (ret) {
+               printk(KERN_ERR"kvm: ia64_pal_vp_create failed!\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static void init_ptce_info(struct kvm_vcpu *vcpu)
+{
+       ia64_ptce_info_t ptce = {0};
+
+       ia64_get_ptce(&ptce);
+       vcpu->arch.ptce_base = ptce.base;
+       vcpu->arch.ptce_count[0] = ptce.count[0];
+       vcpu->arch.ptce_count[1] = ptce.count[1];
+       vcpu->arch.ptce_stride[0] = ptce.stride[0];
+       vcpu->arch.ptce_stride[1] = ptce.stride[1];
+}
+
+static void kvm_migrate_hlt_timer(struct kvm_vcpu *vcpu)
+{
+       struct hrtimer *p_ht = &vcpu->arch.hlt_timer;
+
+       if (hrtimer_cancel(p_ht))
+               hrtimer_start(p_ht, p_ht->expires, HRTIMER_MODE_ABS);
+}
+
+static enum hrtimer_restart hlt_timer_fn(struct hrtimer *data)
+{
+       struct kvm_vcpu *vcpu;
+       wait_queue_head_t *q;
+
+       vcpu  = container_of(data, struct kvm_vcpu, arch.hlt_timer);
+       if (vcpu->arch.mp_state != KVM_MP_STATE_HALTED)
+               goto out;
+
+       q = &vcpu->wq;
+       if (waitqueue_active(q)) {
+               vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+               wake_up_interruptible(q);
+       }
+out:
+       vcpu->arch.timer_check = 1;
+       return HRTIMER_NORESTART;
+}
+
+#define PALE_RESET_ENTRY    0x80000000ffffffb0UL
+
+int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
+{
+       struct kvm_vcpu *v;
+       int r;
+       int i;
+       long itc_offset;
+       struct kvm *kvm = vcpu->kvm;
+       struct kvm_pt_regs *regs = vcpu_regs(vcpu);
+
+       union context *p_ctx = &vcpu->arch.guest;
+       struct kvm_vcpu *vmm_vcpu = to_guest(vcpu->kvm, vcpu);
+
+       /*Init vcpu context for first run.*/
+       if (IS_ERR(vmm_vcpu))
+               return PTR_ERR(vmm_vcpu);
+
+       if (vcpu->vcpu_id == 0) {
+               vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+
+               /*Set entry address for first run.*/
+               regs->cr_iip = PALE_RESET_ENTRY;
+
+               /*Initilize itc offset for vcpus*/
+               itc_offset = 0UL - ia64_getreg(_IA64_REG_AR_ITC);
+               for (i = 0; i < MAX_VCPU_NUM; i++) {
+                       v = (struct kvm_vcpu *)((char *)vcpu + VCPU_SIZE * i);
+                       v->arch.itc_offset = itc_offset;
+                       v->arch.last_itc = 0;
+               }
+       } else
+               vcpu->arch.mp_state = KVM_MP_STATE_UNINITIALIZED;
+
+       r = -ENOMEM;
+       vcpu->arch.apic = kzalloc(sizeof(struct kvm_lapic), GFP_KERNEL);
+       if (!vcpu->arch.apic)
+               goto out;
+       vcpu->arch.apic->vcpu = vcpu;
+
+       p_ctx->gr[1] = 0;
+       p_ctx->gr[12] = (unsigned long)((char *)vmm_vcpu + IA64_STK_OFFSET);
+       p_ctx->gr[13] = (unsigned long)vmm_vcpu;
+       p_ctx->psr = 0x1008522000UL;
+       p_ctx->ar[40] = FPSR_DEFAULT; /*fpsr*/
+       p_ctx->caller_unat = 0;
+       p_ctx->pr = 0x0;
+       p_ctx->ar[36] = 0x0; /*unat*/
+       p_ctx->ar[19] = 0x0; /*rnat*/
+       p_ctx->ar[18] = (unsigned long)vmm_vcpu +
+                               ((sizeof(struct kvm_vcpu)+15) & ~15);
+       p_ctx->ar[64] = 0x0; /*pfs*/
+       p_ctx->cr[0] = 0x7e04UL;
+       p_ctx->cr[2] = (unsigned long)kvm_vmm_info->vmm_ivt;
+       p_ctx->cr[8] = 0x3c;
+
+       /*Initilize region register*/
+       p_ctx->rr[0] = 0x30;
+       p_ctx->rr[1] = 0x30;
+       p_ctx->rr[2] = 0x30;
+       p_ctx->rr[3] = 0x30;
+       p_ctx->rr[4] = 0x30;
+       p_ctx->rr[5] = 0x30;
+       p_ctx->rr[7] = 0x30;
+
+       /*Initilize branch register 0*/
+       p_ctx->br[0] = *(unsigned long *)kvm_vmm_info->vmm_entry;
+
+       vcpu->arch.vmm_rr = kvm->arch.vmm_init_rr;
+       vcpu->arch.metaphysical_rr0 = kvm->arch.metaphysical_rr0;
+       vcpu->arch.metaphysical_rr4 = kvm->arch.metaphysical_rr4;
+
+       hrtimer_init(&vcpu->arch.hlt_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+       vcpu->arch.hlt_timer.function = hlt_timer_fn;
+
+       vcpu->arch.last_run_cpu = -1;
+       vcpu->arch.vpd = (struct vpd *)VPD_ADDR(vcpu->vcpu_id);
+       vcpu->arch.vsa_base = kvm_vsa_base;
+       vcpu->arch.__gp = kvm_vmm_gp;
+       vcpu->arch.dirty_log_lock_pa = __pa(&kvm->arch.dirty_log_lock);
+       vcpu->arch.vhpt.hash = (struct thash_data *)VHPT_ADDR(vcpu->vcpu_id);
+       vcpu->arch.vtlb.hash = (struct thash_data *)VTLB_ADDR(vcpu->vcpu_id);
+       init_ptce_info(vcpu);
+
+       r = 0;
+out:
+       return r;
+}
+
+static int vti_vcpu_setup(struct kvm_vcpu *vcpu, int id)
+{
+       unsigned long psr;
+       int r;
+
+       local_irq_save(psr);
+       r = kvm_insert_vmm_mapping(vcpu);
+       if (r)
+               goto fail;
+       r = kvm_vcpu_init(vcpu, vcpu->kvm, id);
+       if (r)
+               goto fail;
+
+       r = vti_init_vpd(vcpu);
+       if (r) {
+               printk(KERN_DEBUG"kvm: vpd init error!!\n");
+               goto uninit;
+       }
+
+       r = vti_create_vp(vcpu);
+       if (r)
+               goto uninit;
+
+       kvm_purge_vmm_mapping(vcpu);
+       local_irq_restore(psr);
+
+       return 0;
+uninit:
+       kvm_vcpu_uninit(vcpu);
+fail:
+       return r;
+}
+
+struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
+               unsigned int id)
+{
+       struct kvm_vcpu *vcpu;
+       unsigned long vm_base = kvm->arch.vm_base;
+       int r;
+       int cpu;
+
+       r = -ENOMEM;
+       if (!vm_base) {
+               printk(KERN_ERR"kvm: Create vcpu[%d] error!\n", id);
+               goto fail;
+       }
+       vcpu = (struct kvm_vcpu *)(vm_base + KVM_VCPU_OFS + VCPU_SIZE * id);
+       vcpu->kvm = kvm;
+
+       cpu = get_cpu();
+       vti_vcpu_load(vcpu, cpu);
+       r = vti_vcpu_setup(vcpu, id);
+       put_cpu();
+
+       if (r) {
+               printk(KERN_DEBUG"kvm: vcpu_setup error!!\n");
+               goto fail;
+       }
+
+       return vcpu;
+fail:
+       return ERR_PTR(r);
+}
+
+int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
+{
+       return 0;
+}
+
+int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+       return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+       return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
+               struct kvm_debug_guest *dbg)
+{
+       return -EINVAL;
+}
+
+static void free_kvm(struct kvm *kvm)
+{
+       unsigned long vm_base = kvm->arch.vm_base;
+
+       if (vm_base) {
+               memset((void *)vm_base, 0, KVM_VM_DATA_SIZE);
+               free_pages(vm_base, get_order(KVM_VM_DATA_SIZE));
+       }
+
+}
+
+static void kvm_release_vm_pages(struct kvm *kvm)
+{
+       struct kvm_memory_slot *memslot;
+       int i, j;
+       unsigned long base_gfn;
+
+       for (i = 0; i < kvm->nmemslots; i++) {
+               memslot = &kvm->memslots[i];
+               base_gfn = memslot->base_gfn;
+
+               for (j = 0; j < memslot->npages; j++) {
+                       if (memslot->rmap[j])
+                               put_page((struct page *)memslot->rmap[j]);
+               }
+       }
+}
+
+void kvm_arch_destroy_vm(struct kvm *kvm)
+{
+       kfree(kvm->arch.vioapic);
+       kvm_release_vm_pages(kvm);
+       kvm_free_physmem(kvm);
+       free_kvm(kvm);
+}
+
+void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
+{
+}
+
+void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+       if (cpu != vcpu->cpu) {
+               vcpu->cpu = cpu;
+               if (vcpu->arch.ht_active)
+                       kvm_migrate_hlt_timer(vcpu);
+       }
+}
+
+#define SAVE_REGS(_x)  regs->_x = vcpu->arch._x
+
+int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+       int i;
+       int r;
+       struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
+       vcpu_load(vcpu);
+
+       for (i = 0; i < 16; i++) {
+               regs->vpd.vgr[i] = vpd->vgr[i];
+               regs->vpd.vbgr[i] = vpd->vbgr[i];
+       }
+       for (i = 0; i < 128; i++)
+               regs->vpd.vcr[i] = vpd->vcr[i];
+       regs->vpd.vhpi = vpd->vhpi;
+       regs->vpd.vnat = vpd->vnat;
+       regs->vpd.vbnat = vpd->vbnat;
+       regs->vpd.vpsr = vpd->vpsr;
+       regs->vpd.vpr = vpd->vpr;
+
+       r = -EFAULT;
+       r = copy_to_user(regs->saved_guest, &vcpu->arch.guest,
+                                       sizeof(union context));
+       if (r)
+               goto out;
+       r = copy_to_user(regs->saved_stack, (void *)vcpu, IA64_STK_OFFSET);
+       if (r)
+               goto out;
+       SAVE_REGS(mp_state);
+       SAVE_REGS(vmm_rr);
+       memcpy(regs->itrs, vcpu->arch.itrs, sizeof(struct thash_data) * NITRS);
+       memcpy(regs->dtrs, vcpu->arch.dtrs, sizeof(struct thash_data) * NDTRS);
+       SAVE_REGS(itr_regions);
+       SAVE_REGS(dtr_regions);
+       SAVE_REGS(tc_regions);
+       SAVE_REGS(irq_check);
+       SAVE_REGS(itc_check);
+       SAVE_REGS(timer_check);
+       SAVE_REGS(timer_pending);
+       SAVE_REGS(last_itc);
+       for (i = 0; i < 8; i++) {
+               regs->vrr[i] = vcpu->arch.vrr[i];
+               regs->ibr[i] = vcpu->arch.ibr[i];
+               regs->dbr[i] = vcpu->arch.dbr[i];
+       }
+       for (i = 0; i < 4; i++)
+               regs->insvc[i] = vcpu->arch.insvc[i];
+       regs->saved_itc = vcpu->arch.itc_offset + ia64_getreg(_IA64_REG_AR_ITC);
+       SAVE_REGS(xtp);
+       SAVE_REGS(metaphysical_rr0);
+       SAVE_REGS(metaphysical_rr4);
+       SAVE_REGS(metaphysical_saved_rr0);
+       SAVE_REGS(metaphysical_saved_rr4);
+       SAVE_REGS(fp_psr);
+       SAVE_REGS(saved_gp);
+       vcpu_put(vcpu);
+       r = 0;
+out:
+       return r;
+}
+
+void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
+{
+
+       hrtimer_cancel(&vcpu->arch.hlt_timer);
+       kfree(vcpu->arch.apic);
+}
+
+
+long kvm_arch_vcpu_ioctl(struct file *filp,
+               unsigned int ioctl, unsigned long arg)
+{
+       return -EINVAL;
+}
+
+int kvm_arch_set_memory_region(struct kvm *kvm,
+               struct kvm_userspace_memory_region *mem,
+               struct kvm_memory_slot old,
+               int user_alloc)
+{
+       unsigned long i;
+       struct page *page;
+       int npages = mem->memory_size >> PAGE_SHIFT;
+       struct kvm_memory_slot *memslot = &kvm->memslots[mem->slot];
+       unsigned long base_gfn = memslot->base_gfn;
+
+       for (i = 0; i < npages; i++) {
+               page = gfn_to_page(kvm, base_gfn + i);
+               kvm_set_pmt_entry(kvm, base_gfn + i,
+                               page_to_pfn(page) << PAGE_SHIFT,
+                               _PAGE_AR_RWX|_PAGE_MA_WB);
+               memslot->rmap[i] = (unsigned long)page;
+       }
+
+       return 0;
+}
+
+
+long kvm_arch_dev_ioctl(struct file *filp,
+               unsigned int ioctl, unsigned long arg)
+{
+       return -EINVAL;
+}
+
+void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+       kvm_vcpu_uninit(vcpu);
+}
+
+static int vti_cpu_has_kvm_support(void)
+{
+       long  avail = 1, status = 1, control = 1;
+       long ret;
+
+       ret = ia64_pal_proc_get_features(&avail, &status, &control, 0);
+       if (ret)
+               goto out;
+
+       if (!(avail & PAL_PROC_VM_BIT))
+               goto out;
+
+       printk(KERN_DEBUG"kvm: Hardware Supports VT\n");
+
+       ret = ia64_pal_vp_env_info(&kvm_vm_buffer_size, &vp_env_info);
+       if (ret)
+               goto out;
+       printk(KERN_DEBUG"kvm: VM Buffer Size:0x%lx\n", kvm_vm_buffer_size);
+
+       if (!(vp_env_info & VP_OPCODE)) {
+               printk(KERN_WARNING"kvm: No opcode ability on hardware, "
+                               "vm_env_info:0x%lx\n", vp_env_info);
+       }
+
+       return 1;
+out:
+       return 0;
+}
+
+static int kvm_relocate_vmm(struct kvm_vmm_info *vmm_info,
+                                               struct module *module)
+{
+       unsigned long module_base;
+       unsigned long vmm_size;
+
+       unsigned long vmm_offset, func_offset, fdesc_offset;
+       struct fdesc *p_fdesc;
+
+       BUG_ON(!module);
+
+       if (!kvm_vmm_base) {
+               printk("kvm: kvm area hasn't been initilized yet!!\n");
+               return -EFAULT;
+       }
+
+       /*Calculate new position of relocated vmm module.*/
+       module_base = (unsigned long)module->module_core;
+       vmm_size = module->core_size;
+       if (unlikely(vmm_size > KVM_VMM_SIZE))
+               return -EFAULT;
+
+       memcpy((void *)kvm_vmm_base, (void *)module_base, vmm_size);
+       kvm_flush_icache(kvm_vmm_base, vmm_size);
+
+       /*Recalculate kvm_vmm_info based on new VMM*/
+       vmm_offset = vmm_info->vmm_ivt - module_base;
+       kvm_vmm_info->vmm_ivt = KVM_VMM_BASE + vmm_offset;
+       printk(KERN_DEBUG"kvm: Relocated VMM's IVT Base Addr:%lx\n",
+                       kvm_vmm_info->vmm_ivt);
+
+       fdesc_offset = (unsigned long)vmm_info->vmm_entry - module_base;
+       kvm_vmm_info->vmm_entry = (kvm_vmm_entry *)(KVM_VMM_BASE +
+                                                       fdesc_offset);
+       func_offset = *(unsigned long *)vmm_info->vmm_entry - module_base;
+       p_fdesc = (struct fdesc *)(kvm_vmm_base + fdesc_offset);
+       p_fdesc->ip = KVM_VMM_BASE + func_offset;
+       p_fdesc->gp = KVM_VMM_BASE+(p_fdesc->gp - module_base);
+
+       printk(KERN_DEBUG"kvm: Relocated VMM's Init Entry Addr:%lx\n",
+                       KVM_VMM_BASE+func_offset);
+
+       fdesc_offset = (unsigned long)vmm_info->tramp_entry - module_base;
+       kvm_vmm_info->tramp_entry = (kvm_tramp_entry *)(KVM_VMM_BASE +
+                       fdesc_offset);
+       func_offset = *(unsigned long *)vmm_info->tramp_entry - module_base;
+       p_fdesc = (struct fdesc *)(kvm_vmm_base + fdesc_offset);
+       p_fdesc->ip = KVM_VMM_BASE + func_offset;
+       p_fdesc->gp = KVM_VMM_BASE + (p_fdesc->gp - module_base);
+
+       kvm_vmm_gp = p_fdesc->gp;
+
+       printk(KERN_DEBUG"kvm: Relocated VMM's Entry IP:%p\n",
+                                               kvm_vmm_info->vmm_entry);
+       printk(KERN_DEBUG"kvm: Relocated VMM's Trampoline Entry IP:0x%lx\n",
+                                               KVM_VMM_BASE + func_offset);
+
+       return 0;
+}
+
+int kvm_arch_init(void *opaque)
+{
+       int r;
+       struct kvm_vmm_info *vmm_info = (struct kvm_vmm_info *)opaque;
+
+       if (!vti_cpu_has_kvm_support()) {
+               printk(KERN_ERR "kvm: No Hardware Virtualization Support!\n");
+               r = -EOPNOTSUPP;
+               goto out;
+       }
+
+       if (kvm_vmm_info) {
+               printk(KERN_ERR "kvm: Already loaded VMM module!\n");
+               r = -EEXIST;
+               goto out;
+       }
+
+       r = -ENOMEM;
+       kvm_vmm_info = kzalloc(sizeof(struct kvm_vmm_info), GFP_KERNEL);
+       if (!kvm_vmm_info)
+               goto out;
+
+       if (kvm_alloc_vmm_area())
+               goto out_free0;
+
+       r = kvm_relocate_vmm(vmm_info, vmm_info->module);
+       if (r)
+               goto out_free1;
+
+       return 0;
+
+out_free1:
+       kvm_free_vmm_area();
+out_free0:
+       kfree(kvm_vmm_info);
+out:
+       return r;
+}
+
+void kvm_arch_exit(void)
+{
+       kvm_free_vmm_area();
+       kfree(kvm_vmm_info);
+       kvm_vmm_info = NULL;
+}
+
+static int kvm_ia64_sync_dirty_log(struct kvm *kvm,
+               struct kvm_dirty_log *log)
+{
+       struct kvm_memory_slot *memslot;
+       int r, i;
+       long n, base;
+       unsigned long *dirty_bitmap = (unsigned long *)((void *)kvm - KVM_VM_OFS
+                                       + KVM_MEM_DIRTY_LOG_OFS);
+
+       r = -EINVAL;
+       if (log->slot >= KVM_MEMORY_SLOTS)
+               goto out;
+
+       memslot = &kvm->memslots[log->slot];
+       r = -ENOENT;
+       if (!memslot->dirty_bitmap)
+               goto out;
+
+       n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
+       base = memslot->base_gfn / BITS_PER_LONG;
+
+       for (i = 0; i < n/sizeof(long); ++i) {
+               memslot->dirty_bitmap[i] = dirty_bitmap[base + i];
+               dirty_bitmap[base + i] = 0;
+       }
+       r = 0;
+out:
+       return r;
+}
+
+int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
+               struct kvm_dirty_log *log)
+{
+       int r;
+       int n;
+       struct kvm_memory_slot *memslot;
+       int is_dirty = 0;
+
+       spin_lock(&kvm->arch.dirty_log_lock);
+
+       r = kvm_ia64_sync_dirty_log(kvm, log);
+       if (r)
+               goto out;
+
+       r = kvm_get_dirty_log(kvm, log, &is_dirty);
+       if (r)
+               goto out;
+
+       /* If nothing is dirty, don't bother messing with page tables. */
+       if (is_dirty) {
+               kvm_flush_remote_tlbs(kvm);
+               memslot = &kvm->memslots[log->slot];
+               n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
+               memset(memslot->dirty_bitmap, 0, n);
+       }
+       r = 0;
+out:
+       spin_unlock(&kvm->arch.dirty_log_lock);
+       return r;
+}
+
+int kvm_arch_hardware_setup(void)
+{
+       return 0;
+}
+
+void kvm_arch_hardware_unsetup(void)
+{
+}
+
+static void vcpu_kick_intr(void *info)
+{
+#ifdef DEBUG
+       struct kvm_vcpu *vcpu = (struct kvm_vcpu *)info;
+       printk(KERN_DEBUG"vcpu_kick_intr %p \n", vcpu);
+#endif
+}
+
+void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
+{
+       int ipi_pcpu = vcpu->cpu;
+
+       if (waitqueue_active(&vcpu->wq))
+               wake_up_interruptible(&vcpu->wq);
+
+       if (vcpu->guest_mode)
+               smp_call_function_single(ipi_pcpu, vcpu_kick_intr, vcpu, 0, 0);
+}
+
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig)
+{
+
+       struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
+
+       if (!test_and_set_bit(vec, &vpd->irr[0])) {
+               vcpu->arch.irq_new_pending = 1;
+                if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
+                       kvm_vcpu_kick(vcpu);
+               else if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED) {
+                       vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+                       if (waitqueue_active(&vcpu->wq))
+                               wake_up_interruptible(&vcpu->wq);
+               }
+               return 1;
+       }
+       return 0;
+}
+
+int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest)
+{
+       return apic->vcpu->vcpu_id == dest;
+}
+
+int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda)
+{
+       return 0;
+}
+
+struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
+                                      unsigned long bitmap)
+{
+       struct kvm_vcpu *lvcpu = kvm->vcpus[0];
+       int i;
+
+       for (i = 1; i < KVM_MAX_VCPUS; i++) {
+               if (!kvm->vcpus[i])
+                       continue;
+               if (lvcpu->arch.xtp > kvm->vcpus[i]->arch.xtp)
+                       lvcpu = kvm->vcpus[i];
+       }
+
+       return lvcpu;
+}
+
+static int find_highest_bits(int *dat)
+{
+       u32  bits, bitnum;
+       int i;
+
+       /* loop for all 256 bits */
+       for (i = 7; i >= 0 ; i--) {
+               bits = dat[i];
+               if (bits) {
+                       bitnum = fls(bits);
+                       return i * 32 + bitnum - 1;
+               }
+       }
+
+       return -1;
+}
+
+int kvm_highest_pending_irq(struct kvm_vcpu *vcpu)
+{
+    struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
+
+    if (vpd->irr[0] & (1UL << NMI_VECTOR))
+               return NMI_VECTOR;
+    if (vpd->irr[0] & (1UL << ExtINT_VECTOR))
+               return ExtINT_VECTOR;
+
+    return find_highest_bits((int *)&vpd->irr[0]);
+}
+
+int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu)
+{
+       if (kvm_highest_pending_irq(vcpu) != -1)
+               return 1;
+       return 0;
+}
+
+int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
+{
+       return 0;
+}
+
+gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
+{
+       return gfn;
+}
+
+int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
+{
+       return vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE;
+}
+
+int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
+                                   struct kvm_mp_state *mp_state)
+{
+       return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
+                                   struct kvm_mp_state *mp_state)
+{
+       return -EINVAL;
+}
diff --git a/arch/ia64/kvm/kvm_fw.c b/arch/ia64/kvm/kvm_fw.c
new file mode 100644 (file)
index 0000000..091f936
--- /dev/null
@@ -0,0 +1,500 @@
+/*
+ * PAL/SAL call delegation
+ *
+ * Copyright (c) 2004 Li Susie <susie.li@intel.com>
+ * Copyright (c) 2005 Yu Ke <ke.yu@intel.com>
+ * Copyright (c) 2007 Xiantao Zhang <xiantao.zhang@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <linux/kvm_host.h>
+#include <linux/smp.h>
+
+#include "vti.h"
+#include "misc.h"
+
+#include <asm/pal.h>
+#include <asm/sal.h>
+#include <asm/tlb.h>
+
+/*
+ * Handy macros to make sure that the PAL return values start out
+ * as something meaningful.
+ */
+#define INIT_PAL_STATUS_UNIMPLEMENTED(x)               \
+       {                                               \
+               x.status = PAL_STATUS_UNIMPLEMENTED;    \
+               x.v0 = 0;                               \
+               x.v1 = 0;                               \
+               x.v2 = 0;                               \
+       }
+
+#define INIT_PAL_STATUS_SUCCESS(x)                     \
+       {                                               \
+               x.status = PAL_STATUS_SUCCESS;          \
+               x.v0 = 0;                               \
+               x.v1 = 0;                               \
+               x.v2 = 0;                               \
+    }
+
+static void kvm_get_pal_call_data(struct kvm_vcpu *vcpu,
+               u64 *gr28, u64 *gr29, u64 *gr30, u64 *gr31) {
+       struct exit_ctl_data *p;
+
+       if (vcpu) {
+               p = &vcpu->arch.exit_data;
+               if (p->exit_reason == EXIT_REASON_PAL_CALL) {
+                       *gr28 = p->u.pal_data.gr28;
+                       *gr29 = p->u.pal_data.gr29;
+                       *gr30 = p->u.pal_data.gr30;
+                       *gr31 = p->u.pal_data.gr31;
+                       return ;
+               }
+       }
+       printk(KERN_DEBUG"Failed to get vcpu pal data!!!\n");
+}
+
+static void set_pal_result(struct kvm_vcpu *vcpu,
+               struct ia64_pal_retval result) {
+
+       struct exit_ctl_data *p;
+
+       p = kvm_get_exit_data(vcpu);
+       if (p && p->exit_reason == EXIT_REASON_PAL_CALL) {
+               p->u.pal_data.ret = result;
+               return ;
+       }
+       INIT_PAL_STATUS_UNIMPLEMENTED(p->u.pal_data.ret);
+}
+
+static void set_sal_result(struct kvm_vcpu *vcpu,
+               struct sal_ret_values result) {
+       struct exit_ctl_data *p;
+
+       p = kvm_get_exit_data(vcpu);
+       if (p && p->exit_reason == EXIT_REASON_SAL_CALL) {
+               p->u.sal_data.ret = result;
+               return ;
+       }
+       printk(KERN_WARNING"Failed to set sal result!!\n");
+}
+
+struct cache_flush_args {
+       u64 cache_type;
+       u64 operation;
+       u64 progress;
+       long status;
+};
+
+cpumask_t cpu_cache_coherent_map;
+
+static void remote_pal_cache_flush(void *data)
+{
+       struct cache_flush_args *args = data;
+       long status;
+       u64 progress = args->progress;
+
+       status = ia64_pal_cache_flush(args->cache_type, args->operation,
+                                       &progress, NULL);
+       if (status != 0)
+       args->status = status;
+}
+
+static struct ia64_pal_retval pal_cache_flush(struct kvm_vcpu *vcpu)
+{
+       u64 gr28, gr29, gr30, gr31;
+       struct ia64_pal_retval result = {0, 0, 0, 0};
+       struct cache_flush_args args = {0, 0, 0, 0};
+       long psr;
+
+       gr28 = gr29 = gr30 = gr31 = 0;
+       kvm_get_pal_call_data(vcpu, &gr28, &gr29, &gr30, &gr31);
+
+       if (gr31 != 0)
+               printk(KERN_ERR"vcpu:%p called cache_flush error!\n", vcpu);
+
+       /* Always call Host Pal in int=1 */
+       gr30 &= ~PAL_CACHE_FLUSH_CHK_INTRS;
+       args.cache_type = gr29;
+       args.operation = gr30;
+       smp_call_function(remote_pal_cache_flush,
+                               (void *)&args, 1, 1);
+       if (args.status != 0)
+               printk(KERN_ERR"pal_cache_flush error!,"
+                               "status:0x%lx\n", args.status);
+       /*
+        * Call Host PAL cache flush
+        * Clear psr.ic when call PAL_CACHE_FLUSH
+        */
+       local_irq_save(psr);
+       result.status = ia64_pal_cache_flush(gr29, gr30, &result.v1,
+                                               &result.v0);
+       local_irq_restore(psr);
+       if (result.status != 0)
+               printk(KERN_ERR"vcpu:%p crashed due to cache_flush err:%ld"
+                               "in1:%lx,in2:%lx\n",
+                               vcpu, result.status, gr29, gr30);
+
+#if 0
+       if (gr29 == PAL_CACHE_TYPE_COHERENT) {
+               cpus_setall(vcpu->arch.cache_coherent_map);
+               cpu_clear(vcpu->cpu, vcpu->arch.cache_coherent_map);
+               cpus_setall(cpu_cache_coherent_map);
+               cpu_clear(vcpu->cpu, cpu_cache_coherent_map);
+       }
+#endif
+       return result;
+}
+
+struct ia64_pal_retval pal_cache_summary(struct kvm_vcpu *vcpu)
+{
+
+       struct ia64_pal_retval result;
+
+       PAL_CALL(result, PAL_CACHE_SUMMARY, 0, 0, 0);
+       return result;
+}
+
+static struct ia64_pal_retval pal_freq_base(struct kvm_vcpu *vcpu)
+{
+
+       struct ia64_pal_retval result;
+
+       PAL_CALL(result, PAL_FREQ_BASE, 0, 0, 0);
+
+       /*
+        * PAL_FREQ_BASE may not be implemented in some platforms,
+        * call SAL instead.
+        */
+       if (result.v0 == 0) {
+               result.status = ia64_sal_freq_base(SAL_FREQ_BASE_PLATFORM,
+                                                       &result.v0,
+                                                       &result.v1);
+               result.v2 = 0;
+       }
+
+       return result;
+}
+
+static struct ia64_pal_retval pal_freq_ratios(struct kvm_vcpu *vcpu)
+{
+
+       struct ia64_pal_retval result;
+
+       PAL_CALL(result, PAL_FREQ_RATIOS, 0, 0, 0);
+       return result;
+}
+
+static struct ia64_pal_retval pal_logical_to_physica(struct kvm_vcpu *vcpu)
+{
+       struct ia64_pal_retval result;
+
+       INIT_PAL_STATUS_UNIMPLEMENTED(result);
+       return result;
+}
+
+static struct ia64_pal_retval pal_platform_addr(struct kvm_vcpu *vcpu)
+{
+
+       struct ia64_pal_retval result;
+
+       INIT_PAL_STATUS_SUCCESS(result);
+       return result;
+}
+
+static struct ia64_pal_retval pal_proc_get_features(struct kvm_vcpu *vcpu)
+{
+
+       struct ia64_pal_retval result = {0, 0, 0, 0};
+       long in0, in1, in2, in3;
+
+       kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
+       result.status = ia64_pal_proc_get_features(&result.v0, &result.v1,
+                       &result.v2, in2);
+
+       return result;
+}
+
+static struct ia64_pal_retval pal_cache_info(struct kvm_vcpu *vcpu)
+{
+
+       pal_cache_config_info_t ci;
+       long status;
+       unsigned long in0, in1, in2, in3, r9, r10;
+
+       kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
+       status = ia64_pal_cache_config_info(in1, in2, &ci);
+       r9 = ci.pcci_info_1.pcci1_data;
+       r10 = ci.pcci_info_2.pcci2_data;
+       return ((struct ia64_pal_retval){status, r9, r10, 0});
+}
+
+#define GUEST_IMPL_VA_MSB      59
+#define GUEST_RID_BITS         18
+
+static struct ia64_pal_retval pal_vm_summary(struct kvm_vcpu *vcpu)
+{
+
+       pal_vm_info_1_u_t vminfo1;
+       pal_vm_info_2_u_t vminfo2;
+       struct ia64_pal_retval result;
+
+       PAL_CALL(result, PAL_VM_SUMMARY, 0, 0, 0);
+       if (!result.status) {
+               vminfo1.pvi1_val = result.v0;
+               vminfo1.pal_vm_info_1_s.max_itr_entry = 8;
+               vminfo1.pal_vm_info_1_s.max_dtr_entry = 8;
+               result.v0 = vminfo1.pvi1_val;
+               vminfo2.pal_vm_info_2_s.impl_va_msb = GUEST_IMPL_VA_MSB;
+               vminfo2.pal_vm_info_2_s.rid_size = GUEST_RID_BITS;
+               result.v1 = vminfo2.pvi2_val;
+       }
+
+       return result;
+}
+
+static struct ia64_pal_retval pal_vm_info(struct kvm_vcpu *vcpu)
+{
+       struct ia64_pal_retval result;
+
+       INIT_PAL_STATUS_UNIMPLEMENTED(result);
+
+       return result;
+}
+
+static  u64 kvm_get_pal_call_index(struct kvm_vcpu *vcpu)
+{
+       u64 index = 0;
+       struct exit_ctl_data *p;
+
+       p = kvm_get_exit_data(vcpu);
+       if (p && (p->exit_reason == EXIT_REASON_PAL_CALL))
+               index = p->u.pal_data.gr28;
+
+       return index;
+}
+
+int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+
+       u64 gr28;
+       struct ia64_pal_retval result;
+       int ret = 1;
+
+       gr28 = kvm_get_pal_call_index(vcpu);
+       /*printk("pal_call index:%lx\n",gr28);*/
+       switch (gr28) {
+       case PAL_CACHE_FLUSH:
+               result = pal_cache_flush(vcpu);
+               break;
+       case PAL_CACHE_SUMMARY:
+               result = pal_cache_summary(vcpu);
+               break;
+       case PAL_HALT_LIGHT:
+       {
+               vcpu->arch.timer_pending = 1;
+               INIT_PAL_STATUS_SUCCESS(result);
+               if (kvm_highest_pending_irq(vcpu) == -1)
+                       ret = kvm_emulate_halt(vcpu);
+
+       }
+               break;
+
+       case PAL_FREQ_RATIOS:
+               result = pal_freq_ratios(vcpu);
+               break;
+
+       case PAL_FREQ_BASE:
+               result = pal_freq_base(vcpu);
+               break;
+
+       case PAL_LOGICAL_TO_PHYSICAL :
+               result = pal_logical_to_physica(vcpu);
+               break;
+
+       case PAL_VM_SUMMARY :
+               result = pal_vm_summary(vcpu);
+               break;
+
+       case PAL_VM_INFO :
+               result = pal_vm_info(vcpu);
+               break;
+       case PAL_PLATFORM_ADDR :
+               result = pal_platform_addr(vcpu);
+               break;
+       case PAL_CACHE_INFO:
+               result = pal_cache_info(vcpu);
+               break;
+       case PAL_PTCE_INFO:
+               INIT_PAL_STATUS_SUCCESS(result);
+               result.v1 = (1L << 32) | 1L;
+               break;
+       case PAL_VM_PAGE_SIZE:
+               result.status = ia64_pal_vm_page_size(&result.v0,
+                                                       &result.v1);
+               break;
+       case PAL_RSE_INFO:
+               result.status = ia64_pal_rse_info(&result.v0,
+                                       (pal_hints_u_t *)&result.v1);
+               break;
+       case PAL_PROC_GET_FEATURES:
+               result = pal_proc_get_features(vcpu);
+               break;
+       case PAL_DEBUG_INFO:
+               result.status = ia64_pal_debug_info(&result.v0,
+                                                       &result.v1);
+               break;
+       case PAL_VERSION:
+               result.status = ia64_pal_version(
+                               (pal_version_u_t *)&result.v0,
+                               (pal_version_u_t *)&result.v1);
+
+               break;
+       case PAL_FIXED_ADDR:
+               result.status = PAL_STATUS_SUCCESS;
+               result.v0 = vcpu->vcpu_id;
+               break;
+       default:
+               INIT_PAL_STATUS_UNIMPLEMENTED(result);
+               printk(KERN_WARNING"kvm: Unsupported pal call,"
+                                       " index:0x%lx\n", gr28);
+       }
+       set_pal_result(vcpu, result);
+       return ret;
+}
+
+static struct sal_ret_values sal_emulator(struct kvm *kvm,
+                               long index, unsigned long in1,
+                               unsigned long in2, unsigned long in3,
+                               unsigned long in4, unsigned long in5,
+                               unsigned long in6, unsigned long in7)
+{
+       unsigned long r9  = 0;
+       unsigned long r10 = 0;
+       long r11 = 0;
+       long status;
+
+       status = 0;
+       switch (index) {
+       case SAL_FREQ_BASE:
+               status = ia64_sal_freq_base(in1, &r9, &r10);
+               break;
+       case SAL_PCI_CONFIG_READ:
+               printk(KERN_WARNING"kvm: Not allowed to call here!"
+                       " SAL_PCI_CONFIG_READ\n");
+               break;
+       case SAL_PCI_CONFIG_WRITE:
+               printk(KERN_WARNING"kvm: Not allowed to call here!"
+                       " SAL_PCI_CONFIG_WRITE\n");
+               break;
+       case SAL_SET_VECTORS:
+               if (in1 == SAL_VECTOR_OS_BOOT_RENDEZ) {
+                       if (in4 != 0 || in5 != 0 || in6 != 0 || in7 != 0) {
+                               status = -2;
+                       } else {
+                               kvm->arch.rdv_sal_data.boot_ip = in2;
+                               kvm->arch.rdv_sal_data.boot_gp = in3;
+                       }
+                       printk("Rendvous called! iip:%lx\n\n", in2);
+               } else
+                       printk(KERN_WARNING"kvm: CALLED SAL_SET_VECTORS %lu."
+                                                       "ignored...\n", in1);
+               break;
+       case SAL_GET_STATE_INFO:
+               /* No more info.  */
+               status = -5;
+               r9 = 0;
+               break;
+       case SAL_GET_STATE_INFO_SIZE:
+               /* Return a dummy size.  */
+               status = 0;
+               r9 = 128;
+               break;
+       case SAL_CLEAR_STATE_INFO:
+               /* Noop.  */
+               break;
+       case SAL_MC_RENDEZ:
+               printk(KERN_WARNING
+                       "kvm: called SAL_MC_RENDEZ. ignored...\n");
+               break;
+       case SAL_MC_SET_PARAMS:
+               printk(KERN_WARNING
+                       "kvm: called  SAL_MC_SET_PARAMS.ignored!\n");
+               break;
+       case SAL_CACHE_FLUSH:
+               if (1) {
+                       /*Flush using SAL.
+                       This method is faster but has a side
+                       effect on other vcpu running on
+                       this cpu.  */
+                       status = ia64_sal_cache_flush(in1);
+               } else {
+                       /*Maybe need to implement the method
+                       without side effect!*/
+                       status = 0;
+               }
+               break;
+       case SAL_CACHE_INIT:
+               printk(KERN_WARNING
+                       "kvm: called SAL_CACHE_INIT.  ignored...\n");
+               break;
+       case SAL_UPDATE_PAL:
+               printk(KERN_WARNING
+                       "kvm: CALLED SAL_UPDATE_PAL.  ignored...\n");
+               break;
+       default:
+               printk(KERN_WARNING"kvm: called SAL_CALL with unknown index."
+                                               " index:%ld\n", index);
+               status = -1;
+               break;
+       }
+       return ((struct sal_ret_values) {status, r9, r10, r11});
+}
+
+static void kvm_get_sal_call_data(struct kvm_vcpu *vcpu, u64 *in0, u64 *in1,
+               u64 *in2, u64 *in3, u64 *in4, u64 *in5, u64 *in6, u64 *in7){
+
+       struct exit_ctl_data *p;
+
+       p = kvm_get_exit_data(vcpu);
+
+       if (p) {
+               if (p->exit_reason == EXIT_REASON_SAL_CALL) {
+                       *in0 = p->u.sal_data.in0;
+                       *in1 = p->u.sal_data.in1;
+                       *in2 = p->u.sal_data.in2;
+                       *in3 = p->u.sal_data.in3;
+                       *in4 = p->u.sal_data.in4;
+                       *in5 = p->u.sal_data.in5;
+                       *in6 = p->u.sal_data.in6;
+                       *in7 = p->u.sal_data.in7;
+                       return ;
+               }
+       }
+       *in0 = 0;
+}
+
+void kvm_sal_emul(struct kvm_vcpu *vcpu)
+{
+
+       struct sal_ret_values result;
+       u64 index, in1, in2, in3, in4, in5, in6, in7;
+
+       kvm_get_sal_call_data(vcpu, &index, &in1, &in2,
+                       &in3, &in4, &in5, &in6, &in7);
+       result = sal_emulator(vcpu->kvm, index, in1, in2, in3,
+                                       in4, in5, in6, in7);
+       set_sal_result(vcpu, result);
+}
diff --git a/arch/ia64/kvm/kvm_minstate.h b/arch/ia64/kvm/kvm_minstate.h
new file mode 100644 (file)
index 0000000..13980d9
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ *  kvm_minstate.h: min save macros
+ *  Copyright (c) 2007, Intel Corporation.
+ *
+ *  Xuefei Xu (Anthony Xu) (Anthony.xu@intel.com)
+ *  Xiantao Zhang (xiantao.zhang@intel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+
+#include <asm/asmmacro.h>
+#include <asm/types.h>
+#include <asm/kregs.h>
+#include "asm-offsets.h"
+
+#define KVM_MINSTATE_START_SAVE_MIN                                            \
+       mov ar.rsc = 0;/* set enforced lazy mode, pl 0, little-endian, loadrs=0 */\
+       ;;                                                                      \
+       mov.m r28 = ar.rnat;                                                    \
+       addl r22 = VMM_RBS_OFFSET,r1;            /* compute base of RBS */      \
+       ;;                                                                      \
+       lfetch.fault.excl.nt1 [r22];                                            \
+       addl r1 = IA64_STK_OFFSET-VMM_PT_REGS_SIZE,r1;  /* compute base of memory stack */  \
+       mov r23 = ar.bspstore;                  /* save ar.bspstore */          \
+       ;;                                                                      \
+       mov ar.bspstore = r22;                          /* switch to kernel RBS */\
+       ;;                                                                      \
+       mov r18 = ar.bsp;                                                       \
+       mov ar.rsc = 0x3;     /* set eager mode, pl 0, little-endian, loadrs=0 */
+
+
+
+#define KVM_MINSTATE_END_SAVE_MIN                                              \
+       bsw.1;          /* switch back to bank 1 (must be last in insn group) */\
+       ;;
+
+
+#define PAL_VSA_SYNC_READ                                              \
+       /* begin to call pal vps sync_read */                           \
+       add r25 = VMM_VPD_BASE_OFFSET, r21;                             \
+       adds r20 = VMM_VCPU_VSA_BASE_OFFSET, r21;  /* entry point */    \
+       ;;                                                              \
+       ld8 r25 = [r25];      /* read vpd base */                       \
+       ld8 r20 = [r20];                                                \
+       ;;                                                              \
+       add r20 = PAL_VPS_SYNC_READ,r20;                                \
+       ;;                                                              \
+{ .mii;                                                                        \
+       nop 0x0;                                                        \
+       mov r24 = ip;                                                   \
+       mov b0 = r20;                                                   \
+       ;;                                                              \
+};                                                                     \
+{ .mmb;                                                                        \
+       add r24 = 0x20, r24;                                            \
+       nop 0x0;                                                        \
+       br.cond.sptk b0;        /*  call the service */                 \
+       ;;                                                              \
+};
+
+
+
+#define KVM_MINSTATE_GET_CURRENT(reg)   mov reg=r21
+
+/*
+ * KVM_DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves
+ * the minimum state necessary that allows us to turn psr.ic back
+ * on.
+ *
+ * Assumed state upon entry:
+ *  psr.ic: off
+ *  r31:       contains saved predicates (pr)
+ *
+ * Upon exit, the state is as follows:
+ *  psr.ic: off
+ *   r2 = points to &pt_regs.r16
+ *   r8 = contents of ar.ccv
+ *   r9 = contents of ar.csd
+ *  r10 = contents of ar.ssd
+ *  r11 = FPSR_DEFAULT
+ *  r12 = kernel sp (kernel virtual address)
+ *  r13 = points to current task_struct (kernel virtual address)
+ *  p15 = TRUE if psr.i is set in cr.ipsr
+ *  predicate registers (other than p2, p3, and p15), b6, r3, r14, r15:
+ *       preserved
+ *
+ * Note that psr.ic is NOT turned on by this macro.  This is so that
+ * we can pass interruption state as arguments to a handler.
+ */
+
+
+#define PT(f) (VMM_PT_REGS_##f##_OFFSET)
+
+#define KVM_DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA)                  \
+       KVM_MINSTATE_GET_CURRENT(r16);  /* M (or M;;I) */       \
+       mov r27 = ar.rsc;         /* M */                       \
+       mov r20 = r1;         /* A */                           \
+       mov r25 = ar.unat;        /* M */                       \
+       mov r29 = cr.ipsr;        /* M */                       \
+       mov r26 = ar.pfs;         /* I */                       \
+       mov r18 = cr.isr;                                       \
+       COVER;              /* B;; (or nothing) */              \
+       ;;                                                      \
+       tbit.z p0,p15 = r29,IA64_PSR_I_BIT;                     \
+       mov r1 = r16;                                           \
+/*     mov r21=r16;    */                                      \
+       /* switch from user to kernel RBS: */                   \
+       ;;                                                      \
+       invala;             /* M */                             \
+       SAVE_IFS;                                               \
+       ;;                                                      \
+       KVM_MINSTATE_START_SAVE_MIN                             \
+       adds r17 = 2*L1_CACHE_BYTES,r1;/* cache-line size */    \
+       adds r16 = PT(CR_IPSR),r1;                              \
+       ;;                                                      \
+       lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES;             \
+       st8 [r16] = r29;      /* save cr.ipsr */                \
+       ;;                                                      \
+       lfetch.fault.excl.nt1 [r17];                            \
+       tbit.nz p15,p0 = r29,IA64_PSR_I_BIT;                    \
+       mov r29 = b0                                            \
+       ;;                                                      \
+       adds r16 = PT(R8),r1; /* initialize first base pointer */\
+       adds r17 = PT(R9),r1; /* initialize second base pointer */\
+       ;;                                                      \
+.mem.offset 0,0; st8.spill [r16] = r8,16;                      \
+.mem.offset 8,0; st8.spill [r17] = r9,16;                      \
+       ;;                                                      \
+.mem.offset 0,0; st8.spill [r16] = r10,24;                     \
+.mem.offset 8,0; st8.spill [r17] = r11,24;                     \
+       ;;                                                      \
+       mov r9 = cr.iip;         /* M */                        \
+       mov r10 = ar.fpsr;        /* M */                       \
+       ;;                                                      \
+       st8 [r16] = r9,16;    /* save cr.iip */                 \
+       st8 [r17] = r30,16;   /* save cr.ifs */                 \
+       sub r18 = r18,r22;    /* r18=RSE.ndirty*8 */            \
+       ;;                                                      \
+       st8 [r16] = r25,16;   /* save ar.unat */                \
+       st8 [r17] = r26,16;    /* save ar.pfs */                \
+       shl r18 = r18,16;     /* calu ar.rsc used for "loadrs" */\
+       ;;                                                      \
+       st8 [r16] = r27,16;   /* save ar.rsc */                 \
+       st8 [r17] = r28,16;   /* save ar.rnat */                \
+       ;;          /* avoid RAW on r16 & r17 */                \
+       st8 [r16] = r23,16;   /* save ar.bspstore */            \
+       st8 [r17] = r31,16;   /* save predicates */             \
+       ;;                                                      \
+       st8 [r16] = r29,16;   /* save b0 */                     \
+       st8 [r17] = r18,16;   /* save ar.rsc value for "loadrs" */\
+       ;;                                                      \
+.mem.offset 0,0; st8.spill [r16] = r20,16;/* save original r1 */  \
+.mem.offset 8,0; st8.spill [r17] = r12,16;                     \
+       adds r12 = -16,r1;    /* switch to kernel memory stack */  \
+       ;;                                                      \
+.mem.offset 0,0; st8.spill [r16] = r13,16;                     \
+.mem.offset 8,0; st8.spill [r17] = r10,16;     /* save ar.fpsr */\
+       mov r13 = r21;   /* establish `current' */              \
+       ;;                                                      \
+.mem.offset 0,0; st8.spill [r16] = r15,16;                     \
+.mem.offset 8,0; st8.spill [r17] = r14,16;                     \
+       ;;                                                      \
+.mem.offset 0,0; st8.spill [r16] = r2,16;                      \
+.mem.offset 8,0; st8.spill [r17] = r3,16;                      \
+       adds r2 = VMM_PT_REGS_R16_OFFSET,r1;                    \
+        ;;                                                     \
+       adds r16 = VMM_VCPU_IIPA_OFFSET,r13;                    \
+       adds r17 = VMM_VCPU_ISR_OFFSET,r13;                     \
+       mov r26 = cr.iipa;                                      \
+       mov r27 = cr.isr;                                       \
+       ;;                                                      \
+       st8 [r16] = r26;                                        \
+       st8 [r17] = r27;                                        \
+       ;;                                                      \
+       EXTRA;                                                  \
+       mov r8 = ar.ccv;                                        \
+       mov r9 = ar.csd;                                        \
+       mov r10 = ar.ssd;                                       \
+       movl r11 = FPSR_DEFAULT;   /* L-unit */                 \
+       adds r17 = VMM_VCPU_GP_OFFSET,r13;                      \
+       ;;                                                      \
+       ld8 r1 = [r17];/* establish kernel global pointer */    \
+       ;;                                                      \
+       PAL_VSA_SYNC_READ                                       \
+       KVM_MINSTATE_END_SAVE_MIN
+
+/*
+ * SAVE_REST saves the remainder of pt_regs (with psr.ic on).
+ *
+ * Assumed state upon entry:
+ *  psr.ic: on
+ *  r2: points to &pt_regs.f6
+ *  r3: points to &pt_regs.f7
+ *  r8: contents of ar.ccv
+ *  r9: contents of ar.csd
+ *  r10:       contents of ar.ssd
+ *  r11:       FPSR_DEFAULT
+ *
+ * Registers r14 and r15 are guaranteed not to be touched by SAVE_REST.
+ */
+#define KVM_SAVE_REST                          \
+.mem.offset 0,0; st8.spill [r2] = r16,16;      \
+.mem.offset 8,0; st8.spill [r3] = r17,16;      \
+       ;;                              \
+.mem.offset 0,0; st8.spill [r2] = r18,16;      \
+.mem.offset 8,0; st8.spill [r3] = r19,16;      \
+       ;;                              \
+.mem.offset 0,0; st8.spill [r2] = r20,16;      \
+.mem.offset 8,0; st8.spill [r3] = r21,16;      \
+       mov r18=b6;                     \
+       ;;                              \
+.mem.offset 0,0; st8.spill [r2] = r22,16;      \
+.mem.offset 8,0; st8.spill [r3] = r23,16;      \
+       mov r19 = b7;                           \
+       ;;                                      \
+.mem.offset 0,0; st8.spill [r2] = r24,16;      \
+.mem.offset 8,0; st8.spill [r3] = r25,16;      \
+       ;;                                      \
+.mem.offset 0,0; st8.spill [r2] = r26,16;      \
+.mem.offset 8,0; st8.spill [r3] = r27,16;      \
+       ;;                                      \
+.mem.offset 0,0; st8.spill [r2] = r28,16;      \
+.mem.offset 8,0; st8.spill [r3] = r29,16;      \
+       ;;                                      \
+.mem.offset 0,0; st8.spill [r2] = r30,16;      \
+.mem.offset 8,0; st8.spill [r3] = r31,32;      \
+       ;;                                      \
+       mov ar.fpsr = r11;                      \
+       st8 [r2] = r8,8;                        \
+       adds r24 = PT(B6)-PT(F7),r3;            \
+       adds r25 = PT(B7)-PT(F7),r3;            \
+       ;;                                      \
+       st8 [r24] = r18,16;       /* b6 */      \
+       st8 [r25] = r19,16;       /* b7 */      \
+       adds r2 = PT(R4)-PT(F6),r2;             \
+       adds r3 = PT(R5)-PT(F7),r3;             \
+       ;;                                      \
+       st8 [r24] = r9; /* ar.csd */            \
+       st8 [r25] = r10;        /* ar.ssd */    \
+       ;;                                      \
+       mov r18 = ar.unat;                      \
+       adds r19 = PT(EML_UNAT)-PT(R4),r2;      \
+       ;;                                      \
+       st8 [r19] = r18; /* eml_unat */         \
+
+
+#define KVM_SAVE_EXTRA                         \
+.mem.offset 0,0; st8.spill [r2] = r4,16;       \
+.mem.offset 8,0; st8.spill [r3] = r5,16;       \
+       ;;                                      \
+.mem.offset 0,0; st8.spill [r2] = r6,16;       \
+.mem.offset 8,0; st8.spill [r3] = r7;          \
+       ;;                                      \
+       mov r26 = ar.unat;                      \
+       ;;                                      \
+       st8 [r2] = r26;/* eml_unat */           \
+
+#define KVM_SAVE_MIN_WITH_COVER                KVM_DO_SAVE_MIN(cover, mov r30 = cr.ifs,)
+#define KVM_SAVE_MIN_WITH_COVER_R19    KVM_DO_SAVE_MIN(cover, mov r30 = cr.ifs, mov r15 = r19)
+#define KVM_SAVE_MIN                   KVM_DO_SAVE_MIN(     , mov r30 = r0, )
diff --git a/arch/ia64/kvm/lapic.h b/arch/ia64/kvm/lapic.h
new file mode 100644 (file)
index 0000000..6d6cbcb
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __KVM_IA64_LAPIC_H
+#define __KVM_IA64_LAPIC_H
+
+#include <linux/kvm_host.h>
+
+/*
+ * vlsapic
+ */
+struct kvm_lapic{
+       struct kvm_vcpu *vcpu;
+       uint64_t insvc[4];
+       uint64_t vhpi;
+       uint8_t xtp;
+       uint8_t pal_init_pending;
+       uint8_t pad[2];
+};
+
+int kvm_create_lapic(struct kvm_vcpu *vcpu);
+void kvm_free_lapic(struct kvm_vcpu *vcpu);
+
+int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
+int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig);
+
+#endif
diff --git a/arch/ia64/kvm/misc.h b/arch/ia64/kvm/misc.h
new file mode 100644 (file)
index 0000000..e585c46
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef __KVM_IA64_MISC_H
+#define __KVM_IA64_MISC_H
+
+#include <linux/kvm_host.h>
+/*
+ * misc.h
+ *     Copyright (C) 2007, Intel Corporation.
+ *     Xiantao Zhang  (xiantao.zhang@intel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+/*
+ *Return p2m base address at host side!
+ */
+static inline uint64_t *kvm_host_get_pmt(struct kvm *kvm)
+{
+       return (uint64_t *)(kvm->arch.vm_base + KVM_P2M_OFS);
+}
+
+static inline void kvm_set_pmt_entry(struct kvm *kvm, gfn_t gfn,
+               u64 paddr, u64 mem_flags)
+{
+       uint64_t *pmt_base = kvm_host_get_pmt(kvm);
+       unsigned long pte;
+
+       pte = PAGE_ALIGN(paddr) | mem_flags;
+       pmt_base[gfn] = pte;
+}
+
+/*Function for translating host address to guest address*/
+
+static inline void *to_guest(struct kvm *kvm, void *addr)
+{
+       return (void *)((unsigned long)(addr) - kvm->arch.vm_base +
+                       KVM_VM_DATA_BASE);
+}
+
+/*Function for translating guest address to host address*/
+
+static inline void *to_host(struct kvm *kvm, void *addr)
+{
+       return (void *)((unsigned long)addr - KVM_VM_DATA_BASE
+                       + kvm->arch.vm_base);
+}
+
+/* Get host context of the vcpu */
+static inline union context *kvm_get_host_context(struct kvm_vcpu *vcpu)
+{
+       union context *ctx = &vcpu->arch.host;
+       return to_guest(vcpu->kvm, ctx);
+}
+
+/* Get guest context of the vcpu */
+static inline union context *kvm_get_guest_context(struct kvm_vcpu *vcpu)
+{
+       union context *ctx = &vcpu->arch.guest;
+       return  to_guest(vcpu->kvm, ctx);
+}
+
+/* kvm get exit data from gvmm! */
+static inline struct exit_ctl_data *kvm_get_exit_data(struct kvm_vcpu *vcpu)
+{
+       return &vcpu->arch.exit_data;
+}
+
+/*kvm get vcpu ioreq for kvm module!*/
+static inline struct kvm_mmio_req *kvm_get_vcpu_ioreq(struct kvm_vcpu *vcpu)
+{
+       struct exit_ctl_data *p_ctl_data;
+
+       if (vcpu) {
+               p_ctl_data = kvm_get_exit_data(vcpu);
+               if (p_ctl_data->exit_reason == EXIT_REASON_MMIO_INSTRUCTION)
+                       return &p_ctl_data->u.ioreq;
+       }
+
+       return NULL;
+}
+
+#endif
diff --git a/arch/ia64/kvm/mmio.c b/arch/ia64/kvm/mmio.c
new file mode 100644 (file)
index 0000000..351bf70
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * mmio.c: MMIO emulation components.
+ * Copyright (c) 2004, Intel Corporation.
+ *  Yaozu Dong (Eddie Dong) (Eddie.dong@intel.com)
+ *  Kun Tian (Kevin Tian) (Kevin.tian@intel.com)
+ *
+ * Copyright (c) 2007 Intel Corporation  KVM support.
+ * Xuefei Xu (Anthony Xu) (anthony.xu@intel.com)
+ * Xiantao Zhang  (xiantao.zhang@intel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <linux/kvm_host.h>
+
+#include "vcpu.h"
+
+static void vlsapic_write_xtp(struct kvm_vcpu *v, uint8_t val)
+{
+       VLSAPIC_XTP(v) = val;
+}
+
+/*
+ * LSAPIC OFFSET
+ */
+#define PIB_LOW_HALF(ofst)     !(ofst & (1 << 20))
+#define PIB_OFST_INTA          0x1E0000
+#define PIB_OFST_XTP           0x1E0008
+
+/*
+ * execute write IPI op.
+ */
+static void vlsapic_write_ipi(struct kvm_vcpu *vcpu,
+                                       uint64_t addr, uint64_t data)
+{
+       struct exit_ctl_data *p = &current_vcpu->arch.exit_data;
+       unsigned long psr;
+
+       local_irq_save(psr);
+
+       p->exit_reason = EXIT_REASON_IPI;
+       p->u.ipi_data.addr.val = addr;
+       p->u.ipi_data.data.val = data;
+       vmm_transition(current_vcpu);
+
+       local_irq_restore(psr);
+
+}
+
+void lsapic_write(struct kvm_vcpu *v, unsigned long addr,
+                       unsigned long length, unsigned long val)
+{
+       addr &= (PIB_SIZE - 1);
+
+       switch (addr) {
+       case PIB_OFST_INTA:
+               /*panic_domain(NULL, "Undefined write on PIB INTA\n");*/
+               panic_vm(v);
+               break;
+       case PIB_OFST_XTP:
+               if (length == 1) {
+                       vlsapic_write_xtp(v, val);
+               } else {
+                       /*panic_domain(NULL,
+                       "Undefined write on PIB XTP\n");*/
+                       panic_vm(v);
+               }
+               break;
+       default:
+               if (PIB_LOW_HALF(addr)) {
+                       /*lower half */
+                       if (length != 8)
+                               /*panic_domain(NULL,
+                               "Can't LHF write with size %ld!\n",
+                               length);*/
+                               panic_vm(v);
+                       else
+                               vlsapic_write_ipi(v, addr, val);
+               } else {   /*   upper half
+                               printk("IPI-UHF write %lx\n",addr);*/
+                       panic_vm(v);
+               }
+               break;
+       }
+}
+
+unsigned long lsapic_read(struct kvm_vcpu *v, unsigned long addr,
+               unsigned long length)
+{
+       uint64_t result = 0;
+
+       addr &= (PIB_SIZE - 1);
+
+       switch (addr) {
+       case PIB_OFST_INTA:
+               if (length == 1) /* 1 byte load */
+                       ; /* There is no i8259, there is no INTA access*/
+               else
+                       /*panic_domain(NULL,"Undefined read on PIB INTA\n"); */
+                       panic_vm(v);
+
+               break;
+       case PIB_OFST_XTP:
+               if (length == 1) {
+                       result = VLSAPIC_XTP(v);
+                       /* printk("read xtp %lx\n", result); */
+               } else {
+                       /*panic_domain(NULL,
+                       "Undefined read on PIB XTP\n");*/
+                       panic_vm(v);
+               }
+               break;
+       default:
+               panic_vm(v);
+               break;
+       }
+       return result;
+}
+
+static void mmio_access(struct kvm_vcpu *vcpu, u64 src_pa, u64 *dest,
+                                       u16 s, int ma, int dir)
+{
+       unsigned long iot;
+       struct exit_ctl_data *p = &vcpu->arch.exit_data;
+       unsigned long psr;
+
+       iot = __gpfn_is_io(src_pa >> PAGE_SHIFT);
+
+       local_irq_save(psr);
+
+       /*Intercept the acces for PIB range*/
+       if (iot == GPFN_PIB) {
+               if (!dir)
+                       lsapic_write(vcpu, src_pa, s, *dest);
+               else
+                       *dest = lsapic_read(vcpu, src_pa, s);
+               goto out;
+       }
+       p->exit_reason = EXIT_REASON_MMIO_INSTRUCTION;
+       p->u.ioreq.addr = src_pa;
+       p->u.ioreq.size = s;
+       p->u.ioreq.dir = dir;
+       if (dir == IOREQ_WRITE)
+               p->u.ioreq.data = *dest;
+       p->u.ioreq.state = STATE_IOREQ_READY;
+       vmm_transition(vcpu);
+
+       if (p->u.ioreq.state == STATE_IORESP_READY) {
+               if (dir == IOREQ_READ)
+                       *dest = p->u.ioreq.data;
+       } else
+               panic_vm(vcpu);
+out:
+       local_irq_restore(psr);
+       return ;
+}
+
+/*
+   dir 1: read 0:write
+   inst_type 0:integer 1:floating point
+ */
+#define SL_INTEGER     0       /* store/load interger*/
+#define SL_FLOATING    1       /* store/load floating*/
+
+void emulate_io_inst(struct kvm_vcpu *vcpu, u64 padr, u64 ma)
+{
+       struct kvm_pt_regs *regs;
+       IA64_BUNDLE bundle;
+       int slot, dir = 0;
+       int inst_type = -1;
+       u16 size = 0;
+       u64 data, slot1a, slot1b, temp, update_reg;
+       s32 imm;
+       INST64 inst;
+
+       regs = vcpu_regs(vcpu);
+
+       if (fetch_code(vcpu, regs->cr_iip, &bundle)) {
+               /* if fetch code fail, return and try again */
+               return;
+       }
+       slot = ((struct ia64_psr *)&(regs->cr_ipsr))->ri;
+       if (!slot)
+               inst.inst = bundle.slot0;
+       else if (slot == 1) {
+               slot1a = bundle.slot1a;
+               slot1b = bundle.slot1b;
+               inst.inst = slot1a + (slot1b << 18);
+       } else if (slot == 2)
+               inst.inst = bundle.slot2;
+
+       /* Integer Load/Store */
+       if (inst.M1.major == 4 && inst.M1.m == 0 && inst.M1.x == 0) {
+               inst_type = SL_INTEGER;
+               size = (inst.M1.x6 & 0x3);
+               if ((inst.M1.x6 >> 2) > 0xb) {
+                       /*write*/
+                       dir = IOREQ_WRITE;
+                       data = vcpu_get_gr(vcpu, inst.M4.r2);
+               } else if ((inst.M1.x6 >> 2) < 0xb) {
+                       /*read*/
+                       dir = IOREQ_READ;
+               }
+       } else if (inst.M2.major == 4 && inst.M2.m == 1 && inst.M2.x == 0) {
+               /* Integer Load + Reg update */
+               inst_type = SL_INTEGER;
+               dir = IOREQ_READ;
+               size = (inst.M2.x6 & 0x3);
+               temp = vcpu_get_gr(vcpu, inst.M2.r3);
+               update_reg = vcpu_get_gr(vcpu, inst.M2.r2);
+               temp += update_reg;
+               vcpu_set_gr(vcpu, inst.M2.r3, temp, 0);
+       } else if (inst.M3.major == 5) {
+               /*Integer Load/Store + Imm update*/
+               inst_type = SL_INTEGER;
+               size = (inst.M3.x6&0x3);
+               if ((inst.M5.x6 >> 2) > 0xb) {
+                       /*write*/
+                       dir = IOREQ_WRITE;
+                       data = vcpu_get_gr(vcpu, inst.M5.r2);
+                       temp = vcpu_get_gr(vcpu, inst.M5.r3);
+                       imm = (inst.M5.s << 31) | (inst.M5.i << 30) |
+                               (inst.M5.imm7 << 23);
+                       temp += imm >> 23;
+                       vcpu_set_gr(vcpu, inst.M5.r3, temp, 0);
+
+               } else if ((inst.M3.x6 >> 2) < 0xb) {
+                       /*read*/
+                       dir = IOREQ_READ;
+                       temp = vcpu_get_gr(vcpu, inst.M3.r3);
+                       imm = (inst.M3.s << 31) | (inst.M3.i << 30) |
+                               (inst.M3.imm7 << 23);
+                       temp += imm >> 23;
+                       vcpu_set_gr(vcpu, inst.M3.r3, temp, 0);
+
+               }
+       } else if (inst.M9.major == 6 && inst.M9.x6 == 0x3B
+                               && inst.M9.m == 0 && inst.M9.x == 0) {
+               /* Floating-point spill*/
+               struct ia64_fpreg v;
+
+               inst_type = SL_FLOATING;
+               dir = IOREQ_WRITE;
+               vcpu_get_fpreg(vcpu, inst.M9.f2, &v);
+               /* Write high word. FIXME: this is a kludge!  */
+               v.u.bits[1] &= 0x3ffff;
+               mmio_access(vcpu, padr + 8, &v.u.bits[1], 8, ma, IOREQ_WRITE);
+               data = v.u.bits[0];
+               size = 3;
+       } else if (inst.M10.major == 7 && inst.M10.x6 == 0x3B) {
+               /* Floating-point spill + Imm update */
+               struct ia64_fpreg v;
+
+               inst_type = SL_FLOATING;
+               dir = IOREQ_WRITE;
+               vcpu_get_fpreg(vcpu, inst.M10.f2, &v);
+               temp = vcpu_get_gr(vcpu, inst.M10.r3);
+               imm = (inst.M10.s << 31) | (inst.M10.i << 30) |
+                       (inst.M10.imm7 << 23);
+               temp += imm >> 23;
+               vcpu_set_gr(vcpu, inst.M10.r3, temp, 0);
+
+               /* Write high word.FIXME: this is a kludge!  */
+               v.u.bits[1] &= 0x3ffff;
+               mmio_access(vcpu, padr + 8, &v.u.bits[1], 8, ma, IOREQ_WRITE);
+               data = v.u.bits[0];
+               size = 3;
+       } else if (inst.M10.major == 7 && inst.M10.x6 == 0x31) {
+               /* Floating-point stf8 + Imm update */
+               struct ia64_fpreg v;
+               inst_type = SL_FLOATING;
+               dir = IOREQ_WRITE;
+               size = 3;
+               vcpu_get_fpreg(vcpu, inst.M10.f2, &v);
+               data = v.u.bits[0]; /* Significand.  */
+               temp = vcpu_get_gr(vcpu, inst.M10.r3);
+               imm = (inst.M10.s << 31) | (inst.M10.i << 30) |
+                       (inst.M10.imm7 << 23);
+               temp += imm >> 23;
+               vcpu_set_gr(vcpu, inst.M10.r3, temp, 0);
+       } else if (inst.M15.major == 7 && inst.M15.x6 >= 0x2c
+                       && inst.M15.x6 <= 0x2f) {
+               temp = vcpu_get_gr(vcpu, inst.M15.r3);
+               imm = (inst.M15.s << 31) | (inst.M15.i << 30) |
+                       (inst.M15.imm7 << 23);
+               temp += imm >> 23;
+               vcpu_set_gr(vcpu, inst.M15.r3, temp, 0);
+
+               vcpu_increment_iip(vcpu);
+               return;
+       } else if (inst.M12.major == 6 && inst.M12.m == 1
+                       && inst.M12.x == 1 && inst.M12.x6 == 1) {
+               /* Floating-point Load Pair + Imm ldfp8 M12*/
+               struct ia64_fpreg v;
+
+               inst_type = SL_FLOATING;
+               dir = IOREQ_READ;
+               size = 8;     /*ldfd*/
+               mmio_access(vcpu, padr, &data, size, ma, dir);
+               v.u.bits[0] = data;
+               v.u.bits[1] = 0x1003E;
+               vcpu_set_fpreg(vcpu, inst.M12.f1, &v);
+               padr += 8;
+               mmio_access(vcpu, padr, &data, size, ma, dir);
+               v.u.bits[0] = data;
+               v.u.bits[1] = 0x1003E;
+               vcpu_set_fpreg(vcpu, inst.M12.f2, &v);
+               padr += 8;
+               vcpu_set_gr(vcpu, inst.M12.r3, padr, 0);
+               vcpu_increment_iip(vcpu);
+               return;
+       } else {
+               inst_type = -1;
+               panic_vm(vcpu);
+       }
+
+       size = 1 << size;
+       if (dir == IOREQ_WRITE) {
+               mmio_access(vcpu, padr, &data, size, ma, dir);
+       } else {
+               mmio_access(vcpu, padr, &data, size, ma, dir);
+               if (inst_type == SL_INTEGER)
+                       vcpu_set_gr(vcpu, inst.M1.r1, data, 0);
+               else
+                       panic_vm(vcpu);
+
+       }
+       vcpu_increment_iip(vcpu);
+}
diff --git a/arch/ia64/kvm/optvfault.S b/arch/ia64/kvm/optvfault.S
new file mode 100644 (file)
index 0000000..e4f15d6
--- /dev/null
@@ -0,0 +1,918 @@
+/*
+ * arch/ia64/vmx/optvfault.S
+ * optimize virtualization fault handler
+ *
+ * Copyright (C) 2006 Intel Co
+ *     Xuefei Xu (Anthony Xu) <anthony.xu@intel.com>
+ */
+
+#include <asm/asmmacro.h>
+#include <asm/processor.h>
+
+#include "vti.h"
+#include "asm-offsets.h"
+
+#define ACCE_MOV_FROM_AR
+#define ACCE_MOV_FROM_RR
+#define ACCE_MOV_TO_RR
+#define ACCE_RSM
+#define ACCE_SSM
+#define ACCE_MOV_TO_PSR
+#define ACCE_THASH
+
+//mov r1=ar3
+GLOBAL_ENTRY(kvm_asm_mov_from_ar)
+#ifndef ACCE_MOV_FROM_AR
+       br.many kvm_virtualization_fault_back
+#endif
+       add r18=VMM_VCPU_ITC_OFS_OFFSET, r21
+       add r16=VMM_VCPU_LAST_ITC_OFFSET,r21
+       extr.u r17=r25,6,7
+       ;;
+       ld8 r18=[r18]
+       mov r19=ar.itc
+       mov r24=b0
+       ;;
+       add r19=r19,r18
+       addl r20=@gprel(asm_mov_to_reg),gp
+       ;;
+       st8 [r16] = r19
+       adds r30=kvm_resume_to_guest-asm_mov_to_reg,r20
+       shladd r17=r17,4,r20
+       ;;
+       mov b0=r17
+       br.sptk.few b0
+       ;;
+END(kvm_asm_mov_from_ar)
+
+
+// mov r1=rr[r3]
+GLOBAL_ENTRY(kvm_asm_mov_from_rr)
+#ifndef ACCE_MOV_FROM_RR
+       br.many kvm_virtualization_fault_back
+#endif
+       extr.u r16=r25,20,7
+       extr.u r17=r25,6,7
+       addl r20=@gprel(asm_mov_from_reg),gp
+       ;;
+       adds r30=kvm_asm_mov_from_rr_back_1-asm_mov_from_reg,r20
+       shladd r16=r16,4,r20
+       mov r24=b0
+       ;;
+       add r27=VMM_VCPU_VRR0_OFFSET,r21
+       mov b0=r16
+       br.many b0
+       ;;
+kvm_asm_mov_from_rr_back_1:
+       adds r30=kvm_resume_to_guest-asm_mov_from_reg,r20
+       adds r22=asm_mov_to_reg-asm_mov_from_reg,r20
+       shr.u r26=r19,61
+       ;;
+       shladd r17=r17,4,r22
+       shladd r27=r26,3,r27
+       ;;
+       ld8 r19=[r27]
+       mov b0=r17
+       br.many b0
+END(kvm_asm_mov_from_rr)
+
+
+// mov rr[r3]=r2
+GLOBAL_ENTRY(kvm_asm_mov_to_rr)
+#ifndef ACCE_MOV_TO_RR
+       br.many kvm_virtualization_fault_back
+#endif
+       extr.u r16=r25,20,7
+       extr.u r17=r25,13,7
+       addl r20=@gprel(asm_mov_from_reg),gp
+       ;;
+       adds r30=kvm_asm_mov_to_rr_back_1-asm_mov_from_reg,r20
+       shladd r16=r16,4,r20
+       mov r22=b0
+       ;;
+       add r27=VMM_VCPU_VRR0_OFFSET,r21
+       mov b0=r16
+       br.many b0
+       ;;
+kvm_asm_mov_to_rr_back_1:
+       adds r30=kvm_asm_mov_to_rr_back_2-asm_mov_from_reg,r20
+       shr.u r23=r19,61
+       shladd r17=r17,4,r20
+       ;;
+       //if rr6, go back
+       cmp.eq p6,p0=6,r23
+       mov b0=r22
+       (p6) br.cond.dpnt.many kvm_virtualization_fault_back
+       ;;
+       mov r28=r19
+       mov b0=r17
+       br.many b0
+kvm_asm_mov_to_rr_back_2:
+       adds r30=kvm_resume_to_guest-asm_mov_from_reg,r20
+       shladd r27=r23,3,r27
+       ;; // vrr.rid<<4 |0xe
+       st8 [r27]=r19
+       mov b0=r30
+       ;;
+       extr.u r16=r19,8,26
+       extr.u r18 =r19,2,6
+       mov r17 =0xe
+       ;;
+       shladd r16 = r16, 4, r17
+       extr.u r19 =r19,0,8
+       ;;
+       shl r16 = r16,8
+       ;;
+       add r19 = r19, r16
+       ;; //set ve 1
+       dep r19=-1,r19,0,1
+       cmp.lt p6,p0=14,r18
+       ;;
+       (p6) mov r18=14
+       ;;
+       (p6) dep r19=r18,r19,2,6
+       ;;
+       cmp.eq p6,p0=0,r23
+       ;;
+       cmp.eq.or p6,p0=4,r23
+       ;;
+       adds r16=VMM_VCPU_MODE_FLAGS_OFFSET,r21
+       (p6) adds r17=VMM_VCPU_META_SAVED_RR0_OFFSET,r21
+       ;;
+       ld4 r16=[r16]
+       cmp.eq p7,p0=r0,r0
+       (p6) shladd r17=r23,1,r17
+       ;;
+       (p6) st8 [r17]=r19
+       (p6) tbit.nz p6,p7=r16,0
+       ;;
+       (p7) mov rr[r28]=r19
+       mov r24=r22
+       br.many b0
+END(kvm_asm_mov_to_rr)
+
+
+//rsm
+GLOBAL_ENTRY(kvm_asm_rsm)
+#ifndef ACCE_RSM
+       br.many kvm_virtualization_fault_back
+#endif
+       add r16=VMM_VPD_BASE_OFFSET,r21
+       extr.u r26=r25,6,21
+       extr.u r27=r25,31,2
+       ;;
+       ld8 r16=[r16]
+       extr.u r28=r25,36,1
+       dep r26=r27,r26,21,2
+       ;;
+       add r17=VPD_VPSR_START_OFFSET,r16
+       add r22=VMM_VCPU_MODE_FLAGS_OFFSET,r21
+       //r26 is imm24
+       dep r26=r28,r26,23,1
+       ;;
+       ld8 r18=[r17]
+       movl r28=IA64_PSR_IC+IA64_PSR_I+IA64_PSR_DT+IA64_PSR_SI
+       ld4 r23=[r22]
+       sub r27=-1,r26
+       mov r24=b0
+       ;;
+       mov r20=cr.ipsr
+       or r28=r27,r28
+       and r19=r18,r27
+       ;;
+       st8 [r17]=r19
+       and r20=r20,r28
+       /* Comment it out due to short of fp lazy alorgithm support
+       adds r27=IA64_VCPU_FP_PSR_OFFSET,r21
+       ;;
+       ld8 r27=[r27]
+       ;;
+       tbit.nz p8,p0= r27,IA64_PSR_DFH_BIT
+       ;;
+       (p8) dep r20=-1,r20,IA64_PSR_DFH_BIT,1
+       */
+       ;;
+       mov cr.ipsr=r20
+       tbit.nz p6,p0=r23,0
+       ;;
+       tbit.z.or p6,p0=r26,IA64_PSR_DT_BIT
+       (p6) br.dptk kvm_resume_to_guest
+       ;;
+       add r26=VMM_VCPU_META_RR0_OFFSET,r21
+       add r27=VMM_VCPU_META_RR0_OFFSET+8,r21
+       dep r23=-1,r23,0,1
+       ;;
+       ld8 r26=[r26]
+       ld8 r27=[r27]
+       st4 [r22]=r23
+       dep.z r28=4,61,3
+       ;;
+       mov rr[r0]=r26
+       ;;
+       mov rr[r28]=r27
+       ;;
+       srlz.d
+       br.many kvm_resume_to_guest
+END(kvm_asm_rsm)
+
+
+//ssm
+GLOBAL_ENTRY(kvm_asm_ssm)
+#ifndef ACCE_SSM
+       br.many kvm_virtualization_fault_back
+#endif
+       add r16=VMM_VPD_BASE_OFFSET,r21
+       extr.u r26=r25,6,21
+       extr.u r27=r25,31,2
+       ;;
+       ld8 r16=[r16]
+       extr.u r28=r25,36,1
+       dep r26=r27,r26,21,2
+       ;;  //r26 is imm24
+       add r27=VPD_VPSR_START_OFFSET,r16
+       dep r26=r28,r26,23,1
+       ;;  //r19 vpsr
+       ld8 r29=[r27]
+       mov r24=b0
+       ;;
+       add r22=VMM_VCPU_MODE_FLAGS_OFFSET,r21
+       mov r20=cr.ipsr
+       or r19=r29,r26
+       ;;
+       ld4 r23=[r22]
+       st8 [r27]=r19
+       or r20=r20,r26
+       ;;
+       mov cr.ipsr=r20
+       movl r28=IA64_PSR_DT+IA64_PSR_RT+IA64_PSR_IT
+       ;;
+       and r19=r28,r19
+       tbit.z p6,p0=r23,0
+       ;;
+       cmp.ne.or p6,p0=r28,r19
+       (p6) br.dptk kvm_asm_ssm_1
+       ;;
+       add r26=VMM_VCPU_META_SAVED_RR0_OFFSET,r21
+       add r27=VMM_VCPU_META_SAVED_RR0_OFFSET+8,r21
+       dep r23=0,r23,0,1
+       ;;
+       ld8 r26=[r26]
+       ld8 r27=[r27]
+       st4 [r22]=r23
+       dep.z r28=4,61,3
+       ;;
+       mov rr[r0]=r26
+       ;;
+       mov rr[r28]=r27
+       ;;
+       srlz.d
+       ;;
+kvm_asm_ssm_1:
+       tbit.nz p6,p0=r29,IA64_PSR_I_BIT
+       ;;
+       tbit.z.or p6,p0=r19,IA64_PSR_I_BIT
+       (p6) br.dptk kvm_resume_to_guest
+       ;;
+       add r29=VPD_VTPR_START_OFFSET,r16
+       add r30=VPD_VHPI_START_OFFSET,r16
+       ;;
+       ld8 r29=[r29]
+       ld8 r30=[r30]
+       ;;
+       extr.u r17=r29,4,4
+       extr.u r18=r29,16,1
+       ;;
+       dep r17=r18,r17,4,1
+       ;;
+       cmp.gt p6,p0=r30,r17
+       (p6) br.dpnt.few kvm_asm_dispatch_vexirq
+       br.many kvm_resume_to_guest
+END(kvm_asm_ssm)
+
+
+//mov psr.l=r2
+GLOBAL_ENTRY(kvm_asm_mov_to_psr)
+#ifndef ACCE_MOV_TO_PSR
+       br.many kvm_virtualization_fault_back
+#endif
+       add r16=VMM_VPD_BASE_OFFSET,r21
+       extr.u r26=r25,13,7 //r2
+       ;;
+       ld8 r16=[r16]
+       addl r20=@gprel(asm_mov_from_reg),gp
+       ;;
+       adds r30=kvm_asm_mov_to_psr_back-asm_mov_from_reg,r20
+       shladd r26=r26,4,r20
+       mov r24=b0
+       ;;
+       add r27=VPD_VPSR_START_OFFSET,r16
+       mov b0=r26
+       br.many b0
+       ;;
+kvm_asm_mov_to_psr_back:
+       ld8 r17=[r27]
+       add r22=VMM_VCPU_MODE_FLAGS_OFFSET,r21
+       dep r19=0,r19,32,32
+       ;;
+       ld4 r23=[r22]
+       dep r18=0,r17,0,32
+       ;;
+       add r30=r18,r19
+       movl r28=IA64_PSR_DT+IA64_PSR_RT+IA64_PSR_IT
+       ;;
+       st8 [r27]=r30
+       and r27=r28,r30
+       and r29=r28,r17
+       ;;
+       cmp.eq p5,p0=r29,r27
+       cmp.eq p6,p7=r28,r27
+       (p5) br.many kvm_asm_mov_to_psr_1
+       ;;
+       //virtual to physical
+       (p7) add r26=VMM_VCPU_META_RR0_OFFSET,r21
+       (p7) add r27=VMM_VCPU_META_RR0_OFFSET+8,r21
+       (p7) dep r23=-1,r23,0,1
+       ;;
+       //physical to virtual
+       (p6) add r26=VMM_VCPU_META_SAVED_RR0_OFFSET,r21
+       (p6) add r27=VMM_VCPU_META_SAVED_RR0_OFFSET+8,r21
+       (p6) dep r23=0,r23,0,1
+       ;;
+       ld8 r26=[r26]
+       ld8 r27=[r27]
+       st4 [r22]=r23
+       dep.z r28=4,61,3
+       ;;
+       mov rr[r0]=r26
+       ;;
+       mov rr[r28]=r27
+       ;;
+       srlz.d
+       ;;
+kvm_asm_mov_to_psr_1:
+       mov r20=cr.ipsr
+       movl r28=IA64_PSR_IC+IA64_PSR_I+IA64_PSR_DT+IA64_PSR_SI+IA64_PSR_RT
+       ;;
+       or r19=r19,r28
+       dep r20=0,r20,0,32
+       ;;
+       add r20=r19,r20
+       mov b0=r24
+       ;;
+       /* Comment it out due to short of fp lazy algorithm support
+       adds r27=IA64_VCPU_FP_PSR_OFFSET,r21
+       ;;
+       ld8 r27=[r27]
+       ;;
+       tbit.nz p8,p0=r27,IA64_PSR_DFH_BIT
+       ;;
+       (p8) dep r20=-1,r20,IA64_PSR_DFH_BIT,1
+       ;;
+       */
+       mov cr.ipsr=r20
+       cmp.ne p6,p0=r0,r0
+       ;;
+       tbit.nz.or p6,p0=r17,IA64_PSR_I_BIT
+       tbit.z.or p6,p0=r30,IA64_PSR_I_BIT
+       (p6) br.dpnt.few kvm_resume_to_guest
+       ;;
+       add r29=VPD_VTPR_START_OFFSET,r16
+       add r30=VPD_VHPI_START_OFFSET,r16
+       ;;
+       ld8 r29=[r29]
+       ld8 r30=[r30]
+       ;;
+       extr.u r17=r29,4,4
+       extr.u r18=r29,16,1
+       ;;
+       dep r17=r18,r17,4,1
+       ;;
+       cmp.gt p6,p0=r30,r17
+       (p6) br.dpnt.few kvm_asm_dispatch_vexirq
+       br.many kvm_resume_to_guest
+END(kvm_asm_mov_to_psr)
+
+
+ENTRY(kvm_asm_dispatch_vexirq)
+//increment iip
+       mov r16=cr.ipsr
+       ;;
+       extr.u r17=r16,IA64_PSR_RI_BIT,2
+       tbit.nz p6,p7=r16,IA64_PSR_RI_BIT+1
+       ;;
+       (p6) mov r18=cr.iip
+       (p6) mov r17=r0
+       (p7) add r17=1,r17
+       ;;
+       (p6) add r18=0x10,r18
+       dep r16=r17,r16,IA64_PSR_RI_BIT,2
+       ;;
+       (p6) mov cr.iip=r18
+       mov cr.ipsr=r16
+       mov r30 =1
+       br.many kvm_dispatch_vexirq
+END(kvm_asm_dispatch_vexirq)
+
+// thash
+// TODO: add support when pta.vf = 1
+GLOBAL_ENTRY(kvm_asm_thash)
+#ifndef ACCE_THASH
+       br.many kvm_virtualization_fault_back
+#endif
+       extr.u r17=r25,20,7             // get r3 from opcode in r25
+       extr.u r18=r25,6,7              // get r1 from opcode in r25
+       addl r20=@gprel(asm_mov_from_reg),gp
+       ;;
+       adds r30=kvm_asm_thash_back1-asm_mov_from_reg,r20
+       shladd r17=r17,4,r20    // get addr of MOVE_FROM_REG(r17)
+       adds r16=VMM_VPD_BASE_OFFSET,r21        // get vcpu.arch.priveregs
+       ;;
+       mov r24=b0
+       ;;
+       ld8 r16=[r16]           // get VPD addr
+       mov b0=r17
+       br.many b0                      // r19 return value
+       ;;
+kvm_asm_thash_back1:
+       shr.u r23=r19,61                // get RR number
+       adds r25=VMM_VCPU_VRR0_OFFSET,r21       // get vcpu->arch.vrr[0]'s addr
+       adds r16=VMM_VPD_VPTA_OFFSET,r16        // get vpta
+       ;;
+       shladd r27=r23,3,r25    // get vcpu->arch.vrr[r23]'s addr
+       ld8 r17=[r16]           // get PTA
+       mov r26=1
+       ;;
+       extr.u r29=r17,2,6              // get pta.size
+       ld8 r25=[r27]           // get vcpu->arch.vrr[r23]'s value
+       ;;
+       extr.u r25=r25,2,6              // get rr.ps
+       shl r22=r26,r29         // 1UL << pta.size
+       ;;
+       shr.u r23=r19,r25               // vaddr >> rr.ps
+       adds r26=3,r29          // pta.size + 3
+       shl r27=r17,3           // pta << 3
+       ;;
+       shl r23=r23,3           // (vaddr >> rr.ps) << 3
+       shr.u r27=r27,r26               // (pta << 3) >> (pta.size+3)
+       movl r16=7<<61
+       ;;
+       adds r22=-1,r22         // (1UL << pta.size) - 1
+       shl r27=r27,r29         // ((pta<<3)>>(pta.size+3))<<pta.size
+       and r19=r19,r16         // vaddr & VRN_MASK
+       ;;
+       and r22=r22,r23         // vhpt_offset
+       or r19=r19,r27 // (vadr&VRN_MASK)|(((pta<<3)>>(pta.size + 3))<<pta.size)
+       adds r26=asm_mov_to_reg-asm_mov_from_reg,r20
+       ;;
+       or r19=r19,r22          // calc pval
+       shladd r17=r18,4,r26
+       adds r30=kvm_resume_to_guest-asm_mov_from_reg,r20
+       ;;
+       mov b0=r17
+       br.many b0
+END(kvm_asm_thash)
+
+#define MOV_TO_REG0    \
+{;                     \
+       nop.b 0x0;              \
+       nop.b 0x0;              \
+       nop.b 0x0;              \
+       ;;                      \
+};
+
+
+#define MOV_TO_REG(n)  \
+{;                     \
+       mov r##n##=r19; \
+       mov b0=r30;     \
+       br.sptk.many b0;        \
+       ;;                      \
+};
+
+
+#define MOV_FROM_REG(n)        \
+{;                             \
+       mov r19=r##n##;         \
+       mov b0=r30;             \
+       br.sptk.many b0;                \
+       ;;                              \
+};
+
+
+#define MOV_TO_BANK0_REG(n)                    \
+ENTRY_MIN_ALIGN(asm_mov_to_bank0_reg##n##);    \
+{;                                             \
+       mov r26=r2;                             \
+       mov r2=r19;                             \
+       bsw.1;                                  \
+       ;;                                              \
+};                                             \
+{;                                             \
+       mov r##n##=r2;                          \
+       nop.b 0x0;                                      \
+       bsw.0;                                  \
+       ;;                                              \
+};                                             \
+{;                                             \
+       mov r2=r26;                             \
+       mov b0=r30;                             \
+       br.sptk.many b0;                                \
+       ;;                                              \
+};                                             \
+END(asm_mov_to_bank0_reg##n##)
+
+
+#define MOV_FROM_BANK0_REG(n)                  \
+ENTRY_MIN_ALIGN(asm_mov_from_bank0_reg##n##);  \
+{;                                             \
+       mov r26=r2;                             \
+       nop.b 0x0;                                      \
+       bsw.1;                                  \
+       ;;                                              \
+};                                             \
+{;                                             \
+       mov r2=r##n##;                          \
+       nop.b 0x0;                                      \
+       bsw.0;                                  \
+       ;;                                              \
+};                                             \
+{;                                             \
+       mov r19=r2;                             \
+       mov r2=r26;                             \
+       mov b0=r30;                             \
+};                                             \
+{;                                             \
+       nop.b 0x0;                                      \
+       nop.b 0x0;                                      \
+       br.sptk.many b0;                                \
+       ;;                                              \
+};                                             \
+END(asm_mov_from_bank0_reg##n##)
+
+
+#define JMP_TO_MOV_TO_BANK0_REG(n)             \
+{;                                             \
+       nop.b 0x0;                                      \
+       nop.b 0x0;                                      \
+       br.sptk.many asm_mov_to_bank0_reg##n##; \
+       ;;                                              \
+}
+
+
+#define JMP_TO_MOV_FROM_BANK0_REG(n)           \
+{;                                             \
+       nop.b 0x0;                                      \
+       nop.b 0x0;                                      \
+       br.sptk.many asm_mov_from_bank0_reg##n##;       \
+       ;;                                              \
+}
+
+
+MOV_FROM_BANK0_REG(16)
+MOV_FROM_BANK0_REG(17)
+MOV_FROM_BANK0_REG(18)
+MOV_FROM_BANK0_REG(19)
+MOV_FROM_BANK0_REG(20)
+MOV_FROM_BANK0_REG(21)
+MOV_FROM_BANK0_REG(22)
+MOV_FROM_BANK0_REG(23)
+MOV_FROM_BANK0_REG(24)
+MOV_FROM_BANK0_REG(25)
+MOV_FROM_BANK0_REG(26)
+MOV_FROM_BANK0_REG(27)
+MOV_FROM_BANK0_REG(28)
+MOV_FROM_BANK0_REG(29)
+MOV_FROM_BANK0_REG(30)
+MOV_FROM_BANK0_REG(31)
+
+
+// mov from reg table
+ENTRY(asm_mov_from_reg)
+       MOV_FROM_REG(0)
+       MOV_FROM_REG(1)
+       MOV_FROM_REG(2)
+       MOV_FROM_REG(3)
+       MOV_FROM_REG(4)
+       MOV_FROM_REG(5)
+       MOV_FROM_REG(6)
+       MOV_FROM_REG(7)
+       MOV_FROM_REG(8)
+       MOV_FROM_REG(9)
+       MOV_FROM_REG(10)
+       MOV_FROM_REG(11)
+       MOV_FROM_REG(12)
+       MOV_FROM_REG(13)
+       MOV_FROM_REG(14)
+       MOV_FROM_REG(15)
+       JMP_TO_MOV_FROM_BANK0_REG(16)
+       JMP_TO_MOV_FROM_BANK0_REG(17)
+       JMP_TO_MOV_FROM_BANK0_REG(18)
+       JMP_TO_MOV_FROM_BANK0_REG(19)
+       JMP_TO_MOV_FROM_BANK0_REG(20)
+       JMP_TO_MOV_FROM_BANK0_REG(21)
+       JMP_TO_MOV_FROM_BANK0_REG(22)
+       JMP_TO_MOV_FROM_BANK0_REG(23)
+       JMP_TO_MOV_FROM_BANK0_REG(24)
+       JMP_TO_MOV_FROM_BANK0_REG(25)
+       JMP_TO_MOV_FROM_BANK0_REG(26)
+       JMP_TO_MOV_FROM_BANK0_REG(27)
+       JMP_TO_MOV_FROM_BANK0_REG(28)
+       JMP_TO_MOV_FROM_BANK0_REG(29)
+       JMP_TO_MOV_FROM_BANK0_REG(30)
+       JMP_TO_MOV_FROM_BANK0_REG(31)
+       MOV_FROM_REG(32)
+       MOV_FROM_REG(33)
+       MOV_FROM_REG(34)
+       MOV_FROM_REG(35)
+       MOV_FROM_REG(36)
+       MOV_FROM_REG(37)
+       MOV_FROM_REG(38)
+       MOV_FROM_REG(39)
+       MOV_FROM_REG(40)
+       MOV_FROM_REG(41)
+       MOV_FROM_REG(42)
+       MOV_FROM_REG(43)
+       MOV_FROM_REG(44)
+       MOV_FROM_REG(45)
+       MOV_FROM_REG(46)
+       MOV_FROM_REG(47)
+       MOV_FROM_REG(48)
+       MOV_FROM_REG(49)
+       MOV_FROM_REG(50)
+       MOV_FROM_REG(51)
+       MOV_FROM_REG(52)
+       MOV_FROM_REG(53)
+       MOV_FROM_REG(54)
+       MOV_FROM_REG(55)
+       MOV_FROM_REG(56)
+       MOV_FROM_REG(57)
+       MOV_FROM_REG(58)
+       MOV_FROM_REG(59)
+       MOV_FROM_REG(60)
+       MOV_FROM_REG(61)
+       MOV_FROM_REG(62)
+       MOV_FROM_REG(63)
+       MOV_FROM_REG(64)
+       MOV_FROM_REG(65)
+       MOV_FROM_REG(66)
+       MOV_FROM_REG(67)
+       MOV_FROM_REG(68)
+       MOV_FROM_REG(69)
+       MOV_FROM_REG(70)
+       MOV_FROM_REG(71)
+       MOV_FROM_REG(72)
+       MOV_FROM_REG(73)
+       MOV_FROM_REG(74)
+       MOV_FROM_REG(75)
+       MOV_FROM_REG(76)
+       MOV_FROM_REG(77)
+       MOV_FROM_REG(78)
+       MOV_FROM_REG(79)
+       MOV_FROM_REG(80)
+       MOV_FROM_REG(81)
+       MOV_FROM_REG(82)
+       MOV_FROM_REG(83)
+       MOV_FROM_REG(84)
+       MOV_FROM_REG(85)
+       MOV_FROM_REG(86)
+       MOV_FROM_REG(87)
+       MOV_FROM_REG(88)
+       MOV_FROM_REG(89)
+       MOV_FROM_REG(90)
+       MOV_FROM_REG(91)
+       MOV_FROM_REG(92)
+       MOV_FROM_REG(93)
+       MOV_FROM_REG(94)
+       MOV_FROM_REG(95)
+       MOV_FROM_REG(96)
+       MOV_FROM_REG(97)
+       MOV_FROM_REG(98)
+       MOV_FROM_REG(99)
+       MOV_FROM_REG(100)
+       MOV_FROM_REG(101)
+       MOV_FROM_REG(102)
+       MOV_FROM_REG(103)
+       MOV_FROM_REG(104)
+       MOV_FROM_REG(105)
+       MOV_FROM_REG(106)
+       MOV_FROM_REG(107)
+       MOV_FROM_REG(108)
+       MOV_FROM_REG(109)
+       MOV_FROM_REG(110)
+       MOV_FROM_REG(111)
+       MOV_FROM_REG(112)
+       MOV_FROM_REG(113)
+       MOV_FROM_REG(114)
+       MOV_FROM_REG(115)
+       MOV_FROM_REG(116)
+       MOV_FROM_REG(117)
+       MOV_FROM_REG(118)
+       MOV_FROM_REG(119)
+       MOV_FROM_REG(120)
+       MOV_FROM_REG(121)
+       MOV_FROM_REG(122)
+       MOV_FROM_REG(123)
+       MOV_FROM_REG(124)
+       MOV_FROM_REG(125)
+       MOV_FROM_REG(126)
+       MOV_FROM_REG(127)
+END(asm_mov_from_reg)
+
+
+/* must be in bank 0
+ * parameter:
+ * r31: pr
+ * r24: b0
+ */
+ENTRY(kvm_resume_to_guest)
+       adds r16 = VMM_VCPU_SAVED_GP_OFFSET,r21
+       ;;
+       ld8 r1 =[r16]
+       adds r20 = VMM_VCPU_VSA_BASE_OFFSET,r21
+       ;;
+       mov r16=cr.ipsr
+       ;;
+       ld8 r20 = [r20]
+       adds r19=VMM_VPD_BASE_OFFSET,r21
+       ;;
+       ld8 r25=[r19]
+       extr.u r17=r16,IA64_PSR_RI_BIT,2
+       tbit.nz p6,p7=r16,IA64_PSR_RI_BIT+1
+       ;;
+       (p6) mov r18=cr.iip
+       (p6) mov r17=r0
+       ;;
+       (p6) add r18=0x10,r18
+       (p7) add r17=1,r17
+       ;;
+       (p6) mov cr.iip=r18
+       dep r16=r17,r16,IA64_PSR_RI_BIT,2
+       ;;
+       mov cr.ipsr=r16
+       adds r19= VPD_VPSR_START_OFFSET,r25
+       add r28=PAL_VPS_RESUME_NORMAL,r20
+       add r29=PAL_VPS_RESUME_HANDLER,r20
+       ;;
+       ld8 r19=[r19]
+       mov b0=r29
+       cmp.ne p6,p7 = r0,r0
+       ;;
+       tbit.z p6,p7 = r19,IA64_PSR_IC_BIT              // p1=vpsr.ic
+       ;;
+       (p6) ld8 r26=[r25]
+       (p7) mov b0=r28
+       mov pr=r31,-2
+       br.sptk.many b0             // call pal service
+       ;;
+END(kvm_resume_to_guest)
+
+
+MOV_TO_BANK0_REG(16)
+MOV_TO_BANK0_REG(17)
+MOV_TO_BANK0_REG(18)
+MOV_TO_BANK0_REG(19)
+MOV_TO_BANK0_REG(20)
+MOV_TO_BANK0_REG(21)
+MOV_TO_BANK0_REG(22)
+MOV_TO_BANK0_REG(23)
+MOV_TO_BANK0_REG(24)
+MOV_TO_BANK0_REG(25)
+MOV_TO_BANK0_REG(26)
+MOV_TO_BANK0_REG(27)
+MOV_TO_BANK0_REG(28)
+MOV_TO_BANK0_REG(29)
+MOV_TO_BANK0_REG(30)
+MOV_TO_BANK0_REG(31)
+
+
+// mov to reg table
+ENTRY(asm_mov_to_reg)
+       MOV_TO_REG0
+       MOV_TO_REG(1)
+       MOV_TO_REG(2)
+       MOV_TO_REG(3)
+       MOV_TO_REG(4)
+       MOV_TO_REG(5)
+       MOV_TO_REG(6)
+       MOV_TO_REG(7)
+       MOV_TO_REG(8)
+       MOV_TO_REG(9)
+       MOV_TO_REG(10)
+       MOV_TO_REG(11)
+       MOV_TO_REG(12)
+       MOV_TO_REG(13)
+       MOV_TO_REG(14)
+       MOV_TO_REG(15)
+       JMP_TO_MOV_TO_BANK0_REG(16)
+       JMP_TO_MOV_TO_BANK0_REG(17)
+       JMP_TO_MOV_TO_BANK0_REG(18)
+       JMP_TO_MOV_TO_BANK0_REG(19)
+       JMP_TO_MOV_TO_BANK0_REG(20)
+       JMP_TO_MOV_TO_BANK0_REG(21)
+       JMP_TO_MOV_TO_BANK0_REG(22)
+       JMP_TO_MOV_TO_BANK0_REG(23)
+       JMP_TO_MOV_TO_BANK0_REG(24)
+       JMP_TO_MOV_TO_BANK0_REG(25)
+       JMP_TO_MOV_TO_BANK0_REG(26)
+       JMP_TO_MOV_TO_BANK0_REG(27)
+       JMP_TO_MOV_TO_BANK0_REG(28)
+       JMP_TO_MOV_TO_BANK0_REG(29)
+       JMP_TO_MOV_TO_BANK0_REG(30)
+       JMP_TO_MOV_TO_BANK0_REG(31)
+       MOV_TO_REG(32)
+       MOV_TO_REG(33)
+       MOV_TO_REG(34)
+       MOV_TO_REG(35)
+       MOV_TO_REG(36)
+       MOV_TO_REG(37)
+       MOV_TO_REG(38)
+       MOV_TO_REG(39)
+       MOV_TO_REG(40)
+       MOV_TO_REG(41)
+       MOV_TO_REG(42)
+       MOV_TO_REG(43)
+       MOV_TO_REG(44)
+       MOV_TO_REG(45)
+       MOV_TO_REG(46)
+       MOV_TO_REG(47)
+       MOV_TO_REG(48)
+       MOV_TO_REG(49)
+       MOV_TO_REG(50)
+       MOV_TO_REG(51)
+       MOV_TO_REG(52)
+       MOV_TO_REG(53)
+       MOV_TO_REG(54)
+       MOV_TO_REG(55)
+       MOV_TO_REG(56)
+       MOV_TO_REG(57)
+       MOV_TO_REG(58)
+       MOV_TO_REG(59)
+       MOV_TO_REG(60)
+       MOV_TO_REG(61)
+       MOV_TO_REG(62)
+       MOV_TO_REG(63)
+       MOV_TO_REG(64)
+       MOV_TO_REG(65)
+       MOV_TO_REG(66)
+       MOV_TO_REG(67)
+       MOV_TO_REG(68)
+       MOV_TO_REG(69)
+       MOV_TO_REG(70)
+       MOV_TO_REG(71)
+       MOV_TO_REG(72)
+       MOV_TO_REG(73)
+       MOV_TO_REG(74)
+       MOV_TO_REG(75)
+       MOV_TO_REG(76)
+       MOV_TO_REG(77)
+       MOV_TO_REG(78)
+       MOV_TO_REG(79)
+       MOV_TO_REG(80)
+       MOV_TO_REG(81)
+       MOV_TO_REG(82)
+       MOV_TO_REG(83)
+       MOV_TO_REG(84)
+       MOV_TO_REG(85)
+       MOV_TO_REG(86)
+       MOV_TO_REG(87)
+       MOV_TO_REG(88)
+       MOV_TO_REG(89)
+       MOV_TO_REG(90)
+       MOV_TO_REG(91)
+       MOV_TO_REG(92)
+       MOV_TO_REG(93)
+       MOV_TO_REG(94)
+       MOV_TO_REG(95)
+       MOV_TO_REG(96)
+       MOV_TO_REG(97)
+       MOV_TO_REG(98)
+       MOV_TO_REG(99)
+       MOV_TO_REG(100)
+       MOV_TO_REG(101)
+       MOV_TO_REG(102)
+       MOV_TO_REG(103)
+       MOV_TO_REG(104)
+       MOV_TO_REG(105)
+       MOV_TO_REG(106)
+       MOV_TO_REG(107)
+       MOV_TO_REG(108)
+       MOV_TO_REG(109)
+       MOV_TO_REG(110)
+       MOV_TO_REG(111)
+       MOV_TO_REG(112)
+       MOV_TO_REG(113)
+       MOV_TO_REG(114)
+       MOV_TO_REG(115)
+       MOV_TO_REG(116)
+       MOV_TO_REG(117)
+       MOV_TO_REG(118)
+       MOV_TO_REG(119)
+       MOV_TO_REG(120)
+       MOV_TO_REG(121)
+       MOV_TO_REG(122)
+       MOV_TO_REG(123)
+       MOV_TO_REG(124)
+       MOV_TO_REG(125)
+       MOV_TO_REG(126)
+       MOV_TO_REG(127)
+END(asm_mov_to_reg)
diff --git a/arch/ia64/kvm/process.c b/arch/ia64/kvm/process.c
new file mode 100644 (file)
index 0000000..5a33f7e
--- /dev/null
@@ -0,0 +1,970 @@
+/*
+ * process.c: handle interruption inject for guests.
+ * Copyright (c) 2005, 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., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ *     Shaofan Li (Susue Li) <susie.li@intel.com>
+ *     Xiaoyan Feng (Fleming Feng)  <fleming.feng@intel.com>
+ *     Xuefei Xu (Anthony Xu) (Anthony.xu@intel.com)
+ *     Xiantao Zhang (xiantao.zhang@intel.com)
+ */
+#include "vcpu.h"
+
+#include <asm/pal.h>
+#include <asm/sal.h>
+#include <asm/fpswa.h>
+#include <asm/kregs.h>
+#include <asm/tlb.h>
+
+fpswa_interface_t *vmm_fpswa_interface;
+
+#define IA64_VHPT_TRANS_VECTOR                 0x0000
+#define IA64_INST_TLB_VECTOR                   0x0400
+#define IA64_DATA_TLB_VECTOR                   0x0800
+#define IA64_ALT_INST_TLB_VECTOR               0x0c00
+#define IA64_ALT_DATA_TLB_VECTOR               0x1000
+#define IA64_DATA_NESTED_TLB_VECTOR            0x1400
+#define IA64_INST_KEY_MISS_VECTOR              0x1800
+#define IA64_DATA_KEY_MISS_VECTOR              0x1c00
+#define IA64_DIRTY_BIT_VECTOR                  0x2000
+#define IA64_INST_ACCESS_BIT_VECTOR            0x2400
+#define IA64_DATA_ACCESS_BIT_VECTOR            0x2800
+#define IA64_BREAK_VECTOR                      0x2c00
+#define IA64_EXTINT_VECTOR                     0x3000
+#define IA64_PAGE_NOT_PRESENT_VECTOR           0x5000
+#define IA64_KEY_PERMISSION_VECTOR             0x5100
+#define IA64_INST_ACCESS_RIGHTS_VECTOR         0x5200
+#define IA64_DATA_ACCESS_RIGHTS_VECTOR         0x5300
+#define IA64_GENEX_VECTOR                      0x5400
+#define IA64_DISABLED_FPREG_VECTOR             0x5500
+#define IA64_NAT_CONSUMPTION_VECTOR            0x5600
+#define IA64_SPECULATION_VECTOR                0x5700 /* UNUSED */
+#define IA64_DEBUG_VECTOR                      0x5900
+#define IA64_UNALIGNED_REF_VECTOR              0x5a00
+#define IA64_UNSUPPORTED_DATA_REF_VECTOR       0x5b00
+#define IA64_FP_FAULT_VECTOR                   0x5c00
+#define IA64_FP_TRAP_VECTOR                    0x5d00
+#define IA64_LOWERPRIV_TRANSFER_TRAP_VECTOR    0x5e00
+#define IA64_TAKEN_BRANCH_TRAP_VECTOR          0x5f00
+#define IA64_SINGLE_STEP_TRAP_VECTOR           0x6000
+
+/* SDM vol2 5.5 - IVA based interruption handling */
+#define INITIAL_PSR_VALUE_AT_INTERRUPTION (IA64_PSR_UP | IA64_PSR_MFL |\
+                       IA64_PSR_MFH | IA64_PSR_PK | IA64_PSR_DT |      \
+                       IA64_PSR_RT | IA64_PSR_MC|IA64_PSR_IT)
+
+#define DOMN_PAL_REQUEST    0x110000
+#define DOMN_SAL_REQUEST    0x110001
+
+static u64 vec2off[68] = {0x0, 0x400, 0x800, 0xc00, 0x1000, 0x1400, 0x1800,
+       0x1c00, 0x2000, 0x2400, 0x2800, 0x2c00, 0x3000, 0x3400, 0x3800, 0x3c00,
+       0x4000, 0x4400, 0x4800, 0x4c00, 0x5000, 0x5100, 0x5200, 0x5300, 0x5400,
+       0x5500, 0x5600, 0x5700, 0x5800, 0x5900, 0x5a00, 0x5b00, 0x5c00, 0x5d00,
+       0x5e00, 0x5f00, 0x6000, 0x6100, 0x6200, 0x6300, 0x6400, 0x6500, 0x6600,
+       0x6700, 0x6800, 0x6900, 0x6a00, 0x6b00, 0x6c00, 0x6d00, 0x6e00, 0x6f00,
+       0x7000, 0x7100, 0x7200, 0x7300, 0x7400, 0x7500, 0x7600, 0x7700, 0x7800,
+       0x7900, 0x7a00, 0x7b00, 0x7c00, 0x7d00, 0x7e00, 0x7f00
+};
+
+static void collect_interruption(struct kvm_vcpu *vcpu)
+{
+       u64 ipsr;
+       u64 vdcr;
+       u64 vifs;
+       unsigned long vpsr;
+       struct kvm_pt_regs *regs = vcpu_regs(vcpu);
+
+       vpsr = vcpu_get_psr(vcpu);
+       vcpu_bsw0(vcpu);
+       if (vpsr & IA64_PSR_IC) {
+
+               /* Sync mpsr id/da/dd/ss/ed bits to vipsr
+                * since after guest do rfi, we still want these bits on in
+                * mpsr
+                */
+
+               ipsr = regs->cr_ipsr;
+               vpsr = vpsr | (ipsr & (IA64_PSR_ID | IA64_PSR_DA
+                                       | IA64_PSR_DD | IA64_PSR_SS
+                                       | IA64_PSR_ED));
+               vcpu_set_ipsr(vcpu, vpsr);
+
+               /* Currently, for trap, we do not advance IIP to next
+                * instruction. That's because we assume caller already
+                * set up IIP correctly
+                */
+
+               vcpu_set_iip(vcpu , regs->cr_iip);
+
+               /* set vifs.v to zero */
+               vifs = VCPU(vcpu, ifs);
+               vifs &= ~IA64_IFS_V;
+               vcpu_set_ifs(vcpu, vifs);
+
+               vcpu_set_iipa(vcpu, VMX(vcpu, cr_iipa));
+       }
+
+       vdcr = VCPU(vcpu, dcr);
+
+       /* Set guest psr
+        * up/mfl/mfh/pk/dt/rt/mc/it keeps unchanged
+        * be: set to the value of dcr.be
+        * pp: set to the value of dcr.pp
+        */
+       vpsr &= INITIAL_PSR_VALUE_AT_INTERRUPTION;
+       vpsr |= (vdcr & IA64_DCR_BE);
+
+       /* VDCR pp bit position is different from VPSR pp bit */
+       if (vdcr & IA64_DCR_PP) {
+               vpsr |= IA64_PSR_PP;
+       } else {
+               vpsr &= ~IA64_PSR_PP;;
+       }
+
+       vcpu_set_psr(vcpu, vpsr);
+
+}
+
+void inject_guest_interruption(struct kvm_vcpu *vcpu, u64 vec)
+{
+       u64 viva;
+       struct kvm_pt_regs *regs;
+       union ia64_isr pt_isr;
+
+       regs = vcpu_regs(vcpu);
+
+       /* clear cr.isr.ir (incomplete register frame)*/
+       pt_isr.val = VMX(vcpu, cr_isr);
+       pt_isr.ir = 0;
+       VMX(vcpu, cr_isr) = pt_isr.val;
+
+       collect_interruption(vcpu);
+
+       viva = vcpu_get_iva(vcpu);
+       regs->cr_iip = viva + vec;
+}
+
+static u64 vcpu_get_itir_on_fault(struct kvm_vcpu *vcpu, u64 ifa)
+{
+       union ia64_rr rr, rr1;
+
+       rr.val = vcpu_get_rr(vcpu, ifa);
+       rr1.val = 0;
+       rr1.ps = rr.ps;
+       rr1.rid = rr.rid;
+       return (rr1.val);
+}
+
+
+/*
+ * Set vIFA & vITIR & vIHA, when vPSR.ic =1
+ * Parameter:
+ *  set_ifa: if true, set vIFA
+ *  set_itir: if true, set vITIR
+ *  set_iha: if true, set vIHA
+ */
+void set_ifa_itir_iha(struct kvm_vcpu *vcpu, u64 vadr,
+               int set_ifa, int set_itir, int set_iha)
+{
+       long vpsr;
+       u64 value;
+
+       vpsr = VCPU(vcpu, vpsr);
+       /* Vol2, Table 8-1 */
+       if (vpsr & IA64_PSR_IC) {
+               if (set_ifa)
+                       vcpu_set_ifa(vcpu, vadr);
+               if (set_itir) {
+                       value = vcpu_get_itir_on_fault(vcpu, vadr);
+                       vcpu_set_itir(vcpu, value);
+               }
+
+               if (set_iha) {
+                       value = vcpu_thash(vcpu, vadr);
+                       vcpu_set_iha(vcpu, value);
+               }
+       }
+}
+
+/*
+ * Data TLB Fault
+ *  @ Data TLB vector
+ * Refer to SDM Vol2 Table 5-6 & 8-1
+ */
+void dtlb_fault(struct kvm_vcpu *vcpu, u64 vadr)
+{
+       /* If vPSR.ic, IFA, ITIR, IHA */
+       set_ifa_itir_iha(vcpu, vadr, 1, 1, 1);
+       inject_guest_interruption(vcpu, IA64_DATA_TLB_VECTOR);
+}
+
+/*
+ * Instruction TLB Fault
+ *  @ Instruction TLB vector
+ * Refer to SDM Vol2 Table 5-6 & 8-1
+ */
+void itlb_fault(struct kvm_vcpu *vcpu, u64 vadr)
+{
+       /* If vPSR.ic, IFA, ITIR, IHA */
+       set_ifa_itir_iha(vcpu, vadr, 1, 1, 1);
+       inject_guest_interruption(vcpu, IA64_INST_TLB_VECTOR);
+}
+
+
+
+/*
+ * Data Nested TLB Fault
+ *  @ Data Nested TLB Vector
+ * Refer to SDM Vol2 Table 5-6 & 8-1
+ */
+void nested_dtlb(struct kvm_vcpu *vcpu)
+{
+       inject_guest_interruption(vcpu, IA64_DATA_NESTED_TLB_VECTOR);
+}
+
+/*
+ * Alternate Data TLB Fault
+ *  @ Alternate Data TLB vector
+ * Refer to SDM Vol2 Table 5-6 & 8-1
+ */
+void alt_dtlb(struct kvm_vcpu *vcpu, u64 vadr)
+{
+       set_ifa_itir_iha(vcpu, vadr, 1, 1, 0);
+       inject_guest_interruption(vcpu, IA64_ALT_DATA_TLB_VECTOR);
+}
+
+
+/*
+ * Data TLB Fault
+ *  @ Data TLB vector
+ * Refer to SDM Vol2 Table 5-6 & 8-1
+ */
+void alt_itlb(struct kvm_vcpu *vcpu, u64 vadr)
+{
+       set_ifa_itir_iha(vcpu, vadr, 1, 1, 0);
+       inject_guest_interruption(vcpu, IA64_ALT_INST_TLB_VECTOR);
+}
+
+/* Deal with:
+ *  VHPT Translation Vector
+ */
+static void _vhpt_fault(struct kvm_vcpu *vcpu, u64 vadr)
+{
+       /* If vPSR.ic, IFA, ITIR, IHA*/
+       set_ifa_itir_iha(vcpu, vadr, 1, 1, 1);
+       inject_guest_interruption(vcpu, IA64_VHPT_TRANS_VECTOR);
+
+
+}
+
+/*
+ * VHPT Instruction Fault
+ *  @ VHPT Translation vector
+ * Refer to SDM Vol2 Table 5-6 & 8-1
+ */
+void ivhpt_fault(struct kvm_vcpu *vcpu, u64 vadr)
+{
+       _vhpt_fault(vcpu, vadr);
+}
+
+
+/*
+ * VHPT Data Fault
+ *  @ VHPT Translation vector
+ * Refer to SDM Vol2 Table 5-6 & 8-1
+ */
+void dvhpt_fault(struct kvm_vcpu *vcpu, u64 vadr)
+{
+       _vhpt_fault(vcpu, vadr);
+}
+
+
+
+/*
+ * Deal with:
+ *  General Exception vector
+ */
+void _general_exception(struct kvm_vcpu *vcpu)
+{
+       inject_guest_interruption(vcpu, IA64_GENEX_VECTOR);
+}
+
+
+/*
+ * Illegal Operation Fault
+ *  @ General Exception Vector
+ * Refer to SDM Vol2 Table 5-6 & 8-1
+ */
+void illegal_op(struct kvm_vcpu *vcpu)
+{
+       _general_exception(vcpu);
+}
+
+/*
+ * Illegal Dependency Fault
+ *  @ General Exception Vector
+ * Refer to SDM Vol2 Table 5-6 & 8-1
+ */
+void illegal_dep(struct kvm_vcpu *vcpu)
+{
+       _general_exception(vcpu);
+}
+
+/*
+ * Reserved Register/Field Fault
+ *  @ General Exception Vector
+ * Refer to SDM Vol2 Table 5-6 & 8-1
+ */
+void rsv_reg_field(struct kvm_vcpu *vcpu)
+{
+       _general_exception(vcpu);
+}
+/*
+ * Privileged Operation Fault
+ *  @ General Exception Vector
+ * Refer to SDM Vol2 Table 5-6 & 8-1
+ */
+
+void privilege_op(struct kvm_vcpu *vcpu)
+{
+       _general_exception(vcpu);
+}
+
+/*
+ * Unimplement Data Address Fault
+ *  @ General Exception Vector
+ * Refer to SDM Vol2 Table 5-6 & 8-1
+ */
+void unimpl_daddr(struct kvm_vcpu *vcpu)
+{
+       _general_exception(vcpu);
+}
+
+/*
+ * Privileged Register Fault
+ *  @ General Exception Vector
+ * Refer to SDM Vol2 Table 5-6 & 8-1
+ */
+void privilege_reg(struct kvm_vcpu *vcpu)
+{
+       _general_exception(vcpu);
+}
+
+/* Deal with
+ *  Nat consumption vector
+ * Parameter:
+ *  vaddr: Optional, if t == REGISTER
+ */
+static void _nat_consumption_fault(struct kvm_vcpu *vcpu, u64 vadr,
+                                               enum tlb_miss_type t)
+{
+       /* If vPSR.ic && t == DATA/INST, IFA */
+       if (t == DATA || t == INSTRUCTION) {
+               /* IFA */
+               set_ifa_itir_iha(vcpu, vadr, 1, 0, 0);
+       }
+
+       inject_guest_interruption(vcpu, IA64_NAT_CONSUMPTION_VECTOR);
+}
+
+/*
+ * Instruction Nat Page Consumption Fault
+ *  @ Nat Consumption Vector
+ * Refer to SDM Vol2 Table 5-6 & 8-1
+ */
+void inat_page_consumption(struct kvm_vcpu *vcpu, u64 vadr)
+{
+       _nat_consumption_fault(vcpu, vadr, INSTRUCTION);
+}
+
+/*
+ * Register Nat Consumption Fault
+ *  @ Nat Consumption Vector
+ * Refer to SDM Vol2 Table 5-6 & 8-1
+ */
+void rnat_consumption(struct kvm_vcpu *vcpu)
+{
+       _nat_consumption_fault(vcpu, 0, REGISTER);
+}
+
+/*
+ * Data Nat Page Consumption Fault
+ *  @ Nat Consumption Vector
+ * Refer to SDM Vol2 Table 5-6 & 8-1
+ */
+void dnat_page_consumption(struct kvm_vcpu *vcpu, u64 vadr)
+{
+       _nat_consumption_fault(vcpu, vadr, DATA);
+}
+
+/* Deal with
+ *  Page not present vector
+ */
+static void __page_not_present(struct kvm_vcpu *vcpu, u64 vadr)
+{
+       /* If vPSR.ic, IFA, ITIR */
+       set_ifa_itir_iha(vcpu, vadr, 1, 1, 0);
+       inject_guest_interruption(vcpu, IA64_PAGE_NOT_PRESENT_VECTOR);
+}
+
+
+void data_page_not_present(struct kvm_vcpu *vcpu, u64 vadr)
+{
+       __page_not_present(vcpu, vadr);
+}
+
+
+void inst_page_not_present(struct kvm_vcpu *vcpu, u64 vadr)
+{
+       __page_not_present(vcpu, vadr);
+}
+
+
+/* Deal with
+ *  Data access rights vector
+ */
+void data_access_rights(struct kvm_vcpu *vcpu, u64 vadr)
+{
+       /* If vPSR.ic, IFA, ITIR */
+       set_ifa_itir_iha(vcpu, vadr, 1, 1, 0);
+       inject_guest_interruption(vcpu, IA64_DATA_ACCESS_RIGHTS_VECTOR);
+}
+
+fpswa_ret_t vmm_fp_emulate(int fp_fault, void *bundle, unsigned long *ipsr,
+               unsigned long *fpsr, unsigned long *isr, unsigned long *pr,
+               unsigned long *ifs, struct kvm_pt_regs *regs)
+{
+       fp_state_t fp_state;
+       fpswa_ret_t ret;
+       struct kvm_vcpu *vcpu = current_vcpu;
+
+       uint64_t old_rr7 = ia64_get_rr(7UL<<61);
+
+       if (!vmm_fpswa_interface)
+               return (fpswa_ret_t) {-1, 0, 0, 0};
+
+       /*
+        * Just let fpswa driver to use hardware fp registers.
+        * No fp register is valid in memory.
+        */
+       memset(&fp_state, 0, sizeof(fp_state_t));
+
+       /*
+        * unsigned long (*EFI_FPSWA) (
+        *      unsigned long    trap_type,
+        *      void             *Bundle,
+        *      unsigned long    *pipsr,
+        *      unsigned long    *pfsr,
+        *      unsigned long    *pisr,
+        *      unsigned long    *ppreds,
+        *      unsigned long    *pifs,
+        *      void             *fp_state);
+        */
+       /*Call host fpswa interface directly to virtualize
+        *guest fpswa request!
+        */
+       ia64_set_rr(7UL << 61, vcpu->arch.host.rr[7]);
+       ia64_srlz_d();
+
+       ret = (*vmm_fpswa_interface->fpswa) (fp_fault, bundle,
+                       ipsr, fpsr, isr, pr, ifs, &fp_state);
+       ia64_set_rr(7UL << 61, old_rr7);
+       ia64_srlz_d();
+       return ret;
+}
+
+/*
+ * Handle floating-point assist faults and traps for domain.
+ */
+unsigned long vmm_handle_fpu_swa(int fp_fault, struct kvm_pt_regs *regs,
+                                       unsigned long isr)
+{
+       struct kvm_vcpu *v = current_vcpu;
+       IA64_BUNDLE bundle;
+       unsigned long fault_ip;
+       fpswa_ret_t ret;
+
+       fault_ip = regs->cr_iip;
+       /*
+        * When the FP trap occurs, the trapping instruction is completed.
+        * If ipsr.ri == 0, there is the trapping instruction in previous
+        * bundle.
+        */
+       if (!fp_fault && (ia64_psr(regs)->ri == 0))
+               fault_ip -= 16;
+
+       if (fetch_code(v, fault_ip, &bundle))
+               return -EAGAIN;
+
+       if (!bundle.i64[0] && !bundle.i64[1])
+               return -EACCES;
+
+       ret = vmm_fp_emulate(fp_fault, &bundle, &regs->cr_ipsr, &regs->ar_fpsr,
+                       &isr, &regs->pr, &regs->cr_ifs, regs);
+       return ret.status;
+}
+
+void reflect_interruption(u64 ifa, u64 isr, u64 iim,
+               u64 vec, struct kvm_pt_regs *regs)
+{
+       u64 vector;
+       int status ;
+       struct kvm_vcpu *vcpu = current_vcpu;
+       u64 vpsr = VCPU(vcpu, vpsr);
+
+       vector = vec2off[vec];
+
+       if (!(vpsr & IA64_PSR_IC) && (vector != IA64_DATA_NESTED_TLB_VECTOR)) {
+               panic_vm(vcpu);
+               return;
+       }
+
+       switch (vec) {
+       case 32:        /*IA64_FP_FAULT_VECTOR*/
+               status = vmm_handle_fpu_swa(1, regs, isr);
+               if (!status) {
+                       vcpu_increment_iip(vcpu);
+                       return;
+               } else if (-EAGAIN == status)
+                       return;
+               break;
+       case 33:        /*IA64_FP_TRAP_VECTOR*/
+               status = vmm_handle_fpu_swa(0, regs, isr);
+               if (!status)
+                       return ;
+               else if (-EAGAIN == status) {
+                       vcpu_decrement_iip(vcpu);
+                       return ;
+               }
+               break;
+       }
+
+       VCPU(vcpu, isr) = isr;
+       VCPU(vcpu, iipa) = regs->cr_iip;
+       if (vector == IA64_BREAK_VECTOR || vector == IA64_SPECULATION_VECTOR)
+               VCPU(vcpu, iim) = iim;
+       else
+               set_ifa_itir_iha(vcpu, ifa, 1, 1, 1);
+
+       inject_guest_interruption(vcpu, vector);
+}
+
+static void set_pal_call_data(struct kvm_vcpu *vcpu)
+{
+       struct exit_ctl_data *p = &vcpu->arch.exit_data;
+
+       /*FIXME:For static and stacked convention, firmware
+        * has put the parameters in gr28-gr31 before
+        * break to vmm  !!*/
+
+       p->u.pal_data.gr28 = vcpu_get_gr(vcpu, 28);
+       p->u.pal_data.gr29 = vcpu_get_gr(vcpu, 29);
+       p->u.pal_data.gr30 = vcpu_get_gr(vcpu, 30);
+       p->u.pal_data.gr31 = vcpu_get_gr(vcpu, 31);
+       p->exit_reason = EXIT_REASON_PAL_CALL;
+}
+
+static void set_pal_call_result(struct kvm_vcpu *vcpu)
+{
+       struct exit_ctl_data *p = &vcpu->arch.exit_data;
+
+       if (p->exit_reason == EXIT_REASON_PAL_CALL) {
+               vcpu_set_gr(vcpu, 8, p->u.pal_data.ret.status, 0);
+               vcpu_set_gr(vcpu, 9, p->u.pal_data.ret.v0, 0);
+               vcpu_set_gr(vcpu, 10, p->u.pal_data.ret.v1, 0);
+               vcpu_set_gr(vcpu, 11, p->u.pal_data.ret.v2, 0);
+       } else
+               panic_vm(vcpu);
+}
+
+static void set_sal_call_data(struct kvm_vcpu *vcpu)
+{
+       struct exit_ctl_data *p = &vcpu->arch.exit_data;
+
+       p->u.sal_data.in0 = vcpu_get_gr(vcpu, 32);
+       p->u.sal_data.in1 = vcpu_get_gr(vcpu, 33);
+       p->u.sal_data.in2 = vcpu_get_gr(vcpu, 34);
+       p->u.sal_data.in3 = vcpu_get_gr(vcpu, 35);
+       p->u.sal_data.in4 = vcpu_get_gr(vcpu, 36);
+       p->u.sal_data.in5 = vcpu_get_gr(vcpu, 37);
+       p->u.sal_data.in6 = vcpu_get_gr(vcpu, 38);
+       p->u.sal_data.in7 = vcpu_get_gr(vcpu, 39);
+       p->exit_reason = EXIT_REASON_SAL_CALL;
+}
+
+static void set_sal_call_result(struct kvm_vcpu *vcpu)
+{
+       struct exit_ctl_data *p = &vcpu->arch.exit_data;
+
+       if (p->exit_reason == EXIT_REASON_SAL_CALL) {
+               vcpu_set_gr(vcpu, 8, p->u.sal_data.ret.r8, 0);
+               vcpu_set_gr(vcpu, 9, p->u.sal_data.ret.r9, 0);
+               vcpu_set_gr(vcpu, 10, p->u.sal_data.ret.r10, 0);
+               vcpu_set_gr(vcpu, 11, p->u.sal_data.ret.r11, 0);
+       } else
+               panic_vm(vcpu);
+}
+
+void  kvm_ia64_handle_break(unsigned long ifa, struct kvm_pt_regs *regs,
+               unsigned long isr, unsigned long iim)
+{
+       struct kvm_vcpu *v = current_vcpu;
+
+       if (ia64_psr(regs)->cpl == 0) {
+               /* Allow hypercalls only when cpl = 0.  */
+               if (iim == DOMN_PAL_REQUEST) {
+                       set_pal_call_data(v);
+                       vmm_transition(v);
+                       set_pal_call_result(v);
+                       vcpu_increment_iip(v);
+                       return;
+               } else if (iim == DOMN_SAL_REQUEST) {
+                       set_sal_call_data(v);
+                       vmm_transition(v);
+                       set_sal_call_result(v);
+                       vcpu_increment_iip(v);
+                       return;
+               }
+       }
+       reflect_interruption(ifa, isr, iim, 11, regs);
+}
+
+void check_pending_irq(struct kvm_vcpu *vcpu)
+{
+       int  mask, h_pending, h_inservice;
+       u64 isr;
+       unsigned long  vpsr;
+       struct kvm_pt_regs *regs = vcpu_regs(vcpu);
+
+       h_pending = highest_pending_irq(vcpu);
+       if (h_pending == NULL_VECTOR) {
+               update_vhpi(vcpu, NULL_VECTOR);
+               return;
+       }
+       h_inservice = highest_inservice_irq(vcpu);
+
+       vpsr = VCPU(vcpu, vpsr);
+       mask = irq_masked(vcpu, h_pending, h_inservice);
+       if ((vpsr & IA64_PSR_I) && IRQ_NO_MASKED == mask) {
+               isr = vpsr & IA64_PSR_RI;
+               update_vhpi(vcpu, h_pending);
+               reflect_interruption(0, isr, 0, 12, regs); /* EXT IRQ */
+       } else if (mask == IRQ_MASKED_BY_INSVC) {
+               if (VCPU(vcpu, vhpi))
+                       update_vhpi(vcpu, NULL_VECTOR);
+       } else {
+               /* masked by vpsr.i or vtpr.*/
+               update_vhpi(vcpu, h_pending);
+       }
+}
+
+static void generate_exirq(struct kvm_vcpu *vcpu)
+{
+       unsigned  vpsr;
+       uint64_t isr;
+
+       struct kvm_pt_regs *regs = vcpu_regs(vcpu);
+
+       vpsr = VCPU(vcpu, vpsr);
+       isr = vpsr & IA64_PSR_RI;
+       if (!(vpsr & IA64_PSR_IC))
+               panic_vm(vcpu);
+       reflect_interruption(0, isr, 0, 12, regs); /* EXT IRQ */
+}
+
+void vhpi_detection(struct kvm_vcpu *vcpu)
+{
+       uint64_t    threshold, vhpi;
+       union ia64_tpr       vtpr;
+       struct ia64_psr vpsr;
+
+       vpsr = *(struct ia64_psr *)&VCPU(vcpu, vpsr);
+       vtpr.val = VCPU(vcpu, tpr);
+
+       threshold = ((!vpsr.i) << 5) | (vtpr.mmi << 4) | vtpr.mic;
+       vhpi = VCPU(vcpu, vhpi);
+       if (vhpi > threshold) {
+               /* interrupt actived*/
+               generate_exirq(vcpu);
+       }
+}
+
+
+void leave_hypervisor_tail(void)
+{
+       struct kvm_vcpu *v = current_vcpu;
+
+       if (VMX(v, timer_check)) {
+               VMX(v, timer_check) = 0;
+               if (VMX(v, itc_check)) {
+                       if (vcpu_get_itc(v) > VCPU(v, itm)) {
+                               if (!(VCPU(v, itv) & (1 << 16))) {
+                                       vcpu_pend_interrupt(v, VCPU(v, itv)
+                                                       & 0xff);
+                               VMX(v, itc_check) = 0;
+                               } else {
+                                       v->arch.timer_pending = 1;
+                               }
+                               VMX(v, last_itc) = VCPU(v, itm) + 1;
+                       }
+               }
+       }
+
+       rmb();
+       if (v->arch.irq_new_pending) {
+               v->arch.irq_new_pending = 0;
+               VMX(v, irq_check) = 0;
+               check_pending_irq(v);
+               return;
+       }
+       if (VMX(v, irq_check)) {
+               VMX(v, irq_check) = 0;
+               vhpi_detection(v);
+       }
+}
+
+
+static inline void handle_lds(struct kvm_pt_regs *regs)
+{
+       regs->cr_ipsr |= IA64_PSR_ED;
+}
+
+void physical_tlb_miss(struct kvm_vcpu *vcpu, unsigned long vadr, int type)
+{
+       unsigned long pte;
+       union ia64_rr rr;
+
+       rr.val = ia64_get_rr(vadr);
+       pte =  vadr & _PAGE_PPN_MASK;
+       pte = pte | PHY_PAGE_WB;
+       thash_vhpt_insert(vcpu, pte, (u64)(rr.ps << 2), vadr, type);
+       return;
+}
+
+void kvm_page_fault(u64 vadr , u64 vec, struct kvm_pt_regs *regs)
+{
+       unsigned long vpsr;
+       int type;
+
+       u64 vhpt_adr, gppa, pteval, rr, itir;
+       union ia64_isr misr;
+       union ia64_pta vpta;
+       struct thash_data *data;
+       struct kvm_vcpu *v = current_vcpu;
+
+       vpsr = VCPU(v, vpsr);
+       misr.val = VMX(v, cr_isr);
+
+       type = vec;
+
+       if (is_physical_mode(v) && (!(vadr << 1 >> 62))) {
+               if (vec == 2) {
+                       if (__gpfn_is_io((vadr << 1) >> (PAGE_SHIFT + 1))) {
+                               emulate_io_inst(v, ((vadr << 1) >> 1), 4);
+                               return;
+                       }
+               }
+               physical_tlb_miss(v, vadr, type);
+               return;
+       }
+       data = vtlb_lookup(v, vadr, type);
+       if (data != 0) {
+               if (type == D_TLB) {
+                       gppa = (vadr & ((1UL << data->ps) - 1))
+                               + (data->ppn >> (data->ps - 12) << data->ps);
+                       if (__gpfn_is_io(gppa >> PAGE_SHIFT)) {
+                               if (data->pl >= ((regs->cr_ipsr >>
+                                               IA64_PSR_CPL0_BIT) & 3))
+                                       emulate_io_inst(v, gppa, data->ma);
+                               else {
+                                       vcpu_set_isr(v, misr.val);
+                                       data_access_rights(v, vadr);
+                               }
+                               return ;
+                       }
+               }
+               thash_vhpt_insert(v, data->page_flags, data->itir, vadr, type);
+
+       } else if (type == D_TLB) {
+               if (misr.sp) {
+                       handle_lds(regs);
+                       return;
+               }
+
+               rr = vcpu_get_rr(v, vadr);
+               itir = rr & (RR_RID_MASK | RR_PS_MASK);
+
+               if (!vhpt_enabled(v, vadr, misr.rs ? RSE_REF : DATA_REF)) {
+                       if (vpsr & IA64_PSR_IC) {
+                               vcpu_set_isr(v, misr.val);
+                               alt_dtlb(v, vadr);
+                       } else {
+                               nested_dtlb(v);
+                       }
+                       return ;
+               }
+
+               vpta.val = vcpu_get_pta(v);
+               /* avoid recursively walking (short format) VHPT */
+
+               vhpt_adr = vcpu_thash(v, vadr);
+               if (!guest_vhpt_lookup(vhpt_adr, &pteval)) {
+                       /* VHPT successfully read.  */
+                       if (!(pteval & _PAGE_P)) {
+                               if (vpsr & IA64_PSR_IC) {
+                                       vcpu_set_isr(v, misr.val);
+                                       dtlb_fault(v, vadr);
+                               } else {
+                                       nested_dtlb(v);
+                               }
+                       } else if ((pteval & _PAGE_MA_MASK) != _PAGE_MA_ST) {
+                               thash_purge_and_insert(v, pteval, itir,
+                                                               vadr, D_TLB);
+                       } else if (vpsr & IA64_PSR_IC) {
+                               vcpu_set_isr(v, misr.val);
+                               dtlb_fault(v, vadr);
+                       } else {
+                               nested_dtlb(v);
+                       }
+               } else {
+                       /* Can't read VHPT.  */
+                       if (vpsr & IA64_PSR_IC) {
+                               vcpu_set_isr(v, misr.val);
+                               dvhpt_fault(v, vadr);
+                       } else {
+                               nested_dtlb(v);
+                       }
+               }
+       } else if (type == I_TLB) {
+               if (!(vpsr & IA64_PSR_IC))
+                       misr.ni = 1;
+               if (!vhpt_enabled(v, vadr, INST_REF)) {
+                       vcpu_set_isr(v, misr.val);
+                       alt_itlb(v, vadr);
+                       return;
+               }
+
+               vpta.val = vcpu_get_pta(v);
+
+               vhpt_adr = vcpu_thash(v, vadr);
+               if (!guest_vhpt_lookup(vhpt_adr, &pteval)) {
+                       /* VHPT successfully read.  */
+                       if (pteval & _PAGE_P) {
+                               if ((pteval & _PAGE_MA_MASK) == _PAGE_MA_ST) {
+                                       vcpu_set_isr(v, misr.val);
+                                       itlb_fault(v, vadr);
+                                       return ;
+                               }
+                               rr = vcpu_get_rr(v, vadr);
+                               itir = rr & (RR_RID_MASK | RR_PS_MASK);
+                               thash_purge_and_insert(v, pteval, itir,
+                                                       vadr, I_TLB);
+                       } else {
+                               vcpu_set_isr(v, misr.val);
+                               inst_page_not_present(v, vadr);
+                       }
+               } else {
+                       vcpu_set_isr(v, misr.val);
+                       ivhpt_fault(v, vadr);
+               }
+       }
+}
+
+void kvm_vexirq(struct kvm_vcpu *vcpu)
+{
+       u64 vpsr, isr;
+       struct kvm_pt_regs *regs;
+
+       regs = vcpu_regs(vcpu);
+       vpsr = VCPU(vcpu, vpsr);
+       isr = vpsr & IA64_PSR_RI;
+       reflect_interruption(0, isr, 0, 12, regs); /*EXT IRQ*/
+}
+
+void kvm_ia64_handle_irq(struct kvm_vcpu *v)
+{
+       struct exit_ctl_data *p = &v->arch.exit_data;
+       long psr;
+
+       local_irq_save(psr);
+       p->exit_reason = EXIT_REASON_EXTERNAL_INTERRUPT;
+       vmm_transition(v);
+       local_irq_restore(psr);
+
+       VMX(v, timer_check) = 1;
+
+}
+
+static void ptc_ga_remote_func(struct kvm_vcpu *v, int pos)
+{
+       u64 oldrid, moldrid, oldpsbits, vaddr;
+       struct kvm_ptc_g *p = &v->arch.ptc_g_data[pos];
+       vaddr = p->vaddr;
+
+       oldrid = VMX(v, vrr[0]);
+       VMX(v, vrr[0]) = p->rr;
+       oldpsbits = VMX(v, psbits[0]);
+       VMX(v, psbits[0]) = VMX(v, psbits[REGION_NUMBER(vaddr)]);
+       moldrid = ia64_get_rr(0x0);
+       ia64_set_rr(0x0, vrrtomrr(p->rr));
+       ia64_srlz_d();
+
+       vaddr = PAGEALIGN(vaddr, p->ps);
+       thash_purge_entries_remote(v, vaddr, p->ps);
+
+       VMX(v, vrr[0]) = oldrid;
+       VMX(v, psbits[0]) = oldpsbits;
+       ia64_set_rr(0x0, moldrid);
+       ia64_dv_serialize_data();
+}
+
+static void vcpu_do_resume(struct kvm_vcpu *vcpu)
+{
+       /*Re-init VHPT and VTLB once from resume*/
+       vcpu->arch.vhpt.num = VHPT_NUM_ENTRIES;
+       thash_init(&vcpu->arch.vhpt, VHPT_SHIFT);
+       vcpu->arch.vtlb.num = VTLB_NUM_ENTRIES;
+       thash_init(&vcpu->arch.vtlb, VTLB_SHIFT);
+
+       ia64_set_pta(vcpu->arch.vhpt.pta.val);
+}
+
+static void kvm_do_resume_op(struct kvm_vcpu *vcpu)
+{
+       if (test_and_clear_bit(KVM_REQ_RESUME, &vcpu->requests)) {
+               vcpu_do_resume(vcpu);
+               return;
+       }
+
+       if (unlikely(test_and_clear_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests))) {
+               thash_purge_all(vcpu);
+               return;
+       }
+
+       if (test_and_clear_bit(KVM_REQ_PTC_G, &vcpu->requests)) {
+               while (vcpu->arch.ptc_g_count > 0)
+                       ptc_ga_remote_func(vcpu, --vcpu->arch.ptc_g_count);
+       }
+}
+
+void vmm_transition(struct kvm_vcpu *vcpu)
+{
+       ia64_call_vsa(PAL_VPS_SAVE, (unsigned long)vcpu->arch.vpd,
+                       0, 0, 0, 0, 0, 0);
+       vmm_trampoline(&vcpu->arch.guest, &vcpu->arch.host);
+       ia64_call_vsa(PAL_VPS_RESTORE, (unsigned long)vcpu->arch.vpd,
+                                               0, 0, 0, 0, 0, 0);
+       kvm_do_resume_op(vcpu);
+}
diff --git a/arch/ia64/kvm/trampoline.S b/arch/ia64/kvm/trampoline.S
new file mode 100644 (file)
index 0000000..30897d4
--- /dev/null
@@ -0,0 +1,1038 @@
+/* Save all processor states
+ *
+ * Copyright (c) 2007 Fleming Feng <fleming.feng@intel.com>
+ * Copyright (c) 2007 Anthony Xu   <anthony.xu@intel.com>
+ */
+
+#include <asm/asmmacro.h>
+#include "asm-offsets.h"
+
+
+#define CTX(name)    VMM_CTX_##name##_OFFSET
+
+       /*
+        *      r32:            context_t base address
+        */
+#define        SAVE_BRANCH_REGS                        \
+       add     r2 = CTX(B0),r32;               \
+       add     r3 = CTX(B1),r32;               \
+       mov     r16 = b0;                       \
+       mov     r17 = b1;                       \
+       ;;                                      \
+       st8     [r2]=r16,16;                    \
+       st8     [r3]=r17,16;                    \
+       ;;                                      \
+       mov     r16 = b2;                       \
+       mov     r17 = b3;                       \
+       ;;                                      \
+       st8     [r2]=r16,16;                    \
+       st8     [r3]=r17,16;                    \
+       ;;                                      \
+       mov     r16 = b4;                       \
+       mov     r17 = b5;                       \
+       ;;                                      \
+       st8     [r2]=r16;                       \
+       st8     [r3]=r17;                       \
+       ;;
+
+       /*
+        *      r33:            context_t base address
+        */
+#define        RESTORE_BRANCH_REGS                     \
+       add     r2 = CTX(B0),r33;               \
+       add     r3 = CTX(B1),r33;               \
+       ;;                                      \
+       ld8     r16=[r2],16;                    \
+       ld8     r17=[r3],16;                    \
+       ;;                                      \
+       mov     b0 = r16;                       \
+       mov     b1 = r17;                       \
+       ;;                                      \
+       ld8     r16=[r2],16;                    \
+       ld8     r17=[r3],16;                    \
+       ;;                                      \
+       mov     b2 = r16;                       \
+       mov     b3 = r17;                       \
+       ;;                                      \
+       ld8     r16=[r2];                       \
+       ld8     r17=[r3];                       \
+       ;;                                      \
+       mov     b4=r16;                         \
+       mov     b5=r17;                         \
+       ;;
+
+
+       /*
+        *      r32: context_t base address
+        *      bsw == 1
+        *      Save all bank1 general registers, r4 ~ r7
+        */
+#define        SAVE_GENERAL_REGS                       \
+       add     r2=CTX(R4),r32;                 \
+       add     r3=CTX(R5),r32;                 \
+       ;;                                      \
+.mem.offset 0,0;                               \
+       st8.spill       [r2]=r4,16;             \
+.mem.offset 8,0;                               \
+       st8.spill       [r3]=r5,16;             \
+       ;;                                      \
+.mem.offset 0,0;                               \
+       st8.spill       [r2]=r6,48;             \
+.mem.offset 8,0;                               \
+       st8.spill       [r3]=r7,48;             \
+       ;;                                      \
+.mem.offset 0,0;                               \
+    st8.spill    [r2]=r12;                     \
+.mem.offset 8,0;                               \
+    st8.spill    [r3]=r13;                     \
+    ;;
+
+       /*
+        *      r33: context_t base address
+        *      bsw == 1
+        */
+#define        RESTORE_GENERAL_REGS                    \
+       add     r2=CTX(R4),r33;                 \
+       add     r3=CTX(R5),r33;                 \
+       ;;                                      \
+       ld8.fill        r4=[r2],16;             \
+       ld8.fill        r5=[r3],16;             \
+       ;;                                      \
+       ld8.fill        r6=[r2],48;             \
+       ld8.fill        r7=[r3],48;             \
+       ;;                                      \
+       ld8.fill    r12=[r2];                   \
+       ld8.fill    r13 =[r3];                  \
+       ;;
+
+
+
+
+       /*
+        *      r32:            context_t base address
+        */
+#define        SAVE_KERNEL_REGS                        \
+       add     r2 = CTX(KR0),r32;              \
+       add     r3 = CTX(KR1),r32;              \
+       mov     r16 = ar.k0;                    \
+       mov     r17 = ar.k1;                    \
+       ;;                                      \
+       st8     [r2] = r16,16;                  \
+       st8     [r3] = r17,16;                  \
+       ;;                                      \
+       mov     r16 = ar.k2;                    \
+       mov     r17 = ar.k3;                    \
+       ;;                                      \
+       st8     [r2] = r16,16;                  \
+       st8     [r3] = r17,16;                  \
+       ;;                                      \
+       mov     r16 = ar.k4;                    \
+       mov     r17 = ar.k5;                    \
+       ;;                                      \
+       st8     [r2] = r16,16;                  \
+       st8     [r3] = r17,16;                  \
+       ;;                                      \
+       mov     r16 = ar.k6;                    \
+       mov     r17 = ar.k7;                    \
+       ;;                                      \
+       st8     [r2] = r16;                     \
+       st8     [r3] = r17;                     \
+       ;;
+
+
+
+       /*
+        *      r33:            context_t base address
+        */
+#define        RESTORE_KERNEL_REGS                     \
+       add     r2 = CTX(KR0),r33;              \
+       add     r3 = CTX(KR1),r33;              \
+       ;;                                      \
+       ld8     r16=[r2],16;                    \
+       ld8     r17=[r3],16;                    \
+       ;;                                      \
+       mov     ar.k0=r16;                      \
+       mov     ar.k1=r17;                      \
+       ;;                                      \
+       ld8     r16=[r2],16;                    \
+       ld8     r17=[r3],16;                    \
+       ;;                                      \
+       mov     ar.k2=r16;                      \
+       mov     ar.k3=r17;                      \
+       ;;                                      \
+       ld8     r16=[r2],16;                    \
+       ld8     r17=[r3],16;                    \
+       ;;                                      \
+       mov     ar.k4=r16;                      \
+       mov     ar.k5=r17;                      \
+       ;;                                      \
+       ld8     r16=[r2],16;                    \
+       ld8     r17=[r3],16;                    \
+       ;;                                      \
+       mov     ar.k6=r16;                      \
+       mov     ar.k7=r17;                      \
+       ;;
+
+
+
+       /*
+        *      r32:            context_t base address
+        */
+#define        SAVE_APP_REGS                           \
+       add  r2 = CTX(BSPSTORE),r32;            \
+       mov  r16 = ar.bspstore;                 \
+       ;;                                      \
+       st8  [r2] = r16,CTX(RNAT)-CTX(BSPSTORE);\
+       mov  r16 = ar.rnat;                     \
+       ;;                                      \
+       st8  [r2] = r16,CTX(FCR)-CTX(RNAT);     \
+       mov  r16 = ar.fcr;                      \
+       ;;                                      \
+       st8  [r2] = r16,CTX(EFLAG)-CTX(FCR);    \
+       mov  r16 = ar.eflag;                    \
+       ;;                                      \
+       st8  [r2] = r16,CTX(CFLG)-CTX(EFLAG);   \
+       mov  r16 = ar.cflg;                     \
+       ;;                                      \
+       st8  [r2] = r16,CTX(FSR)-CTX(CFLG);     \
+       mov  r16 = ar.fsr;                      \
+       ;;                                      \
+       st8  [r2] = r16,CTX(FIR)-CTX(FSR);      \
+       mov  r16 = ar.fir;                      \
+       ;;                                      \
+       st8  [r2] = r16,CTX(FDR)-CTX(FIR);      \
+       mov  r16 = ar.fdr;                      \
+       ;;                                      \
+       st8  [r2] = r16,CTX(UNAT)-CTX(FDR);     \
+       mov  r16 = ar.unat;                     \
+       ;;                                      \
+       st8  [r2] = r16,CTX(FPSR)-CTX(UNAT);    \
+       mov  r16 = ar.fpsr;                     \
+       ;;                                      \
+       st8  [r2] = r16,CTX(PFS)-CTX(FPSR);     \
+       mov  r16 = ar.pfs;                      \
+       ;;                                      \
+       st8  [r2] = r16,CTX(LC)-CTX(PFS);       \
+       mov  r16 = ar.lc;                       \
+       ;;                                      \
+       st8  [r2] = r16;                        \
+       ;;
+
+       /*
+        *      r33:            context_t base address
+        */
+#define        RESTORE_APP_REGS                        \
+       add  r2=CTX(BSPSTORE),r33;              \
+       ;;                                      \
+       ld8  r16=[r2],CTX(RNAT)-CTX(BSPSTORE);  \
+       ;;                                      \
+       mov  ar.bspstore=r16;                   \
+       ld8  r16=[r2],CTX(FCR)-CTX(RNAT);       \
+       ;;                                      \
+       mov  ar.rnat=r16;                       \
+       ld8  r16=[r2],CTX(EFLAG)-CTX(FCR);      \
+       ;;                                      \
+       mov  ar.fcr=r16;                        \
+       ld8  r16=[r2],CTX(CFLG)-CTX(EFLAG);     \
+       ;;                                      \
+       mov  ar.eflag=r16;                      \
+       ld8  r16=[r2],CTX(FSR)-CTX(CFLG);       \
+       ;;                                      \
+       mov  ar.cflg=r16;                       \
+       ld8  r16=[r2],CTX(FIR)-CTX(FSR);        \
+       ;;                                      \
+       mov  ar.fsr=r16;                        \
+       ld8  r16=[r2],CTX(FDR)-CTX(FIR);        \
+       ;;                                      \
+       mov  ar.fir=r16;                        \
+       ld8  r16=[r2],CTX(UNAT)-CTX(FDR);       \
+       ;;                                      \
+       mov  ar.fdr=r16;                        \
+       ld8  r16=[r2],CTX(FPSR)-CTX(UNAT);      \
+       ;;                                      \
+       mov  ar.unat=r16;                       \
+       ld8  r16=[r2],CTX(PFS)-CTX(FPSR);       \
+       ;;                                      \
+       mov  ar.fpsr=r16;                       \
+       ld8  r16=[r2],CTX(LC)-CTX(PFS);         \
+       ;;                                      \
+       mov  ar.pfs=r16;                        \
+       ld8  r16=[r2];                          \
+       ;;                                      \
+       mov  ar.lc=r16;                         \
+       ;;
+
+       /*
+        *      r32:            context_t base address
+        */
+#define        SAVE_CTL_REGS                           \
+       add     r2 = CTX(DCR),r32;              \
+       mov     r16 = cr.dcr;                   \
+       ;;                                      \
+       st8     [r2] = r16,CTX(IVA)-CTX(DCR);   \
+       ;;                                      \
+       mov     r16 = cr.iva;                   \
+       ;;                                      \
+       st8     [r2] = r16,CTX(PTA)-CTX(IVA);   \
+       ;;                                      \
+       mov r16 = cr.pta;                       \
+       ;;                                      \
+       st8 [r2] = r16 ;                        \
+       ;;
+
+       /*
+        *      r33:            context_t base address
+        */
+#define        RESTORE_CTL_REGS                                \
+       add     r2 = CTX(DCR),r33;                      \
+       ;;                                              \
+       ld8     r16 = [r2],CTX(IVA)-CTX(DCR);           \
+       ;;                                              \
+       mov     cr.dcr = r16;                           \
+       dv_serialize_data;                              \
+       ;;                                              \
+       ld8     r16 = [r2],CTX(PTA)-CTX(IVA);           \
+       ;;                                              \
+       mov     cr.iva = r16;                           \
+       dv_serialize_data;                              \
+       ;;                                              \
+       ld8 r16 = [r2];                                 \
+       ;;                                              \
+       mov cr.pta = r16;                               \
+       dv_serialize_data;                              \
+       ;;
+
+
+       /*
+        *      r32:            context_t base address
+        */
+#define        SAVE_REGION_REGS                        \
+       add     r2=CTX(RR0),r32;                \
+       mov     r16=rr[r0];                     \
+       dep.z   r18=1,61,3;                     \
+       ;;                                      \
+       st8     [r2]=r16,8;                     \
+       mov     r17=rr[r18];                    \
+       dep.z   r18=2,61,3;                     \
+       ;;                                      \
+       st8     [r2]=r17,8;                     \
+       mov     r16=rr[r18];                    \
+       dep.z   r18=3,61,3;                     \
+       ;;                                      \
+       st8     [r2]=r16,8;                     \
+       mov     r17=rr[r18];                    \
+       dep.z   r18=4,61,3;                     \
+       ;;                                      \
+       st8     [r2]=r17,8;                     \
+       mov     r16=rr[r18];                    \
+       dep.z   r18=5,61,3;                     \
+       ;;                                      \
+       st8     [r2]=r16,8;                     \
+       mov     r17=rr[r18];                    \
+       dep.z   r18=7,61,3;                     \
+       ;;                                      \
+       st8     [r2]=r17,16;                    \
+       mov     r16=rr[r18];                    \
+       ;;                                      \
+       st8     [r2]=r16,8;                     \
+       ;;
+
+       /*
+        *      r33:context_t base address
+        */
+#define        RESTORE_REGION_REGS     \
+       add     r2=CTX(RR0),r33;\
+       mov r18=r0;             \
+       ;;                      \
+       ld8     r20=[r2],8;     \
+       ;;      /* rr0 */       \
+       ld8     r21=[r2],8;     \
+       ;;      /* rr1 */       \
+       ld8     r22=[r2],8;     \
+       ;;      /* rr2 */       \
+       ld8     r23=[r2],8;     \
+       ;;      /* rr3 */       \
+       ld8     r24=[r2],8;     \
+       ;;      /* rr4 */       \
+       ld8     r25=[r2],16;    \
+       ;;      /* rr5 */       \
+       ld8     r27=[r2];       \
+       ;;      /* rr7 */       \
+       mov rr[r18]=r20;        \
+       dep.z   r18=1,61,3;     \
+       ;;  /* rr1 */           \
+       mov rr[r18]=r21;        \
+       dep.z   r18=2,61,3;     \
+       ;;  /* rr2 */           \
+       mov rr[r18]=r22;        \
+       dep.z   r18=3,61,3;     \
+       ;;  /* rr3 */           \
+       mov rr[r18]=r23;        \
+       dep.z   r18=4,61,3;     \
+       ;;  /* rr4 */           \
+       mov rr[r18]=r24;        \
+       dep.z   r18=5,61,3;     \
+       ;;  /* rr5 */           \
+       mov rr[r18]=r25;        \
+       dep.z   r18=7,61,3;     \
+       ;;  /* rr7 */           \
+       mov rr[r18]=r27;        \
+       ;;                      \
+       srlz.i;                 \
+       ;;
+
+
+
+       /*
+        *      r32:    context_t base address
+        *      r36~r39:scratch registers
+        */
+#define        SAVE_DEBUG_REGS                         \
+       add     r2=CTX(IBR0),r32;               \
+       add     r3=CTX(DBR0),r32;               \
+       mov     r16=ibr[r0];                    \
+       mov     r17=dbr[r0];                    \
+       ;;                                      \
+       st8     [r2]=r16,8;                     \
+       st8     [r3]=r17,8;                     \
+       add     r18=1,r0;                       \
+       ;;                                      \
+       mov     r16=ibr[r18];                   \
+       mov     r17=dbr[r18];                   \
+       ;;                                      \
+       st8     [r2]=r16,8;                     \
+       st8     [r3]=r17,8;                     \
+       add     r18=2,r0;                       \
+       ;;                                      \
+       mov     r16=ibr[r18];                   \
+       mov     r17=dbr[r18];                   \
+       ;;                                      \
+       st8     [r2]=r16,8;                     \
+       st8     [r3]=r17,8;                     \
+       add     r18=2,r0;                       \
+       ;;                                      \
+       mov     r16=ibr[r18];                   \
+       mov     r17=dbr[r18];                   \
+       ;;                                      \
+       st8     [r2]=r16,8;                     \
+       st8     [r3]=r17,8;                     \
+       add     r18=3,r0;                       \
+       ;;                                      \
+       mov     r16=ibr[r18];                   \
+       mov     r17=dbr[r18];                   \
+       ;;                                      \
+       st8     [r2]=r16,8;                     \
+       st8     [r3]=r17,8;                     \
+       add     r18=4,r0;                       \
+       ;;                                      \
+       mov     r16=ibr[r18];                   \
+       mov     r17=dbr[r18];                   \
+       ;;                                      \
+       st8     [r2]=r16,8;                     \
+       st8     [r3]=r17,8;                     \
+       add     r18=5,r0;                       \
+       ;;                                      \
+       mov     r16=ibr[r18];                   \
+       mov     r17=dbr[r18];                   \
+       ;;                                      \
+       st8     [r2]=r16,8;                     \
+       st8     [r3]=r17,8;                     \
+       add     r18=6,r0;                       \
+       ;;                                      \
+       mov     r16=ibr[r18];                   \
+       mov     r17=dbr[r18];                   \
+       ;;                                      \
+       st8     [r2]=r16,8;                     \
+       st8     [r3]=r17,8;                     \
+       add     r18=7,r0;                       \
+       ;;                                      \
+       mov     r16=ibr[r18];                   \
+       mov     r17=dbr[r18];                   \
+       ;;                                      \
+       st8     [r2]=r16,8;                     \
+       st8     [r3]=r17,8;                     \
+       ;;
+
+
+/*
+ *      r33:    point to context_t structure
+ *      ar.lc are corrupted.
+ */
+#define RESTORE_DEBUG_REGS                     \
+       add     r2=CTX(IBR0),r33;               \
+       add     r3=CTX(DBR0),r33;               \
+       mov r16=7;                              \
+       mov r17=r0;                             \
+       ;;                                      \
+       mov ar.lc = r16;                        \
+       ;;                                      \
+1:                                             \
+       ld8 r18=[r2],8;                         \
+       ld8 r19=[r3],8;                         \
+       ;;                                      \
+       mov ibr[r17]=r18;                       \
+       mov dbr[r17]=r19;                       \
+       ;;                                      \
+       srlz.i;                                 \
+       ;;                                      \
+       add r17=1,r17;                          \
+       br.cloop.sptk 1b;                       \
+       ;;
+
+
+       /*
+        *      r32:            context_t base address
+        */
+#define        SAVE_FPU_LOW                            \
+       add     r2=CTX(F2),r32;                 \
+       add     r3=CTX(F3),r32;                 \
+       ;;                                      \
+       stf.spill.nta   [r2]=f2,32;             \
+       stf.spill.nta   [r3]=f3,32;             \
+       ;;                                      \
+       stf.spill.nta   [r2]=f4,32;             \
+       stf.spill.nta   [r3]=f5,32;             \
+       ;;                                      \
+       stf.spill.nta   [r2]=f6,32;             \
+       stf.spill.nta   [r3]=f7,32;             \
+       ;;                                      \
+       stf.spill.nta   [r2]=f8,32;             \
+       stf.spill.nta   [r3]=f9,32;             \
+       ;;                                      \
+       stf.spill.nta   [r2]=f10,32;            \
+       stf.spill.nta   [r3]=f11,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f12,32;            \
+       stf.spill.nta   [r3]=f13,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f14,32;            \
+       stf.spill.nta   [r3]=f15,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f16,32;            \
+       stf.spill.nta   [r3]=f17,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f18,32;            \
+       stf.spill.nta   [r3]=f19,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f20,32;            \
+       stf.spill.nta   [r3]=f21,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f22,32;            \
+       stf.spill.nta   [r3]=f23,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f24,32;            \
+       stf.spill.nta   [r3]=f25,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f26,32;            \
+       stf.spill.nta   [r3]=f27,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f28,32;            \
+       stf.spill.nta   [r3]=f29,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f30;               \
+       stf.spill.nta   [r3]=f31;               \
+       ;;
+
+       /*
+        *      r32:            context_t base address
+        */
+#define        SAVE_FPU_HIGH                           \
+       add     r2=CTX(F32),r32;                \
+       add     r3=CTX(F33),r32;                \
+       ;;                                      \
+       stf.spill.nta   [r2]=f32,32;            \
+       stf.spill.nta   [r3]=f33,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f34,32;            \
+       stf.spill.nta   [r3]=f35,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f36,32;            \
+       stf.spill.nta   [r3]=f37,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f38,32;            \
+       stf.spill.nta   [r3]=f39,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f40,32;            \
+       stf.spill.nta   [r3]=f41,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f42,32;            \
+       stf.spill.nta   [r3]=f43,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f44,32;            \
+       stf.spill.nta   [r3]=f45,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f46,32;            \
+       stf.spill.nta   [r3]=f47,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f48,32;            \
+       stf.spill.nta   [r3]=f49,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f50,32;            \
+       stf.spill.nta   [r3]=f51,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f52,32;            \
+       stf.spill.nta   [r3]=f53,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f54,32;            \
+       stf.spill.nta   [r3]=f55,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f56,32;            \
+       stf.spill.nta   [r3]=f57,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f58,32;            \
+       stf.spill.nta   [r3]=f59,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f60,32;            \
+       stf.spill.nta   [r3]=f61,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f62,32;            \
+       stf.spill.nta   [r3]=f63,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f64,32;            \
+       stf.spill.nta   [r3]=f65,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f66,32;            \
+       stf.spill.nta   [r3]=f67,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f68,32;            \
+       stf.spill.nta   [r3]=f69,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f70,32;            \
+       stf.spill.nta   [r3]=f71,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f72,32;            \
+       stf.spill.nta   [r3]=f73,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f74,32;            \
+       stf.spill.nta   [r3]=f75,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f76,32;            \
+       stf.spill.nta   [r3]=f77,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f78,32;            \
+       stf.spill.nta   [r3]=f79,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f80,32;            \
+       stf.spill.nta   [r3]=f81,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f82,32;            \
+       stf.spill.nta   [r3]=f83,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f84,32;            \
+       stf.spill.nta   [r3]=f85,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f86,32;            \
+       stf.spill.nta   [r3]=f87,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f88,32;            \
+       stf.spill.nta   [r3]=f89,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f90,32;            \
+       stf.spill.nta   [r3]=f91,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f92,32;            \
+       stf.spill.nta   [r3]=f93,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f94,32;            \
+       stf.spill.nta   [r3]=f95,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f96,32;            \
+       stf.spill.nta   [r3]=f97,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f98,32;            \
+       stf.spill.nta   [r3]=f99,32;            \
+       ;;                                      \
+       stf.spill.nta   [r2]=f100,32;           \
+       stf.spill.nta   [r3]=f101,32;           \
+       ;;                                      \
+       stf.spill.nta   [r2]=f102,32;           \
+       stf.spill.nta   [r3]=f103,32;           \
+       ;;                                      \
+       stf.spill.nta   [r2]=f104,32;           \
+       stf.spill.nta   [r3]=f105,32;           \
+       ;;                                      \
+       stf.spill.nta   [r2]=f106,32;           \
+       stf.spill.nta   [r3]=f107,32;           \
+       ;;                                      \
+       stf.spill.nta   [r2]=f108,32;           \
+       stf.spill.nta   [r3]=f109,32;           \
+       ;;                                      \
+       stf.spill.nta   [r2]=f110,32;           \
+       stf.spill.nta   [r3]=f111,32;           \
+       ;;                                      \
+       stf.spill.nta   [r2]=f112,32;           \
+       stf.spill.nta   [r3]=f113,32;           \
+       ;;                                      \
+       stf.spill.nta   [r2]=f114,32;           \
+       stf.spill.nta   [r3]=f115,32;           \
+       ;;                                      \
+       stf.spill.nta   [r2]=f116,32;           \
+       stf.spill.nta   [r3]=f117,32;           \
+       ;;                                      \
+       stf.spill.nta   [r2]=f118,32;           \
+       stf.spill.nta   [r3]=f119,32;           \
+       ;;                                      \
+       stf.spill.nta   [r2]=f120,32;           \
+       stf.spill.nta   [r3]=f121,32;           \
+       ;;                                      \
+       stf.spill.nta   [r2]=f122,32;           \
+       stf.spill.nta   [r3]=f123,32;           \
+       ;;                                      \
+       stf.spill.nta   [r2]=f124,32;           \
+       stf.spill.nta   [r3]=f125,32;           \
+       ;;                                      \
+       stf.spill.nta   [r2]=f126;              \
+       stf.spill.nta   [r3]=f127;              \
+       ;;
+
+     /*
+      *      r33:    point to context_t structure
+      */
+#define        RESTORE_FPU_LOW                         \
+    add     r2 = CTX(F2), r33;                 \
+    add     r3 = CTX(F3), r33;                 \
+    ;;                                         \
+    ldf.fill.nta f2 = [r2], 32;                        \
+    ldf.fill.nta f3 = [r3], 32;                        \
+    ;;                                         \
+    ldf.fill.nta f4 = [r2], 32;                        \
+    ldf.fill.nta f5 = [r3], 32;                        \
+    ;;                                         \
+    ldf.fill.nta f6 = [r2], 32;                        \
+    ldf.fill.nta f7 = [r3], 32;                        \
+    ;;                                         \
+    ldf.fill.nta f8 = [r2], 32;                        \
+    ldf.fill.nta f9 = [r3], 32;                        \
+    ;;                                         \
+    ldf.fill.nta f10 = [r2], 32;               \
+    ldf.fill.nta f11 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f12 = [r2], 32;               \
+    ldf.fill.nta f13 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f14 = [r2], 32;               \
+    ldf.fill.nta f15 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f16 = [r2], 32;               \
+    ldf.fill.nta f17 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f18 = [r2], 32;               \
+    ldf.fill.nta f19 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f20 = [r2], 32;               \
+    ldf.fill.nta f21 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f22 = [r2], 32;               \
+    ldf.fill.nta f23 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f24 = [r2], 32;               \
+    ldf.fill.nta f25 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f26 = [r2], 32;               \
+    ldf.fill.nta f27 = [r3], 32;               \
+       ;;                                      \
+    ldf.fill.nta f28 = [r2], 32;               \
+    ldf.fill.nta f29 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f30 = [r2], 32;               \
+    ldf.fill.nta f31 = [r3], 32;               \
+    ;;
+
+
+
+    /*
+     *      r33:    point to context_t structure
+     */
+#define        RESTORE_FPU_HIGH                        \
+    add     r2 = CTX(F32), r33;                        \
+    add     r3 = CTX(F33), r33;                        \
+    ;;                                         \
+    ldf.fill.nta f32 = [r2], 32;               \
+    ldf.fill.nta f33 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f34 = [r2], 32;               \
+    ldf.fill.nta f35 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f36 = [r2], 32;               \
+    ldf.fill.nta f37 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f38 = [r2], 32;               \
+    ldf.fill.nta f39 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f40 = [r2], 32;               \
+    ldf.fill.nta f41 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f42 = [r2], 32;               \
+    ldf.fill.nta f43 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f44 = [r2], 32;               \
+    ldf.fill.nta f45 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f46 = [r2], 32;               \
+    ldf.fill.nta f47 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f48 = [r2], 32;               \
+    ldf.fill.nta f49 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f50 = [r2], 32;               \
+    ldf.fill.nta f51 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f52 = [r2], 32;               \
+    ldf.fill.nta f53 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f54 = [r2], 32;               \
+    ldf.fill.nta f55 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f56 = [r2], 32;               \
+    ldf.fill.nta f57 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f58 = [r2], 32;               \
+    ldf.fill.nta f59 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f60 = [r2], 32;               \
+    ldf.fill.nta f61 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f62 = [r2], 32;               \
+    ldf.fill.nta f63 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f64 = [r2], 32;               \
+    ldf.fill.nta f65 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f66 = [r2], 32;               \
+    ldf.fill.nta f67 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f68 = [r2], 32;               \
+    ldf.fill.nta f69 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f70 = [r2], 32;               \
+    ldf.fill.nta f71 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f72 = [r2], 32;               \
+    ldf.fill.nta f73 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f74 = [r2], 32;               \
+    ldf.fill.nta f75 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f76 = [r2], 32;               \
+    ldf.fill.nta f77 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f78 = [r2], 32;               \
+    ldf.fill.nta f79 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f80 = [r2], 32;               \
+    ldf.fill.nta f81 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f82 = [r2], 32;               \
+    ldf.fill.nta f83 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f84 = [r2], 32;               \
+    ldf.fill.nta f85 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f86 = [r2], 32;               \
+    ldf.fill.nta f87 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f88 = [r2], 32;               \
+    ldf.fill.nta f89 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f90 = [r2], 32;               \
+    ldf.fill.nta f91 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f92 = [r2], 32;               \
+    ldf.fill.nta f93 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f94 = [r2], 32;               \
+    ldf.fill.nta f95 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f96 = [r2], 32;               \
+    ldf.fill.nta f97 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f98 = [r2], 32;               \
+    ldf.fill.nta f99 = [r3], 32;               \
+    ;;                                         \
+    ldf.fill.nta f100 = [r2], 32;              \
+    ldf.fill.nta f101 = [r3], 32;              \
+    ;;                                         \
+    ldf.fill.nta f102 = [r2], 32;              \
+    ldf.fill.nta f103 = [r3], 32;              \
+    ;;                                         \
+    ldf.fill.nta f104 = [r2], 32;              \
+    ldf.fill.nta f105 = [r3], 32;              \
+    ;;                                         \
+    ldf.fill.nta f106 = [r2], 32;              \
+    ldf.fill.nta f107 = [r3], 32;              \
+    ;;                                         \
+    ldf.fill.nta f108 = [r2], 32;              \
+    ldf.fill.nta f109 = [r3], 32;              \
+    ;;                                         \
+    ldf.fill.nta f110 = [r2], 32;              \
+    ldf.fill.nta f111 = [r3], 32;              \
+    ;;                                         \
+    ldf.fill.nta f112 = [r2], 32;              \
+    ldf.fill.nta f113 = [r3], 32;              \
+    ;;                                         \
+    ldf.fill.nta f114 = [r2], 32;              \
+    ldf.fill.nta f115 = [r3], 32;              \
+    ;;                                         \
+    ldf.fill.nta f116 = [r2], 32;              \
+    ldf.fill.nta f117 = [r3], 32;              \
+    ;;                                         \
+    ldf.fill.nta f118 = [r2], 32;              \
+    ldf.fill.nta f119 = [r3], 32;              \
+    ;;                                         \
+    ldf.fill.nta f120 = [r2], 32;              \
+    ldf.fill.nta f121 = [r3], 32;              \
+    ;;                                         \
+    ldf.fill.nta f122 = [r2], 32;              \
+    ldf.fill.nta f123 = [r3], 32;              \
+    ;;                                         \
+    ldf.fill.nta f124 = [r2], 32;              \
+    ldf.fill.nta f125 = [r3], 32;              \
+    ;;                                         \
+    ldf.fill.nta f126 = [r2], 32;              \
+    ldf.fill.nta f127 = [r3], 32;              \
+    ;;
+
+       /*
+        *      r32:            context_t base address
+        */
+#define        SAVE_PTK_REGS                           \
+    add r2=CTX(PKR0), r32;                     \
+    mov r16=7;                                 \
+    ;;                                                 \
+    mov ar.lc=r16;                             \
+    mov r17=r0;                                        \
+    ;;                                         \
+1:                                             \
+    mov r18=pkr[r17];                          \
+    ;;                                         \
+    srlz.i;                                    \
+    ;;                                                 \
+    st8 [r2]=r18, 8;                           \
+    ;;                                         \
+    add r17 =1,r17;                            \
+    ;;                                         \
+    br.cloop.sptk 1b;                          \
+    ;;
+
+/*
+ *      r33:    point to context_t structure
+ *      ar.lc are corrupted.
+ */
+#define RESTORE_PTK_REGS                       \
+    add r2=CTX(PKR0), r33;                     \
+    mov r16=7;                                 \
+    ;;                                                 \
+    mov ar.lc=r16;                             \
+    mov r17=r0;                                        \
+    ;;                                         \
+1:                                             \
+    ld8 r18=[r2], 8;                           \
+    ;;                                         \
+    mov pkr[r17]=r18;                          \
+    ;;                                         \
+    srlz.i;                                    \
+    ;;                                                 \
+    add r17 =1,r17;                            \
+    ;;                                         \
+    br.cloop.sptk 1b;                          \
+    ;;
+
+
+/*
+ * void vmm_trampoline( context_t * from,
+ *                     context_t * to)
+ *
+ *     from:   r32
+ *     to:     r33
+ *  note: interrupt disabled before call this function.
+ */
+GLOBAL_ENTRY(vmm_trampoline)
+    mov r16 = psr
+    adds r2 = CTX(PSR), r32
+    ;;
+    st8 [r2] = r16, 8       // psr
+    mov r17 = pr
+    ;;
+    st8 [r2] = r17, 8       // pr
+    mov r18 = ar.unat
+    ;;
+    st8 [r2] = r18
+    mov r17 = ar.rsc
+    ;;
+    adds r2 = CTX(RSC),r32
+    ;;
+    st8 [r2]= r17
+    mov ar.rsc =0
+    flushrs
+    ;;
+    SAVE_GENERAL_REGS
+    ;;
+    SAVE_KERNEL_REGS
+    ;;
+    SAVE_APP_REGS
+    ;;
+    SAVE_BRANCH_REGS
+    ;;
+    SAVE_CTL_REGS
+    ;;
+    SAVE_REGION_REGS
+    ;;
+    //SAVE_DEBUG_REGS
+    ;;
+    rsm  psr.dfl
+    ;;
+    srlz.d
+    ;;
+    SAVE_FPU_LOW
+    ;;
+    rsm  psr.dfh
+    ;;
+    srlz.d
+    ;;
+    SAVE_FPU_HIGH
+    ;;
+    SAVE_PTK_REGS
+    ;;
+    RESTORE_PTK_REGS
+    ;;
+    RESTORE_FPU_HIGH
+    ;;
+    RESTORE_FPU_LOW
+    ;;
+    //RESTORE_DEBUG_REGS
+    ;;
+    RESTORE_REGION_REGS
+    ;;
+    RESTORE_CTL_REGS
+    ;;
+    RESTORE_BRANCH_REGS
+    ;;
+    RESTORE_APP_REGS
+    ;;
+    RESTORE_KERNEL_REGS
+    ;;
+    RESTORE_GENERAL_REGS
+    ;;
+    adds r2=CTX(PSR), r33
+    ;;
+    ld8 r16=[r2], 8       // psr
+    ;;
+    mov psr.l=r16
+    ;;
+    srlz.d
+    ;;
+    ld8 r16=[r2], 8       // pr
+    ;;
+    mov pr =r16,-1
+    ld8 r16=[r2]       // unat
+    ;;
+    mov ar.unat=r16
+    ;;
+    adds r2=CTX(RSC),r33
+    ;;
+    ld8 r16 =[r2]
+    ;;
+    mov ar.rsc = r16
+    ;;
+    br.ret.sptk.few b0
+END(vmm_trampoline)
diff --git a/arch/ia64/kvm/vcpu.c b/arch/ia64/kvm/vcpu.c
new file mode 100644 (file)
index 0000000..e44027c
--- /dev/null
@@ -0,0 +1,2163 @@
+/*
+ * kvm_vcpu.c: handling all virtual cpu related thing.
+ * Copyright (c) 2005, 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., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ *  Shaofan Li (Susue Li) <susie.li@intel.com>
+ *  Yaozu Dong (Eddie Dong) (Eddie.dong@intel.com)
+ *  Xuefei Xu (Anthony Xu) (Anthony.xu@intel.com)
+ *  Xiantao Zhang <xiantao.zhang@intel.com>
+ */
+
+#include <linux/kvm_host.h>
+#include <linux/types.h>
+
+#include <asm/processor.h>
+#include <asm/ia64regs.h>
+#include <asm/gcc_intrin.h>
+#include <asm/kregs.h>
+#include <asm/pgtable.h>
+#include <asm/tlb.h>
+
+#include "asm-offsets.h"
+#include "vcpu.h"
+
+/*
+ * Special notes:
+ * - Index by it/dt/rt sequence
+ * - Only existing mode transitions are allowed in this table
+ * - RSE is placed at lazy mode when emulating guest partial mode
+ * - If gva happens to be rr0 and rr4, only allowed case is identity
+ *   mapping (gva=gpa), or panic! (How?)
+ */
+int mm_switch_table[8][8] = {
+       /*  2004/09/12(Kevin): Allow switch to self */
+       /*
+        *  (it,dt,rt): (0,0,0) -> (1,1,1)
+        *  This kind of transition usually occurs in the very early
+        *  stage of Linux boot up procedure. Another case is in efi
+        *  and pal calls. (see "arch/ia64/kernel/head.S")
+        *
+        *  (it,dt,rt): (0,0,0) -> (0,1,1)
+        *  This kind of transition is found when OSYa exits efi boot
+        *  service. Due to gva = gpa in this case (Same region),
+        *  data access can be satisfied though itlb entry for physical
+        *  emulation is hit.
+        */
+       {SW_SELF, 0,  0,  SW_NOP, 0,  0,  0,  SW_P2V},
+       {0,  0,  0,  0,  0,  0,  0,  0},
+       {0,  0,  0,  0,  0,  0,  0,  0},
+       /*
+        *  (it,dt,rt): (0,1,1) -> (1,1,1)
+        *  This kind of transition is found in OSYa.
+        *
+        *  (it,dt,rt): (0,1,1) -> (0,0,0)
+        *  This kind of transition is found in OSYa
+        */
+       {SW_NOP, 0,  0,  SW_SELF, 0,  0,  0,  SW_P2V},
+       /* (1,0,0)->(1,1,1) */
+       {0,  0,  0,  0,  0,  0,  0,  SW_P2V},
+       /*
+        *  (it,dt,rt): (1,0,1) -> (1,1,1)
+        *  This kind of transition usually occurs when Linux returns
+        *  from the low level TLB miss handlers.
+        *  (see "arch/ia64/kernel/ivt.S")
+        */
+       {0,  0,  0,  0,  0,  SW_SELF, 0,  SW_P2V},
+       {0,  0,  0,  0,  0,  0,  0,  0},
+       /*
+        *  (it,dt,rt): (1,1,1) -> (1,0,1)
+        *  This kind of transition usually occurs in Linux low level
+        *  TLB miss handler. (see "arch/ia64/kernel/ivt.S")
+        *
+        *  (it,dt,rt): (1,1,1) -> (0,0,0)
+        *  This kind of transition usually occurs in pal and efi calls,
+        *  which requires running in physical mode.
+        *  (see "arch/ia64/kernel/head.S")
+        *  (1,1,1)->(1,0,0)
+        */
+
+       {SW_V2P, 0,  0,  0,  SW_V2P, SW_V2P, 0,  SW_SELF},
+};
+
+void physical_mode_init(struct kvm_vcpu  *vcpu)
+{
+       vcpu->arch.mode_flags = GUEST_IN_PHY;
+}
+
+void switch_to_physical_rid(struct kvm_vcpu *vcpu)
+{
+       unsigned long psr;
+
+       /* Save original virtual mode rr[0] and rr[4] */
+       psr = ia64_clear_ic();
+       ia64_set_rr(VRN0<<VRN_SHIFT, vcpu->arch.metaphysical_rr0);
+       ia64_srlz_d();
+       ia64_set_rr(VRN4<<VRN_SHIFT, vcpu->arch.metaphysical_rr4);
+       ia64_srlz_d();
+
+       ia64_set_psr(psr);
+       return;
+}
+
+
+void switch_to_virtual_rid(struct kvm_vcpu *vcpu)
+{
+       unsigned long psr;
+
+       psr = ia64_clear_ic();
+       ia64_set_rr(VRN0 << VRN_SHIFT, vcpu->arch.metaphysical_saved_rr0);
+       ia64_srlz_d();
+       ia64_set_rr(VRN4 << VRN_SHIFT, vcpu->arch.metaphysical_saved_rr4);
+       ia64_srlz_d();
+       ia64_set_psr(psr);
+       return;
+}
+
+static int mm_switch_action(struct ia64_psr opsr, struct ia64_psr npsr)
+{
+       return mm_switch_table[MODE_IND(opsr)][MODE_IND(npsr)];
+}
+
+void switch_mm_mode(struct kvm_vcpu *vcpu, struct ia64_psr old_psr,
+                                       struct ia64_psr new_psr)
+{
+       int act;
+       act = mm_switch_action(old_psr, new_psr);
+       switch (act) {
+       case SW_V2P:
+               /*printk("V -> P mode transition: (0x%lx -> 0x%lx)\n",
+               old_psr.val, new_psr.val);*/
+               switch_to_physical_rid(vcpu);
+               /*
+                * Set rse to enforced lazy, to prevent active rse
+                *save/restor when guest physical mode.
+                */
+               vcpu->arch.mode_flags |= GUEST_IN_PHY;
+               break;
+       case SW_P2V:
+               switch_to_virtual_rid(vcpu);
+               /*
+                * recover old mode which is saved when entering
+                * guest physical mode
+                */
+               vcpu->arch.mode_flags &= ~GUEST_IN_PHY;
+               break;
+       case SW_SELF:
+               break;
+       case SW_NOP:
+               break;
+       default:
+               /* Sanity check */
+               break;
+       }
+       return;
+}
+
+
+
+/*
+ * In physical mode, insert tc/tr for region 0 and 4 uses
+ * RID[0] and RID[4] which is for physical mode emulation.
+ * However what those inserted tc/tr wants is rid for
+ * virtual mode. So original virtual rid needs to be restored
+ * before insert.
+ *
+ * Operations which required such switch include:
+ *  - insertions (itc.*, itr.*)
+ *  - purges (ptc.* and ptr.*)
+ *  - tpa
+ *  - tak
+ *  - thash?, ttag?
+ * All above needs actual virtual rid for destination entry.
+ */
+
+void check_mm_mode_switch(struct kvm_vcpu *vcpu,  struct ia64_psr old_psr,
+                                       struct ia64_psr new_psr)
+{
+
+       if ((old_psr.dt != new_psr.dt)
+                       || (old_psr.it != new_psr.it)
+                       || (old_psr.rt != new_psr.rt))
+               switch_mm_mode(vcpu, old_psr, new_psr);
+
+       return;
+}
+
+
+/*
+ * In physical mode, insert tc/tr for region 0 and 4 uses
+ * RID[0] and RID[4] which is for physical mode emulation.
+ * However what those inserted tc/tr wants is rid for
+ * virtual mode. So original virtual rid needs to be restored
+ * before insert.
+ *
+ * Operations which required such switch include:
+ *  - insertions (itc.*, itr.*)
+ *  - purges (ptc.* and ptr.*)
+ *  - tpa
+ *  - tak
+ *  - thash?, ttag?
+ * All above needs actual virtual rid for destination entry.
+ */
+
+void prepare_if_physical_mode(struct kvm_vcpu *vcpu)
+{
+       if (is_physical_mode(vcpu)) {
+               vcpu->arch.mode_flags |= GUEST_PHY_EMUL;
+               switch_to_virtual_rid(vcpu);
+       }
+       return;
+}
+
+/* Recover always follows prepare */
+void recover_if_physical_mode(struct kvm_vcpu *vcpu)
+{
+       if (is_physical_mode(vcpu))
+               switch_to_physical_rid(vcpu);
+       vcpu->arch.mode_flags &= ~GUEST_PHY_EMUL;
+       return;
+}
+
+#define RPT(x) ((u16) &((struct kvm_pt_regs *)0)->x)
+
+static u16 gr_info[32] = {
+       0,      /* r0 is read-only : WE SHOULD NEVER GET THIS */
+       RPT(r1), RPT(r2), RPT(r3),
+       RPT(r4), RPT(r5), RPT(r6), RPT(r7),
+       RPT(r8), RPT(r9), RPT(r10), RPT(r11),
+       RPT(r12), RPT(r13), RPT(r14), RPT(r15),
+       RPT(r16), RPT(r17), RPT(r18), RPT(r19),
+       RPT(r20), RPT(r21), RPT(r22), RPT(r23),
+       RPT(r24), RPT(r25), RPT(r26), RPT(r27),
+       RPT(r28), RPT(r29), RPT(r30), RPT(r31)
+};
+
+#define IA64_FIRST_STACKED_GR   32
+#define IA64_FIRST_ROTATING_FR  32
+
+static inline unsigned long
+rotate_reg(unsigned long sor, unsigned long rrb, unsigned long reg)
+{
+       reg += rrb;
+       if (reg >= sor)
+               reg -= sor;
+       return reg;
+}
+
+/*
+ * Return the (rotated) index for floating point register
+ * be in the REGNUM (REGNUM must range from 32-127,
+ * result is in the range from 0-95.
+ */
+static inline unsigned long fph_index(struct kvm_pt_regs *regs,
+                                               long regnum)
+{
+       unsigned long rrb_fr = (regs->cr_ifs >> 25) & 0x7f;
+       return rotate_reg(96, rrb_fr, (regnum - IA64_FIRST_ROTATING_FR));
+}
+
+
+/*
+ * The inverse of the above: given bspstore and the number of
+ * registers, calculate ar.bsp.
+ */
+static inline unsigned long *kvm_rse_skip_regs(unsigned long *addr,
+                                                       long num_regs)
+{
+       long delta = ia64_rse_slot_num(addr) + num_regs;
+       int i = 0;
+
+       if (num_regs < 0)
+               delta -= 0x3e;
+       if (delta < 0) {
+               while (delta <= -0x3f) {
+                       i--;
+                       delta += 0x3f;
+               }
+       } else {
+               while (delta >= 0x3f) {
+                       i++;
+                       delta -= 0x3f;
+               }
+       }
+
+       return addr + num_regs + i;
+}
+
+static void get_rse_reg(struct kvm_pt_regs *regs, unsigned long r1,
+                                       unsigned long *val, int *nat)
+{
+       unsigned long *bsp, *addr, *rnat_addr, *bspstore;
+       unsigned long *kbs = (void *) current_vcpu + VMM_RBS_OFFSET;
+       unsigned long nat_mask;
+       unsigned long old_rsc, new_rsc;
+       long sof = (regs->cr_ifs) & 0x7f;
+       long sor = (((regs->cr_ifs >> 14) & 0xf) << 3);
+       long rrb_gr = (regs->cr_ifs >> 18) & 0x7f;
+       long ridx = r1 - 32;
+
+       if (ridx < sor)
+               ridx = rotate_reg(sor, rrb_gr, ridx);
+
+       old_rsc = ia64_getreg(_IA64_REG_AR_RSC);
+       new_rsc = old_rsc&(~(0x3));
+       ia64_setreg(_IA64_REG_AR_RSC, new_rsc);
+
+       bspstore = (unsigned long *)ia64_getreg(_IA64_REG_AR_BSPSTORE);
+       bsp = kbs + (regs->loadrs >> 19);
+
+       addr = kvm_rse_skip_regs(bsp, -sof + ridx);
+       nat_mask = 1UL << ia64_rse_slot_num(addr);
+       rnat_addr = ia64_rse_rnat_addr(addr);
+
+       if (addr >= bspstore) {
+               ia64_flushrs();
+               ia64_mf();
+               bspstore = (unsigned long *)ia64_getreg(_IA64_REG_AR_BSPSTORE);
+       }
+       *val = *addr;
+       if (nat) {
+               if (bspstore < rnat_addr)
+                       *nat = (int)!!(ia64_getreg(_IA64_REG_AR_RNAT)
+                                                       & nat_mask);
+               else
+                       *nat = (int)!!((*rnat_addr) & nat_mask);
+               ia64_setreg(_IA64_REG_AR_RSC, old_rsc);
+       }
+}
+
+void set_rse_reg(struct kvm_pt_regs *regs, unsigned long r1,
+                               unsigned long val, unsigned long nat)
+{
+       unsigned long *bsp, *bspstore, *addr, *rnat_addr;
+       unsigned long *kbs = (void *) current_vcpu + VMM_RBS_OFFSET;
+       unsigned long nat_mask;
+       unsigned long old_rsc, new_rsc, psr;
+       unsigned long rnat;
+       long sof = (regs->cr_ifs) & 0x7f;
+       long sor = (((regs->cr_ifs >> 14) & 0xf) << 3);
+       long rrb_gr = (regs->cr_ifs >> 18) & 0x7f;
+       long ridx = r1 - 32;
+
+       if (ridx < sor)
+               ridx = rotate_reg(sor, rrb_gr, ridx);
+
+       old_rsc = ia64_getreg(_IA64_REG_AR_RSC);
+       /* put RSC to lazy mode, and set loadrs 0 */
+       new_rsc = old_rsc & (~0x3fff0003);
+       ia64_setreg(_IA64_REG_AR_RSC, new_rsc);
+       bsp = kbs + (regs->loadrs >> 19); /* 16 + 3 */
+
+       addr = kvm_rse_skip_regs(bsp, -sof + ridx);
+       nat_mask = 1UL << ia64_rse_slot_num(addr);
+       rnat_addr = ia64_rse_rnat_addr(addr);
+
+       local_irq_save(psr);
+       bspstore = (unsigned long *)ia64_getreg(_IA64_REG_AR_BSPSTORE);
+       if (addr >= bspstore) {
+
+               ia64_flushrs();
+               ia64_mf();
+               *addr = val;
+               bspstore = (unsigned long *)ia64_getreg(_IA64_REG_AR_BSPSTORE);
+               rnat = ia64_getreg(_IA64_REG_AR_RNAT);
+               if (bspstore < rnat_addr)
+                       rnat = rnat & (~nat_mask);
+               else
+                       *rnat_addr = (*rnat_addr)&(~nat_mask);
+
+               ia64_mf();
+               ia64_loadrs();
+               ia64_setreg(_IA64_REG_AR_RNAT, rnat);
+       } else {
+               rnat = ia64_getreg(_IA64_REG_AR_RNAT);
+               *addr = val;
+               if (bspstore < rnat_addr)
+                       rnat = rnat&(~nat_mask);
+               else
+                       *rnat_addr = (*rnat_addr) & (~nat_mask);
+
+               ia64_setreg(_IA64_REG_AR_BSPSTORE, bspstore);
+               ia64_setreg(_IA64_REG_AR_RNAT, rnat);
+       }
+       local_irq_restore(psr);
+       ia64_setreg(_IA64_REG_AR_RSC, old_rsc);
+}
+
+void getreg(unsigned long regnum, unsigned long *val,
+                               int *nat, struct kvm_pt_regs *regs)
+{
+       unsigned long addr, *unat;
+       if (regnum >= IA64_FIRST_STACKED_GR) {
+               get_rse_reg(regs, regnum, val, nat);
+               return;
+       }
+
+       /*
+        * Now look at registers in [0-31] range and init correct UNAT
+        */
+       addr = (unsigned long)regs;
+       unat = &regs->eml_unat;;
+
+       addr += gr_info[regnum];
+
+       *val  = *(unsigned long *)addr;
+       /*
+        * do it only when requested
+        */
+       if (nat)
+               *nat  = (*unat >> ((addr >> 3) & 0x3f)) & 0x1UL;
+}
+
+void setreg(unsigned long regnum, unsigned long val,
+                       int nat, struct kvm_pt_regs *regs)
+{
+       unsigned long addr;
+       unsigned long bitmask;
+       unsigned long *unat;
+
+       /*
+        * First takes care of stacked registers
+        */
+       if (regnum >= IA64_FIRST_STACKED_GR) {
+               set_rse_reg(regs, regnum, val, nat);
+               return;
+       }
+
+       /*
+        * Now look at registers in [0-31] range and init correct UNAT
+        */
+       addr = (unsigned long)regs;
+       unat = &regs->eml_unat;
+       /*
+        * add offset from base of struct
+        * and do it !
+        */
+       addr += gr_info[regnum];
+
+       *(unsigned long *)addr = val;
+
+       /*
+        * We need to clear the corresponding UNAT bit to fully emulate the load
+        * UNAT bit_pos = GR[r3]{8:3} form EAS-2.4
+        */
+       bitmask   = 1UL << ((addr >> 3) & 0x3f);
+       if (nat)
+               *unat |= bitmask;
+        else
+               *unat &= ~bitmask;
+
+}
+
+u64 vcpu_get_gr(struct kvm_vcpu *vcpu, unsigned long reg)
+{
+       struct kvm_pt_regs *regs = vcpu_regs(vcpu);
+       u64 val;
+
+       if (!reg)
+               return 0;
+       getreg(reg, &val, 0, regs);
+       return val;
+}
+
+void vcpu_set_gr(struct kvm_vcpu *vcpu, u64 reg, u64 value, int nat)
+{
+       struct kvm_pt_regs *regs = vcpu_regs(vcpu);
+       long sof = (regs->cr_ifs) & 0x7f;
+
+       if (!reg)
+               return;
+       if (reg >= sof + 32)
+               return;
+       setreg(reg, value, nat, regs);  /* FIXME: handle NATs later*/
+}
+
+void getfpreg(unsigned long regnum, struct ia64_fpreg *fpval,
+                               struct kvm_pt_regs *regs)
+{
+       /* Take floating register rotation into consideration*/
+       if (regnum >= IA64_FIRST_ROTATING_FR)
+               regnum = IA64_FIRST_ROTATING_FR + fph_index(regs, regnum);
+#define CASE_FIXED_FP(reg)                     \
+       case  (reg) :                           \
+               ia64_stf_spill(fpval, reg);     \
+       break
+
+       switch (regnum) {
+               CASE_FIXED_FP(0);
+               CASE_FIXED_FP(1);
+               CASE_FIXED_FP(2);
+               CASE_FIXED_FP(3);
+               CASE_FIXED_FP(4);
+               CASE_FIXED_FP(5);
+
+               CASE_FIXED_FP(6);
+               CASE_FIXED_FP(7);
+               CASE_FIXED_FP(8);
+               CASE_FIXED_FP(9);
+               CASE_FIXED_FP(10);
+               CASE_FIXED_FP(11);
+
+               CASE_FIXED_FP(12);
+               CASE_FIXED_FP(13);
+               CASE_FIXED_FP(14);
+               CASE_FIXED_FP(15);
+               CASE_FIXED_FP(16);
+               CASE_FIXED_FP(17);
+               CASE_FIXED_FP(18);
+               CASE_FIXED_FP(19);
+               CASE_FIXED_FP(20);
+               CASE_FIXED_FP(21);
+               CASE_FIXED_FP(22);
+               CASE_FIXED_FP(23);
+               CASE_FIXED_FP(24);
+               CASE_FIXED_FP(25);
+               CASE_FIXED_FP(26);
+               CASE_FIXED_FP(27);
+               CASE_FIXED_FP(28);
+               CASE_FIXED_FP(29);
+               CASE_FIXED_FP(30);
+               CASE_FIXED_FP(31);
+               CASE_FIXED_FP(32);
+               CASE_FIXED_FP(33);
+               CASE_FIXED_FP(34);
+               CASE_FIXED_FP(35);
+               CASE_FIXED_FP(36);
+               CASE_FIXED_FP(37);
+               CASE_FIXED_FP(38);
+               CASE_FIXED_FP(39);
+               CASE_FIXED_FP(40);
+               CASE_FIXED_FP(41);
+               CASE_FIXED_FP(42);
+               CASE_FIXED_FP(43);
+               CASE_FIXED_FP(44);
+               CASE_FIXED_FP(45);
+               CASE_FIXED_FP(46);
+               CASE_FIXED_FP(47);
+               CASE_FIXED_FP(48);
+               CASE_FIXED_FP(49);
+               CASE_FIXED_FP(50);
+               CASE_FIXED_FP(51);
+               CASE_FIXED_FP(52);
+               CASE_FIXED_FP(53);
+               CASE_FIXED_FP(54);
+               CASE_FIXED_FP(55);
+               CASE_FIXED_FP(56);
+               CASE_FIXED_FP(57);
+               CASE_FIXED_FP(58);
+               CASE_FIXED_FP(59);
+               CASE_FIXED_FP(60);
+               CASE_FIXED_FP(61);
+               CASE_FIXED_FP(62);
+               CASE_FIXED_FP(63);
+               CASE_FIXED_FP(64);
+               CASE_FIXED_FP(65);
+               CASE_FIXED_FP(66);
+               CASE_FIXED_FP(67);
+               CASE_FIXED_FP(68);
+               CASE_FIXED_FP(69);
+               CASE_FIXED_FP(70);
+               CASE_FIXED_FP(71);
+               CASE_FIXED_FP(72);
+               CASE_FIXED_FP(73);
+               CASE_FIXED_FP(74);
+               CASE_FIXED_FP(75);
+               CASE_FIXED_FP(76);
+               CASE_FIXED_FP(77);
+               CASE_FIXED_FP(78);
+               CASE_FIXED_FP(79);
+               CASE_FIXED_FP(80);
+               CASE_FIXED_FP(81);
+               CASE_FIXED_FP(82);
+               CASE_FIXED_FP(83);
+               CASE_FIXED_FP(84);
+               CASE_FIXED_FP(85);
+               CASE_FIXED_FP(86);
+               CASE_FIXED_FP(87);
+               CASE_FIXED_FP(88);
+               CASE_FIXED_FP(89);
+               CASE_FIXED_FP(90);
+               CASE_FIXED_FP(91);
+               CASE_FIXED_FP(92);
+               CASE_FIXED_FP(93);
+               CASE_FIXED_FP(94);
+               CASE_FIXED_FP(95);
+               CASE_FIXED_FP(96);
+               CASE_FIXED_FP(97);
+               CASE_FIXED_FP(98);
+               CASE_FIXED_FP(99);
+               CASE_FIXED_FP(100);
+               CASE_FIXED_FP(101);
+               CASE_FIXED_FP(102);
+               CASE_FIXED_FP(103);
+               CASE_FIXED_FP(104);
+               CASE_FIXED_FP(105);
+               CASE_FIXED_FP(106);
+               CASE_FIXED_FP(107);
+               CASE_FIXED_FP(108);
+               CASE_FIXED_FP(109);
+               CASE_FIXED_FP(110);
+               CASE_FIXED_FP(111);
+               CASE_FIXED_FP(112);
+               CASE_FIXED_FP(113);
+               CASE_FIXED_FP(114);
+               CASE_FIXED_FP(115);
+               CASE_FIXED_FP(116);
+               CASE_FIXED_FP(117);
+               CASE_FIXED_FP(118);
+               CASE_FIXED_FP(119);
+               CASE_FIXED_FP(120);
+               CASE_FIXED_FP(121);
+               CASE_FIXED_FP(122);
+               CASE_FIXED_FP(123);
+               CASE_FIXED_FP(124);
+               CASE_FIXED_FP(125);
+               CASE_FIXED_FP(126);
+               CASE_FIXED_FP(127);
+       }
+#undef CASE_FIXED_FP
+}
+
+void setfpreg(unsigned long regnum, struct ia64_fpreg *fpval,
+                                       struct kvm_pt_regs *regs)
+{
+       /* Take floating register rotation into consideration*/
+       if (regnum >= IA64_FIRST_ROTATING_FR)
+               regnum = IA64_FIRST_ROTATING_FR + fph_index(regs, regnum);
+
+#define CASE_FIXED_FP(reg)                     \
+       case (reg) :                            \
+               ia64_ldf_fill(reg, fpval);      \
+       break
+
+       switch (regnum) {
+               CASE_FIXED_FP(2);
+               CASE_FIXED_FP(3);
+               CASE_FIXED_FP(4);
+               CASE_FIXED_FP(5);
+
+               CASE_FIXED_FP(6);
+               CASE_FIXED_FP(7);
+               CASE_FIXED_FP(8);
+               CASE_FIXED_FP(9);
+               CASE_FIXED_FP(10);
+               CASE_FIXED_FP(11);
+
+               CASE_FIXED_FP(12);
+               CASE_FIXED_FP(13);
+               CASE_FIXED_FP(14);
+               CASE_FIXED_FP(15);
+               CASE_FIXED_FP(16);
+               CASE_FIXED_FP(17);
+               CASE_FIXED_FP(18);
+               CASE_FIXED_FP(19);
+               CASE_FIXED_FP(20);
+               CASE_FIXED_FP(21);
+               CASE_FIXED_FP(22);
+               CASE_FIXED_FP(23);
+               CASE_FIXED_FP(24);
+               CASE_FIXED_FP(25);
+               CASE_FIXED_FP(26);
+               CASE_FIXED_FP(27);
+               CASE_FIXED_FP(28);
+               CASE_FIXED_FP(29);
+               CASE_FIXED_FP(30);
+               CASE_FIXED_FP(31);
+               CASE_FIXED_FP(32);
+               CASE_FIXED_FP(33);
+               CASE_FIXED_FP(34);
+               CASE_FIXED_FP(35);
+               CASE_FIXED_FP(36);
+               CASE_FIXED_FP(37);
+               CASE_FIXED_FP(38);
+               CASE_FIXED_FP(39);
+               CASE_FIXED_FP(40);
+               CASE_FIXED_FP(41);
+               CASE_FIXED_FP(42);
+               CASE_FIXED_FP(43);
+               CASE_FIXED_FP(44);
+               CASE_FIXED_FP(45);
+               CASE_FIXED_FP(46);
+               CASE_FIXED_FP(47);
+               CASE_FIXED_FP(48);
+               CASE_FIXED_FP(49);
+               CASE_FIXED_FP(50);
+               CASE_FIXED_FP(51);
+               CASE_FIXED_FP(52);
+               CASE_FIXED_FP(53);
+               CASE_FIXED_FP(54);
+               CASE_FIXED_FP(55);
+               CASE_FIXED_FP(56);
+               CASE_FIXED_FP(57);
+               CASE_FIXED_FP(58);
+               CASE_FIXED_FP(59);
+               CASE_FIXED_FP(60);
+               CASE_FIXED_FP(61);
+               CASE_FIXED_FP(62);
+               CASE_FIXED_FP(63);
+               CASE_FIXED_FP(64);
+               CASE_FIXED_FP(65);
+               CASE_FIXED_FP(66);
+               CASE_FIXED_FP(67);
+               CASE_FIXED_FP(68);
+               CASE_FIXED_FP(69);
+               CASE_FIXED_FP(70);
+               CASE_FIXED_FP(71);
+               CASE_FIXED_FP(72);
+               CASE_FIXED_FP(73);
+               CASE_FIXED_FP(74);
+               CASE_FIXED_FP(75);
+               CASE_FIXED_FP(76);
+               CASE_FIXED_FP(77);
+               CASE_FIXED_FP(78);
+               CASE_FIXED_FP(79);
+               CASE_FIXED_FP(80);
+               CASE_FIXED_FP(81);
+               CASE_FIXED_FP(82);
+               CASE_FIXED_FP(83);
+               CASE_FIXED_FP(84);
+               CASE_FIXED_FP(85);
+               CASE_FIXED_FP(86);
+               CASE_FIXED_FP(87);
+               CASE_FIXED_FP(88);
+               CASE_FIXED_FP(89);
+               CASE_FIXED_FP(90);
+               CASE_FIXED_FP(91);
+               CASE_FIXED_FP(92);
+               CASE_FIXED_FP(93);
+               CASE_FIXED_FP(94);
+               CASE_FIXED_FP(95);
+               CASE_FIXED_FP(96);
+               CASE_FIXED_FP(97);
+               CASE_FIXED_FP(98);
+               CASE_FIXED_FP(99);
+               CASE_FIXED_FP(100);
+               CASE_FIXED_FP(101);
+               CASE_FIXED_FP(102);
+               CASE_FIXED_FP(103);
+               CASE_FIXED_FP(104);
+               CASE_FIXED_FP(105);
+               CASE_FIXED_FP(106);
+               CASE_FIXED_FP(107);
+               CASE_FIXED_FP(108);
+               CASE_FIXED_FP(109);
+               CASE_FIXED_FP(110);
+               CASE_FIXED_FP(111);
+               CASE_FIXED_FP(112);
+               CASE_FIXED_FP(113);
+               CASE_FIXED_FP(114);
+               CASE_FIXED_FP(115);
+               CASE_FIXED_FP(116);
+               CASE_FIXED_FP(117);
+               CASE_FIXED_FP(118);
+               CASE_FIXED_FP(119);
+               CASE_FIXED_FP(120);
+               CASE_FIXED_FP(121);
+               CASE_FIXED_FP(122);
+               CASE_FIXED_FP(123);
+               CASE_FIXED_FP(124);
+               CASE_FIXED_FP(125);
+               CASE_FIXED_FP(126);
+               CASE_FIXED_FP(127);
+       }
+}
+
+void vcpu_get_fpreg(struct kvm_vcpu *vcpu, unsigned long reg,
+                                               struct ia64_fpreg *val)
+{
+       struct kvm_pt_regs *regs = vcpu_regs(vcpu);
+
+       getfpreg(reg, val, regs);   /* FIXME: handle NATs later*/
+}
+
+void vcpu_set_fpreg(struct kvm_vcpu *vcpu, unsigned long reg,
+                                               struct ia64_fpreg *val)
+{
+       struct kvm_pt_regs *regs = vcpu_regs(vcpu);
+
+       if (reg > 1)
+               setfpreg(reg, val, regs);   /* FIXME: handle NATs later*/
+}
+
+/************************************************************************
+ * lsapic timer
+ ***********************************************************************/
+u64 vcpu_get_itc(struct kvm_vcpu *vcpu)
+{
+       unsigned long guest_itc;
+       guest_itc = VMX(vcpu, itc_offset) + ia64_getreg(_IA64_REG_AR_ITC);
+
+       if (guest_itc >= VMX(vcpu, last_itc)) {
+               VMX(vcpu, last_itc) = guest_itc;
+               return  guest_itc;
+       } else
+               return VMX(vcpu, last_itc);
+}
+
+static inline void vcpu_set_itm(struct kvm_vcpu *vcpu, u64 val);
+static void vcpu_set_itc(struct kvm_vcpu *vcpu, u64 val)
+{
+       struct kvm_vcpu *v;
+       int i;
+       long itc_offset = val - ia64_getreg(_IA64_REG_AR_ITC);
+       unsigned long vitv = VCPU(vcpu, itv);
+
+       if (vcpu->vcpu_id == 0) {
+               for (i = 0; i < MAX_VCPU_NUM; i++) {
+                       v = (struct kvm_vcpu *)((char *)vcpu + VCPU_SIZE * i);
+                       VMX(v, itc_offset) = itc_offset;
+                       VMX(v, last_itc) = 0;
+               }
+       }
+       VMX(vcpu, last_itc) = 0;
+       if (VCPU(vcpu, itm) <= val) {
+               VMX(vcpu, itc_check) = 0;
+               vcpu_unpend_interrupt(vcpu, vitv);
+       } else {
+               VMX(vcpu, itc_check) = 1;
+               vcpu_set_itm(vcpu, VCPU(vcpu, itm));
+       }
+
+}
+
+static inline u64 vcpu_get_itm(struct kvm_vcpu *vcpu)
+{
+       return ((u64)VCPU(vcpu, itm));
+}
+
+static inline void vcpu_set_itm(struct kvm_vcpu *vcpu, u64 val)
+{
+       unsigned long vitv = VCPU(vcpu, itv);
+       VCPU(vcpu, itm) = val;
+
+       if (val > vcpu_get_itc(vcpu)) {
+               VMX(vcpu, itc_check) = 1;
+               vcpu_unpend_interrupt(vcpu, vitv);
+               VMX(vcpu, timer_pending) = 0;
+       } else
+               VMX(vcpu, itc_check) = 0;
+}
+
+#define  ITV_VECTOR(itv)    (itv&0xff)
+#define  ITV_IRQ_MASK(itv)  (itv&(1<<16))
+
+static inline void vcpu_set_itv(struct kvm_vcpu *vcpu, u64 val)
+{
+       VCPU(vcpu, itv) = val;
+       if (!ITV_IRQ_MASK(val) && vcpu->arch.timer_pending) {
+               vcpu_pend_interrupt(vcpu, ITV_VECTOR(val));
+               vcpu->arch.timer_pending = 0;
+       }
+}
+
+static inline void vcpu_set_eoi(struct kvm_vcpu *vcpu, u64 val)
+{
+       int vec;
+
+       vec = highest_inservice_irq(vcpu);
+       if (vec == NULL_VECTOR)
+               return;
+       VMX(vcpu, insvc[vec >> 6]) &= ~(1UL << (vec & 63));
+       VCPU(vcpu, eoi) = 0;
+       vcpu->arch.irq_new_pending = 1;
+
+}
+
+/* See Table 5-8 in SDM vol2 for the definition */
+int irq_masked(struct kvm_vcpu *vcpu, int h_pending, int h_inservice)
+{
+       union ia64_tpr vtpr;
+
+       vtpr.val = VCPU(vcpu, tpr);
+
+       if (h_inservice == NMI_VECTOR)
+               return IRQ_MASKED_BY_INSVC;
+
+       if (h_pending == NMI_VECTOR) {
+               /* Non Maskable Interrupt */
+               return IRQ_NO_MASKED;
+       }
+
+       if (h_inservice == ExtINT_VECTOR)
+               return IRQ_MASKED_BY_INSVC;
+
+       if (h_pending == ExtINT_VECTOR) {
+               if (vtpr.mmi) {
+                       /* mask all external IRQ */
+                       return IRQ_MASKED_BY_VTPR;
+               } else
+                       return IRQ_NO_MASKED;
+       }
+
+       if (is_higher_irq(h_pending, h_inservice)) {
+               if (is_higher_class(h_pending, vtpr.mic + (vtpr.mmi << 4)))
+                       return IRQ_NO_MASKED;
+               else
+                       return IRQ_MASKED_BY_VTPR;
+       } else {
+               return IRQ_MASKED_BY_INSVC;
+       }
+}
+
+void vcpu_pend_interrupt(struct kvm_vcpu *vcpu, u8 vec)
+{
+       long spsr;
+       int ret;
+
+       local_irq_save(spsr);
+       ret = test_and_set_bit(vec, &VCPU(vcpu, irr[0]));
+       local_irq_restore(spsr);
+
+       vcpu->arch.irq_new_pending = 1;
+}
+
+void vcpu_unpend_interrupt(struct kvm_vcpu *vcpu, u8 vec)
+{
+       long spsr;
+       int ret;
+
+       local_irq_save(spsr);
+       ret = test_and_clear_bit(vec, &VCPU(vcpu, irr[0]));
+       local_irq_restore(spsr);
+       if (ret) {
+               vcpu->arch.irq_new_pending = 1;
+               wmb();
+       }
+}
+
+void update_vhpi(struct kvm_vcpu *vcpu, int vec)
+{
+       u64 vhpi;
+
+       if (vec == NULL_VECTOR)
+               vhpi = 0;
+       else if (vec == NMI_VECTOR)
+               vhpi = 32;
+       else if (vec == ExtINT_VECTOR)
+               vhpi = 16;
+       else
+               vhpi = vec >> 4;
+
+       VCPU(vcpu, vhpi) = vhpi;
+       if (VCPU(vcpu, vac).a_int)
+               ia64_call_vsa(PAL_VPS_SET_PENDING_INTERRUPT,
+                               (u64)vcpu->arch.vpd, 0, 0, 0, 0, 0, 0);
+}
+
+u64 vcpu_get_ivr(struct kvm_vcpu *vcpu)
+{
+       int vec, h_inservice, mask;
+
+       vec = highest_pending_irq(vcpu);
+       h_inservice = highest_inservice_irq(vcpu);
+       mask = irq_masked(vcpu, vec, h_inservice);
+       if (vec == NULL_VECTOR || mask == IRQ_MASKED_BY_INSVC) {
+               if (VCPU(vcpu, vhpi))
+                       update_vhpi(vcpu, NULL_VECTOR);
+               return IA64_SPURIOUS_INT_VECTOR;
+       }
+       if (mask == IRQ_MASKED_BY_VTPR) {
+               update_vhpi(vcpu, vec);
+               return IA64_SPURIOUS_INT_VECTOR;
+       }
+       VMX(vcpu, insvc[vec >> 6]) |= (1UL << (vec & 63));
+       vcpu_unpend_interrupt(vcpu, vec);
+       return  (u64)vec;
+}
+
+/**************************************************************************
+  Privileged operation emulation routines
+ **************************************************************************/
+u64 vcpu_thash(struct kvm_vcpu *vcpu, u64 vadr)
+{
+       union ia64_pta vpta;
+       union ia64_rr vrr;
+       u64 pval;
+       u64 vhpt_offset;
+
+       vpta.val = vcpu_get_pta(vcpu);
+       vrr.val = vcpu_get_rr(vcpu, vadr);
+       vhpt_offset = ((vadr >> vrr.ps) << 3) & ((1UL << (vpta.size)) - 1);
+       if (vpta.vf) {
+               pval = ia64_call_vsa(PAL_VPS_THASH, vadr, vrr.val,
+                               vpta.val, 0, 0, 0, 0);
+       } else {
+               pval = (vadr & VRN_MASK) | vhpt_offset |
+                       (vpta.val << 3 >> (vpta.size + 3) << (vpta.size));
+       }
+       return  pval;
+}
+
+u64 vcpu_ttag(struct kvm_vcpu *vcpu, u64 vadr)
+{
+       union ia64_rr vrr;
+       union ia64_pta vpta;
+       u64 pval;
+
+       vpta.val = vcpu_get_pta(vcpu);
+       vrr.val = vcpu_get_rr(vcpu, vadr);
+       if (vpta.vf) {
+               pval = ia64_call_vsa(PAL_VPS_TTAG, vadr, vrr.val,
+                                               0, 0, 0, 0, 0);
+       } else
+               pval = 1;
+
+       return  pval;
+}
+
+u64 vcpu_tak(struct kvm_vcpu *vcpu, u64 vadr)
+{
+       struct thash_data *data;
+       union ia64_pta vpta;
+       u64 key;
+
+       vpta.val = vcpu_get_pta(vcpu);
+       if (vpta.vf == 0) {
+               key = 1;
+               return key;
+       }
+       data = vtlb_lookup(vcpu, vadr, D_TLB);
+       if (!data || !data->p)
+               key = 1;
+       else
+               key = data->key;
+
+       return key;
+}
+
+
+
+void kvm_thash(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long thash, vadr;
+
+       vadr = vcpu_get_gr(vcpu, inst.M46.r3);
+       thash = vcpu_thash(vcpu, vadr);
+       vcpu_set_gr(vcpu, inst.M46.r1, thash, 0);
+}
+
+
+void kvm_ttag(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long tag, vadr;
+
+       vadr = vcpu_get_gr(vcpu, inst.M46.r3);
+       tag = vcpu_ttag(vcpu, vadr);
+       vcpu_set_gr(vcpu, inst.M46.r1, tag, 0);
+}
+
+int vcpu_tpa(struct kvm_vcpu *vcpu, u64 vadr, u64 *padr)
+{
+       struct thash_data *data;
+       union ia64_isr visr, pt_isr;
+       struct kvm_pt_regs *regs;
+       struct ia64_psr vpsr;
+
+       regs = vcpu_regs(vcpu);
+       pt_isr.val = VMX(vcpu, cr_isr);
+       visr.val = 0;
+       visr.ei = pt_isr.ei;
+       visr.ir = pt_isr.ir;
+       vpsr = *(struct ia64_psr *)&VCPU(vcpu, vpsr);
+       visr.na = 1;
+
+       data = vhpt_lookup(vadr);
+       if (data) {
+               if (data->p == 0) {
+                       vcpu_set_isr(vcpu, visr.val);
+                       data_page_not_present(vcpu, vadr);
+                       return IA64_FAULT;
+               } else if (data->ma == VA_MATTR_NATPAGE) {
+                       vcpu_set_isr(vcpu, visr.val);
+                       dnat_page_consumption(vcpu, vadr);
+                       return IA64_FAULT;
+               } else {
+                       *padr = (data->gpaddr >> data->ps << data->ps) |
+                               (vadr & (PSIZE(data->ps) - 1));
+                       return IA64_NO_FAULT;
+               }
+       }
+
+       data = vtlb_lookup(vcpu, vadr, D_TLB);
+       if (data) {
+               if (data->p == 0) {
+                       vcpu_set_isr(vcpu, visr.val);
+                       data_page_not_present(vcpu, vadr);
+                       return IA64_FAULT;
+               } else if (data->ma == VA_MATTR_NATPAGE) {
+                       vcpu_set_isr(vcpu, visr.val);
+                       dnat_page_consumption(vcpu, vadr);
+                       return IA64_FAULT;
+               } else{
+                       *padr = ((data->ppn >> (data->ps - 12)) << data->ps)
+                               | (vadr & (PSIZE(data->ps) - 1));
+                       return IA64_NO_FAULT;
+               }
+       }
+       if (!vhpt_enabled(vcpu, vadr, NA_REF)) {
+               if (vpsr.ic) {
+                       vcpu_set_isr(vcpu, visr.val);
+                       alt_dtlb(vcpu, vadr);
+                       return IA64_FAULT;
+               } else {
+                       nested_dtlb(vcpu);
+                       return IA64_FAULT;
+               }
+       } else {
+               if (vpsr.ic) {
+                       vcpu_set_isr(vcpu, visr.val);
+                       dvhpt_fault(vcpu, vadr);
+                       return IA64_FAULT;
+               } else{
+                       nested_dtlb(vcpu);
+                       return IA64_FAULT;
+               }
+       }
+
+       return IA64_NO_FAULT;
+}
+
+
+int kvm_tpa(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long r1, r3;
+
+       r3 = vcpu_get_gr(vcpu, inst.M46.r3);
+
+       if (vcpu_tpa(vcpu, r3, &r1))
+               return IA64_FAULT;
+
+       vcpu_set_gr(vcpu, inst.M46.r1, r1, 0);
+       return(IA64_NO_FAULT);
+}
+
+void kvm_tak(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long r1, r3;
+
+       r3 = vcpu_get_gr(vcpu, inst.M46.r3);
+       r1 = vcpu_tak(vcpu, r3);
+       vcpu_set_gr(vcpu, inst.M46.r1, r1, 0);
+}
+
+
+/************************************
+ * Insert/Purge translation register/cache
+ ************************************/
+void vcpu_itc_i(struct kvm_vcpu *vcpu, u64 pte, u64 itir, u64 ifa)
+{
+       thash_purge_and_insert(vcpu, pte, itir, ifa, I_TLB);
+}
+
+void vcpu_itc_d(struct kvm_vcpu *vcpu, u64 pte, u64 itir, u64 ifa)
+{
+       thash_purge_and_insert(vcpu, pte, itir, ifa, D_TLB);
+}
+
+void vcpu_itr_i(struct kvm_vcpu *vcpu, u64 slot, u64 pte, u64 itir, u64 ifa)
+{
+       u64 ps, va, rid;
+       struct thash_data *p_itr;
+
+       ps = itir_ps(itir);
+       va = PAGEALIGN(ifa, ps);
+       pte &= ~PAGE_FLAGS_RV_MASK;
+       rid = vcpu_get_rr(vcpu, ifa);
+       rid = rid & RR_RID_MASK;
+       p_itr = (struct thash_data *)&vcpu->arch.itrs[slot];
+       vcpu_set_tr(p_itr, pte, itir, va, rid);
+       vcpu_quick_region_set(VMX(vcpu, itr_regions), va);
+}
+
+
+void vcpu_itr_d(struct kvm_vcpu *vcpu, u64 slot, u64 pte, u64 itir, u64 ifa)
+{
+       u64 gpfn;
+       u64 ps, va, rid;
+       struct thash_data *p_dtr;
+
+       ps = itir_ps(itir);
+       va = PAGEALIGN(ifa, ps);
+       pte &= ~PAGE_FLAGS_RV_MASK;
+
+       if (ps != _PAGE_SIZE_16M)
+               thash_purge_entries(vcpu, va, ps);
+       gpfn = (pte & _PAGE_PPN_MASK) >> PAGE_SHIFT;
+       if (__gpfn_is_io(gpfn))
+               pte |= VTLB_PTE_IO;
+       rid = vcpu_get_rr(vcpu, va);
+       rid = rid & RR_RID_MASK;
+       p_dtr = (struct thash_data *)&vcpu->arch.dtrs[slot];
+       vcpu_set_tr((struct thash_data *)&vcpu->arch.dtrs[slot],
+                                                       pte, itir, va, rid);
+       vcpu_quick_region_set(VMX(vcpu, dtr_regions), va);
+}
+
+void vcpu_ptr_d(struct kvm_vcpu *vcpu, u64 ifa, u64 ps)
+{
+       int index;
+       u64 va;
+
+       va = PAGEALIGN(ifa, ps);
+       while ((index = vtr_find_overlap(vcpu, va, ps, D_TLB)) >= 0)
+               vcpu->arch.dtrs[index].page_flags = 0;
+
+       thash_purge_entries(vcpu, va, ps);
+}
+
+void vcpu_ptr_i(struct kvm_vcpu *vcpu, u64 ifa, u64 ps)
+{
+       int index;
+       u64 va;
+
+       va = PAGEALIGN(ifa, ps);
+       while ((index = vtr_find_overlap(vcpu, va, ps, I_TLB)) >= 0)
+               vcpu->arch.itrs[index].page_flags = 0;
+
+       thash_purge_entries(vcpu, va, ps);
+}
+
+void vcpu_ptc_l(struct kvm_vcpu *vcpu, u64 va, u64 ps)
+{
+       va = PAGEALIGN(va, ps);
+       thash_purge_entries(vcpu, va, ps);
+}
+
+void vcpu_ptc_e(struct kvm_vcpu *vcpu, u64 va)
+{
+       thash_purge_all(vcpu);
+}
+
+void vcpu_ptc_ga(struct kvm_vcpu *vcpu, u64 va, u64 ps)
+{
+       struct exit_ctl_data *p = &vcpu->arch.exit_data;
+       long psr;
+       local_irq_save(psr);
+       p->exit_reason = EXIT_REASON_PTC_G;
+
+       p->u.ptc_g_data.rr = vcpu_get_rr(vcpu, va);
+       p->u.ptc_g_data.vaddr = va;
+       p->u.ptc_g_data.ps = ps;
+       vmm_transition(vcpu);
+       /* Do Local Purge Here*/
+       vcpu_ptc_l(vcpu, va, ps);
+       local_irq_restore(psr);
+}
+
+
+void vcpu_ptc_g(struct kvm_vcpu *vcpu, u64 va, u64 ps)
+{
+       vcpu_ptc_ga(vcpu, va, ps);
+}
+
+void kvm_ptc_e(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long ifa;
+
+       ifa = vcpu_get_gr(vcpu, inst.M45.r3);
+       vcpu_ptc_e(vcpu, ifa);
+}
+
+void kvm_ptc_g(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long ifa, itir;
+
+       ifa = vcpu_get_gr(vcpu, inst.M45.r3);
+       itir = vcpu_get_gr(vcpu, inst.M45.r2);
+       vcpu_ptc_g(vcpu, ifa, itir_ps(itir));
+}
+
+void kvm_ptc_ga(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long ifa, itir;
+
+       ifa = vcpu_get_gr(vcpu, inst.M45.r3);
+       itir = vcpu_get_gr(vcpu, inst.M45.r2);
+       vcpu_ptc_ga(vcpu, ifa, itir_ps(itir));
+}
+
+void kvm_ptc_l(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long ifa, itir;
+
+       ifa = vcpu_get_gr(vcpu, inst.M45.r3);
+       itir = vcpu_get_gr(vcpu, inst.M45.r2);
+       vcpu_ptc_l(vcpu, ifa, itir_ps(itir));
+}
+
+void kvm_ptr_d(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long ifa, itir;
+
+       ifa = vcpu_get_gr(vcpu, inst.M45.r3);
+       itir = vcpu_get_gr(vcpu, inst.M45.r2);
+       vcpu_ptr_d(vcpu, ifa, itir_ps(itir));
+}
+
+void kvm_ptr_i(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long ifa, itir;
+
+       ifa = vcpu_get_gr(vcpu, inst.M45.r3);
+       itir = vcpu_get_gr(vcpu, inst.M45.r2);
+       vcpu_ptr_i(vcpu, ifa, itir_ps(itir));
+}
+
+void kvm_itr_d(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long itir, ifa, pte, slot;
+
+       slot = vcpu_get_gr(vcpu, inst.M45.r3);
+       pte = vcpu_get_gr(vcpu, inst.M45.r2);
+       itir = vcpu_get_itir(vcpu);
+       ifa = vcpu_get_ifa(vcpu);
+       vcpu_itr_d(vcpu, slot, pte, itir, ifa);
+}
+
+
+
+void kvm_itr_i(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long itir, ifa, pte, slot;
+
+       slot = vcpu_get_gr(vcpu, inst.M45.r3);
+       pte = vcpu_get_gr(vcpu, inst.M45.r2);
+       itir = vcpu_get_itir(vcpu);
+       ifa = vcpu_get_ifa(vcpu);
+       vcpu_itr_i(vcpu, slot, pte, itir, ifa);
+}
+
+void kvm_itc_d(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long itir, ifa, pte;
+
+       itir = vcpu_get_itir(vcpu);
+       ifa = vcpu_get_ifa(vcpu);
+       pte = vcpu_get_gr(vcpu, inst.M45.r2);
+       vcpu_itc_d(vcpu, pte, itir, ifa);
+}
+
+void kvm_itc_i(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long itir, ifa, pte;
+
+       itir = vcpu_get_itir(vcpu);
+       ifa = vcpu_get_ifa(vcpu);
+       pte = vcpu_get_gr(vcpu, inst.M45.r2);
+       vcpu_itc_i(vcpu, pte, itir, ifa);
+}
+
+/*************************************
+ * Moves to semi-privileged registers
+ *************************************/
+
+void kvm_mov_to_ar_imm(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long imm;
+
+       if (inst.M30.s)
+               imm = -inst.M30.imm;
+       else
+               imm = inst.M30.imm;
+
+       vcpu_set_itc(vcpu, imm);
+}
+
+void kvm_mov_to_ar_reg(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long r2;
+
+       r2 = vcpu_get_gr(vcpu, inst.M29.r2);
+       vcpu_set_itc(vcpu, r2);
+}
+
+
+void kvm_mov_from_ar_reg(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long r1;
+
+       r1 = vcpu_get_itc(vcpu);
+       vcpu_set_gr(vcpu, inst.M31.r1, r1, 0);
+}
+/**************************************************************************
+  struct kvm_vcpu*protection key register access routines
+ **************************************************************************/
+
+unsigned long vcpu_get_pkr(struct kvm_vcpu *vcpu, unsigned long reg)
+{
+       return ((unsigned long)ia64_get_pkr(reg));
+}
+
+void vcpu_set_pkr(struct kvm_vcpu *vcpu, unsigned long reg, unsigned long val)
+{
+       ia64_set_pkr(reg, val);
+}
+
+
+unsigned long vcpu_get_itir_on_fault(struct kvm_vcpu *vcpu, unsigned long ifa)
+{
+       union ia64_rr rr, rr1;
+
+       rr.val = vcpu_get_rr(vcpu, ifa);
+       rr1.val = 0;
+       rr1.ps = rr.ps;
+       rr1.rid = rr.rid;
+       return (rr1.val);
+}
+
+
+
+/********************************
+ * Moves to privileged registers
+ ********************************/
+unsigned long vcpu_set_rr(struct kvm_vcpu *vcpu, unsigned long reg,
+                                       unsigned long val)
+{
+       union ia64_rr oldrr, newrr;
+       unsigned long rrval;
+       struct exit_ctl_data *p = &vcpu->arch.exit_data;
+       unsigned long psr;
+
+       oldrr.val = vcpu_get_rr(vcpu, reg);
+       newrr.val = val;
+       vcpu->arch.vrr[reg >> VRN_SHIFT] = val;
+
+       switch ((unsigned long)(reg >> VRN_SHIFT)) {
+       case VRN6:
+               vcpu->arch.vmm_rr = vrrtomrr(val);
+               local_irq_save(psr);
+               p->exit_reason = EXIT_REASON_SWITCH_RR6;
+               vmm_transition(vcpu);
+               local_irq_restore(psr);
+               break;
+       case VRN4:
+               rrval = vrrtomrr(val);
+               vcpu->arch.metaphysical_saved_rr4 = rrval;
+               if (!is_physical_mode(vcpu))
+                       ia64_set_rr(reg, rrval);
+               break;
+       case VRN0:
+               rrval = vrrtomrr(val);
+               vcpu->arch.metaphysical_saved_rr0 = rrval;
+               if (!is_physical_mode(vcpu))
+                       ia64_set_rr(reg, rrval);
+               break;
+       default:
+               ia64_set_rr(reg, vrrtomrr(val));
+               break;
+       }
+
+       return (IA64_NO_FAULT);
+}
+
+
+
+void kvm_mov_to_rr(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long r3, r2;
+
+       r3 = vcpu_get_gr(vcpu, inst.M42.r3);
+       r2 = vcpu_get_gr(vcpu, inst.M42.r2);
+       vcpu_set_rr(vcpu, r3, r2);
+}
+
+void kvm_mov_to_dbr(struct kvm_vcpu *vcpu, INST64 inst)
+{
+}
+
+void kvm_mov_to_ibr(struct kvm_vcpu *vcpu, INST64 inst)
+{
+}
+
+void kvm_mov_to_pmc(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long r3, r2;
+
+       r3 = vcpu_get_gr(vcpu, inst.M42.r3);
+       r2 = vcpu_get_gr(vcpu, inst.M42.r2);
+       vcpu_set_pmc(vcpu, r3, r2);
+}
+
+void kvm_mov_to_pmd(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long r3, r2;
+
+       r3 = vcpu_get_gr(vcpu, inst.M42.r3);
+       r2 = vcpu_get_gr(vcpu, inst.M42.r2);
+       vcpu_set_pmd(vcpu, r3, r2);
+}
+
+void kvm_mov_to_pkr(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       u64 r3, r2;
+
+       r3 = vcpu_get_gr(vcpu, inst.M42.r3);
+       r2 = vcpu_get_gr(vcpu, inst.M42.r2);
+       vcpu_set_pkr(vcpu, r3, r2);
+}
+
+
+
+void kvm_mov_from_rr(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long r3, r1;
+
+       r3 = vcpu_get_gr(vcpu, inst.M43.r3);
+       r1 = vcpu_get_rr(vcpu, r3);
+       vcpu_set_gr(vcpu, inst.M43.r1, r1, 0);
+}
+
+void kvm_mov_from_pkr(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long r3, r1;
+
+       r3 = vcpu_get_gr(vcpu, inst.M43.r3);
+       r1 = vcpu_get_pkr(vcpu, r3);
+       vcpu_set_gr(vcpu, inst.M43.r1, r1, 0);
+}
+
+void kvm_mov_from_dbr(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long r3, r1;
+
+       r3 = vcpu_get_gr(vcpu, inst.M43.r3);
+       r1 = vcpu_get_dbr(vcpu, r3);
+       vcpu_set_gr(vcpu, inst.M43.r1, r1, 0);
+}
+
+void kvm_mov_from_ibr(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long r3, r1;
+
+       r3 = vcpu_get_gr(vcpu, inst.M43.r3);
+       r1 = vcpu_get_ibr(vcpu, r3);
+       vcpu_set_gr(vcpu, inst.M43.r1, r1, 0);
+}
+
+void kvm_mov_from_pmc(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long r3, r1;
+
+       r3 = vcpu_get_gr(vcpu, inst.M43.r3);
+       r1 = vcpu_get_pmc(vcpu, r3);
+       vcpu_set_gr(vcpu, inst.M43.r1, r1, 0);
+}
+
+
+unsigned long vcpu_get_cpuid(struct kvm_vcpu *vcpu, unsigned long reg)
+{
+       /* FIXME: This could get called as a result of a rsvd-reg fault */
+       if (reg > (ia64_get_cpuid(3) & 0xff))
+               return 0;
+       else
+               return ia64_get_cpuid(reg);
+}
+
+void kvm_mov_from_cpuid(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long r3, r1;
+
+       r3 = vcpu_get_gr(vcpu, inst.M43.r3);
+       r1 = vcpu_get_cpuid(vcpu, r3);
+       vcpu_set_gr(vcpu, inst.M43.r1, r1, 0);
+}
+
+void vcpu_set_tpr(struct kvm_vcpu *vcpu, unsigned long val)
+{
+       VCPU(vcpu, tpr) = val;
+       vcpu->arch.irq_check = 1;
+}
+
+unsigned long kvm_mov_to_cr(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long r2;
+
+       r2 = vcpu_get_gr(vcpu, inst.M32.r2);
+       VCPU(vcpu, vcr[inst.M32.cr3]) = r2;
+
+       switch (inst.M32.cr3) {
+       case 0:
+               vcpu_set_dcr(vcpu, r2);
+               break;
+       case 1:
+               vcpu_set_itm(vcpu, r2);
+               break;
+       case 66:
+               vcpu_set_tpr(vcpu, r2);
+               break;
+       case 67:
+               vcpu_set_eoi(vcpu, r2);
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+
+unsigned long kvm_mov_from_cr(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long tgt = inst.M33.r1;
+       unsigned long val;
+
+       switch (inst.M33.cr3) {
+       case 65:
+               val = vcpu_get_ivr(vcpu);
+               vcpu_set_gr(vcpu, tgt, val, 0);
+               break;
+
+       case 67:
+               vcpu_set_gr(vcpu, tgt, 0L, 0);
+               break;
+       default:
+               val = VCPU(vcpu, vcr[inst.M33.cr3]);
+               vcpu_set_gr(vcpu, tgt, val, 0);
+               break;
+       }
+
+       return 0;
+}
+
+
+
+void vcpu_set_psr(struct kvm_vcpu *vcpu, unsigned long val)
+{
+
+       unsigned long mask;
+       struct kvm_pt_regs *regs;
+       struct ia64_psr old_psr, new_psr;
+
+       old_psr = *(struct ia64_psr *)&VCPU(vcpu, vpsr);
+
+       regs = vcpu_regs(vcpu);
+       /* We only support guest as:
+        *  vpsr.pk = 0
+        *  vpsr.is = 0
+        * Otherwise panic
+        */
+       if (val & (IA64_PSR_PK | IA64_PSR_IS | IA64_PSR_VM))
+               panic_vm(vcpu);
+
+       /*
+        * For those IA64_PSR bits: id/da/dd/ss/ed/ia
+        * Since these bits will become 0, after success execution of each
+        * instruction, we will change set them to mIA64_PSR
+        */
+       VCPU(vcpu, vpsr) = val
+               & (~(IA64_PSR_ID | IA64_PSR_DA | IA64_PSR_DD |
+                       IA64_PSR_SS | IA64_PSR_ED | IA64_PSR_IA));
+
+       if (!old_psr.i && (val & IA64_PSR_I)) {
+               /* vpsr.i 0->1 */
+               vcpu->arch.irq_check = 1;
+       }
+       new_psr = *(struct ia64_psr *)&VCPU(vcpu, vpsr);
+
+       /*
+        * All vIA64_PSR bits shall go to mPSR (v->tf->tf_special.psr)
+        * , except for the following bits:
+        *  ic/i/dt/si/rt/mc/it/bn/vm
+        */
+       mask =  IA64_PSR_IC + IA64_PSR_I + IA64_PSR_DT + IA64_PSR_SI +
+               IA64_PSR_RT + IA64_PSR_MC + IA64_PSR_IT + IA64_PSR_BN +
+               IA64_PSR_VM;
+
+       regs->cr_ipsr = (regs->cr_ipsr & mask) | (val & (~mask));
+
+       check_mm_mode_switch(vcpu, old_psr, new_psr);
+
+       return ;
+}
+
+unsigned long vcpu_cover(struct kvm_vcpu *vcpu)
+{
+       struct ia64_psr vpsr;
+
+       struct kvm_pt_regs *regs = vcpu_regs(vcpu);
+       vpsr = *(struct ia64_psr *)&VCPU(vcpu, vpsr);
+
+       if (!vpsr.ic)
+               VCPU(vcpu, ifs) = regs->cr_ifs;
+       regs->cr_ifs = IA64_IFS_V;
+       return (IA64_NO_FAULT);
+}
+
+
+
+/**************************************************************************
+  VCPU banked general register access routines
+ **************************************************************************/
+#define vcpu_bsw0_unat(i, b0unat, b1unat, runat, VMM_PT_REGS_R16_SLOT) \
+       do {                                                            \
+               __asm__ __volatile__ (                                  \
+                               ";;extr.u %0 = %3,%6,16;;\n"            \
+                               "dep %1 = %0, %1, 0, 16;;\n"            \
+                               "st8 [%4] = %1\n"                       \
+                               "extr.u %0 = %2, 16, 16;;\n"            \
+                               "dep %3 = %0, %3, %6, 16;;\n"           \
+                               "st8 [%5] = %3\n"                       \
+                               ::"r"(i), "r"(*b1unat), "r"(*b0unat),   \
+                               "r"(*runat), "r"(b1unat), "r"(runat),   \
+                               "i"(VMM_PT_REGS_R16_SLOT) : "memory");  \
+       } while (0)
+
+void vcpu_bsw0(struct kvm_vcpu *vcpu)
+{
+       unsigned long i;
+
+       struct kvm_pt_regs *regs = vcpu_regs(vcpu);
+       unsigned long *r = &regs->r16;
+       unsigned long *b0 = &VCPU(vcpu, vbgr[0]);
+       unsigned long *b1 = &VCPU(vcpu, vgr[0]);
+       unsigned long *runat = &regs->eml_unat;
+       unsigned long *b0unat = &VCPU(vcpu, vbnat);
+       unsigned long *b1unat = &VCPU(vcpu, vnat);
+
+
+       if (VCPU(vcpu, vpsr) & IA64_PSR_BN) {
+               for (i = 0; i < 16; i++) {
+                       *b1++ = *r;
+                       *r++ = *b0++;
+               }
+               vcpu_bsw0_unat(i, b0unat, b1unat, runat,
+                               VMM_PT_REGS_R16_SLOT);
+               VCPU(vcpu, vpsr) &= ~IA64_PSR_BN;
+       }
+}
+
+#define vcpu_bsw1_unat(i, b0unat, b1unat, runat, VMM_PT_REGS_R16_SLOT) \
+       do {                                                            \
+               __asm__ __volatile__ (";;extr.u %0 = %3, %6, 16;;\n"    \
+                               "dep %1 = %0, %1, 16, 16;;\n"           \
+                               "st8 [%4] = %1\n"                       \
+                               "extr.u %0 = %2, 0, 16;;\n"             \
+                               "dep %3 = %0, %3, %6, 16;;\n"           \
+                               "st8 [%5] = %3\n"                       \
+                               ::"r"(i), "r"(*b0unat), "r"(*b1unat),   \
+                               "r"(*runat), "r"(b0unat), "r"(runat),   \
+                               "i"(VMM_PT_REGS_R16_SLOT) : "memory");  \
+       } while (0)
+
+void vcpu_bsw1(struct kvm_vcpu *vcpu)
+{
+       unsigned long i;
+       struct kvm_pt_regs *regs = vcpu_regs(vcpu);
+       unsigned long *r = &regs->r16;
+       unsigned long *b0 = &VCPU(vcpu, vbgr[0]);
+       unsigned long *b1 = &VCPU(vcpu, vgr[0]);
+       unsigned long *runat = &regs->eml_unat;
+       unsigned long *b0unat = &VCPU(vcpu, vbnat);
+       unsigned long *b1unat = &VCPU(vcpu, vnat);
+
+       if (!(VCPU(vcpu, vpsr) & IA64_PSR_BN)) {
+               for (i = 0; i < 16; i++) {
+                       *b0++ = *r;
+                       *r++ = *b1++;
+               }
+               vcpu_bsw1_unat(i, b0unat, b1unat, runat,
+                               VMM_PT_REGS_R16_SLOT);
+               VCPU(vcpu, vpsr) |= IA64_PSR_BN;
+       }
+}
+
+
+
+
+void vcpu_rfi(struct kvm_vcpu *vcpu)
+{
+       unsigned long ifs, psr;
+       struct kvm_pt_regs *regs = vcpu_regs(vcpu);
+
+       psr = VCPU(vcpu, ipsr);
+       if (psr & IA64_PSR_BN)
+               vcpu_bsw1(vcpu);
+       else
+               vcpu_bsw0(vcpu);
+       vcpu_set_psr(vcpu, psr);
+       ifs = VCPU(vcpu, ifs);
+       if (ifs >> 63)
+               regs->cr_ifs = ifs;
+       regs->cr_iip = VCPU(vcpu, iip);
+}
+
+
+/*
+   VPSR can't keep track of below bits of guest PSR
+   This function gets guest PSR
+ */
+
+unsigned long vcpu_get_psr(struct kvm_vcpu *vcpu)
+{
+       unsigned long mask;
+       struct kvm_pt_regs *regs = vcpu_regs(vcpu);
+
+       mask = IA64_PSR_BE | IA64_PSR_UP | IA64_PSR_AC | IA64_PSR_MFL |
+               IA64_PSR_MFH | IA64_PSR_CPL | IA64_PSR_RI;
+       return (VCPU(vcpu, vpsr) & ~mask) | (regs->cr_ipsr & mask);
+}
+
+void kvm_rsm(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long vpsr;
+       unsigned long imm24 = (inst.M44.i<<23) | (inst.M44.i2<<21)
+                                       | inst.M44.imm;
+
+       vpsr = vcpu_get_psr(vcpu);
+       vpsr &= (~imm24);
+       vcpu_set_psr(vcpu, vpsr);
+}
+
+void kvm_ssm(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long vpsr;
+       unsigned long imm24 = (inst.M44.i << 23) | (inst.M44.i2 << 21)
+                               | inst.M44.imm;
+
+       vpsr = vcpu_get_psr(vcpu);
+       vpsr |= imm24;
+       vcpu_set_psr(vcpu, vpsr);
+}
+
+/* Generate Mask
+ * Parameter:
+ *  bit -- starting bit
+ *  len -- how many bits
+ */
+#define MASK(bit,len)                                  \
+({                                                     \
+               __u64   ret;                            \
+                                                       \
+               __asm __volatile("dep %0=-1, r0, %1, %2"\
+                               : "=r" (ret):           \
+                 "M" (bit),                            \
+                 "M" (len));                           \
+               ret;                                    \
+})
+
+void vcpu_set_psr_l(struct kvm_vcpu *vcpu, unsigned long val)
+{
+       val = (val & MASK(0, 32)) | (vcpu_get_psr(vcpu) & MASK(32, 32));
+       vcpu_set_psr(vcpu, val);
+}
+
+void kvm_mov_to_psr(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long val;
+
+       val = vcpu_get_gr(vcpu, inst.M35.r2);
+       vcpu_set_psr_l(vcpu, val);
+}
+
+void kvm_mov_from_psr(struct kvm_vcpu *vcpu, INST64 inst)
+{
+       unsigned long val;
+
+       val = vcpu_get_psr(vcpu);
+       val = (val & MASK(0, 32)) | (val & MASK(35, 2));
+       vcpu_set_gr(vcpu, inst.M33.r1, val, 0);
+}
+
+void vcpu_increment_iip(struct kvm_vcpu *vcpu)
+{
+       struct kvm_pt_regs *regs = vcpu_regs(vcpu);
+       struct ia64_psr *ipsr = (struct ia64_psr *)&regs->cr_ipsr;
+       if (ipsr->ri == 2) {
+               ipsr->ri = 0;
+               regs->cr_iip += 16;
+       } else
+               ipsr->ri++;
+}
+
+void vcpu_decrement_iip(struct kvm_vcpu *vcpu)
+{
+       struct kvm_pt_regs *regs = vcpu_regs(vcpu);
+       struct ia64_psr *ipsr = (struct ia64_psr *)&regs->cr_ipsr;
+
+       if (ipsr->ri == 0) {
+               ipsr->ri = 2;
+               regs->cr_iip -= 16;
+       } else
+               ipsr->ri--;
+}
+
+/** Emulate a privileged operation.
+ *
+ *
+ * @param vcpu virtual cpu
+ * @cause the reason cause virtualization fault
+ * @opcode the instruction code which cause virtualization fault
+ */
+
+void kvm_emulate(struct kvm_vcpu *vcpu, struct kvm_pt_regs *regs)
+{
+       unsigned long status, cause, opcode ;
+       INST64 inst;
+
+       status = IA64_NO_FAULT;
+       cause = VMX(vcpu, cause);
+       opcode = VMX(vcpu, opcode);
+       inst.inst = opcode;
+       /*
+        * Switch to actual virtual rid in rr0 and rr4,
+        * which is required by some tlb related instructions.
+        */
+       prepare_if_physical_mode(vcpu);
+
+       switch (cause) {
+       case EVENT_RSM:
+               kvm_rsm(vcpu, inst);
+               break;
+       case EVENT_SSM:
+               kvm_ssm(vcpu, inst);
+               break;
+       case EVENT_MOV_TO_PSR:
+               kvm_mov_to_psr(vcpu, inst);
+               break;
+       case EVENT_MOV_FROM_PSR:
+               kvm_mov_from_psr(vcpu, inst);
+               break;
+       case EVENT_MOV_FROM_CR:
+               kvm_mov_from_cr(vcpu, inst);
+               break;
+       case EVENT_MOV_TO_CR:
+               kvm_mov_to_cr(vcpu, inst);
+               break;
+       case EVENT_BSW_0:
+               vcpu_bsw0(vcpu);
+               break;
+       case EVENT_BSW_1:
+               vcpu_bsw1(vcpu);
+               break;
+       case EVENT_COVER:
+               vcpu_cover(vcpu);
+               break;
+       case EVENT_RFI:
+               vcpu_rfi(vcpu);
+               break;
+       case EVENT_ITR_D:
+               kvm_itr_d(vcpu, inst);
+               break;
+       case EVENT_ITR_I:
+               kvm_itr_i(vcpu, inst);
+               break;
+       case EVENT_PTR_D:
+               kvm_ptr_d(vcpu, inst);
+               break;
+       case EVENT_PTR_I:
+               kvm_ptr_i(vcpu, inst);
+               break;
+       case EVENT_ITC_D:
+               kvm_itc_d(vcpu, inst);
+               break;
+       case EVENT_ITC_I:
+               kvm_itc_i(vcpu, inst);
+               break;
+       case EVENT_PTC_L:
+               kvm_ptc_l(vcpu, inst);
+               break;
+       case EVENT_PTC_G:
+               kvm_ptc_g(vcpu, inst);
+               break;
+       case EVENT_PTC_GA:
+               kvm_ptc_ga(vcpu, inst);
+               break;
+       case EVENT_PTC_E:
+               kvm_ptc_e(vcpu, inst);
+               break;
+       case EVENT_MOV_TO_RR:
+               kvm_mov_to_rr(vcpu, inst);
+               break;
+       case EVENT_MOV_FROM_RR:
+               kvm_mov_from_rr(vcpu, inst);
+               break;
+       case EVENT_THASH:
+               kvm_thash(vcpu, inst);
+               break;
+       case EVENT_TTAG:
+               kvm_ttag(vcpu, inst);
+               break;
+       case EVENT_TPA:
+               status = kvm_tpa(vcpu, inst);
+               break;
+       case EVENT_TAK:
+               kvm_tak(vcpu, inst);
+               break;
+       case EVENT_MOV_TO_AR_IMM:
+               kvm_mov_to_ar_imm(vcpu, inst);
+               break;
+       case EVENT_MOV_TO_AR:
+               kvm_mov_to_ar_reg(vcpu, inst);
+               break;
+       case EVENT_MOV_FROM_AR:
+               kvm_mov_from_ar_reg(vcpu, inst);
+               break;
+       case EVENT_MOV_TO_DBR:
+               kvm_mov_to_dbr(vcpu, inst);
+               break;
+       case EVENT_MOV_TO_IBR:
+               kvm_mov_to_ibr(vcpu, inst);
+               break;
+       case EVENT_MOV_TO_PMC:
+               kvm_mov_to_pmc(vcpu, inst);
+               break;
+       case EVENT_MOV_TO_PMD:
+               kvm_mov_to_pmd(vcpu, inst);
+               break;
+       case EVENT_MOV_TO_PKR:
+               kvm_mov_to_pkr(vcpu, inst);
+               break;
+       case EVENT_MOV_FROM_DBR:
+               kvm_mov_from_dbr(vcpu, inst);
+               break;
+       case EVENT_MOV_FROM_IBR:
+               kvm_mov_from_ibr(vcpu, inst);
+               break;
+       case EVENT_MOV_FROM_PMC:
+               kvm_mov_from_pmc(vcpu, inst);
+               break;
+       case EVENT_MOV_FROM_PKR:
+               kvm_mov_from_pkr(vcpu, inst);
+               break;
+       case EVENT_MOV_FROM_CPUID:
+               kvm_mov_from_cpuid(vcpu, inst);
+               break;
+       case EVENT_VMSW:
+               status = IA64_FAULT;
+               break;
+       default:
+               break;
+       };
+       /*Assume all status is NO_FAULT ?*/
+       if (status == IA64_NO_FAULT && cause != EVENT_RFI)
+               vcpu_increment_iip(vcpu);
+
+       recover_if_physical_mode(vcpu);
+}
+
+void init_vcpu(struct kvm_vcpu *vcpu)
+{
+       int i;
+
+       vcpu->arch.mode_flags = GUEST_IN_PHY;
+       VMX(vcpu, vrr[0]) = 0x38;
+       VMX(vcpu, vrr[1]) = 0x38;
+       VMX(vcpu, vrr[2]) = 0x38;
+       VMX(vcpu, vrr[3]) = 0x38;
+       VMX(vcpu, vrr[4]) = 0x38;
+       VMX(vcpu, vrr[5]) = 0x38;
+       VMX(vcpu, vrr[6]) = 0x38;
+       VMX(vcpu, vrr[7]) = 0x38;
+       VCPU(vcpu, vpsr) = IA64_PSR_BN;
+       VCPU(vcpu, dcr) = 0;
+       /* pta.size must not be 0.  The minimum is 15 (32k) */
+       VCPU(vcpu, pta) = 15 << 2;
+       VCPU(vcpu, itv) = 0x10000;
+       VCPU(vcpu, itm) = 0;
+       VMX(vcpu, last_itc) = 0;
+
+       VCPU(vcpu, lid) = VCPU_LID(vcpu);
+       VCPU(vcpu, ivr) = 0;
+       VCPU(vcpu, tpr) = 0x10000;
+       VCPU(vcpu, eoi) = 0;
+       VCPU(vcpu, irr[0]) = 0;
+       VCPU(vcpu, irr[1]) = 0;
+       VCPU(vcpu, irr[2]) = 0;
+       VCPU(vcpu, irr[3]) = 0;
+       VCPU(vcpu, pmv) = 0x10000;
+       VCPU(vcpu, cmcv) = 0x10000;
+       VCPU(vcpu, lrr0) = 0x10000;   /* default reset value? */
+       VCPU(vcpu, lrr1) = 0x10000;   /* default reset value? */
+       update_vhpi(vcpu, NULL_VECTOR);
+       VLSAPIC_XTP(vcpu) = 0x80;       /* disabled */
+
+       for (i = 0; i < 4; i++)
+               VLSAPIC_INSVC(vcpu, i) = 0;
+}
+
+void kvm_init_all_rr(struct kvm_vcpu *vcpu)
+{
+       unsigned long psr;
+
+       local_irq_save(psr);
+
+       /* WARNING: not allow co-exist of both virtual mode and physical
+        * mode in same region
+        */
+
+       vcpu->arch.metaphysical_saved_rr0 = vrrtomrr(VMX(vcpu, vrr[VRN0]));
+       vcpu->arch.metaphysical_saved_rr4 = vrrtomrr(VMX(vcpu, vrr[VRN4]));
+
+       if (is_physical_mode(vcpu)) {
+               if (vcpu->arch.mode_flags & GUEST_PHY_EMUL)
+                       panic_vm(vcpu);
+
+               ia64_set_rr((VRN0 << VRN_SHIFT), vcpu->arch.metaphysical_rr0);
+               ia64_dv_serialize_data();
+               ia64_set_rr((VRN4 << VRN_SHIFT), vcpu->arch.metaphysical_rr4);
+               ia64_dv_serialize_data();
+       } else {
+               ia64_set_rr((VRN0 << VRN_SHIFT),
+                               vcpu->arch.metaphysical_saved_rr0);
+               ia64_dv_serialize_data();
+               ia64_set_rr((VRN4 << VRN_SHIFT),
+                               vcpu->arch.metaphysical_saved_rr4);
+               ia64_dv_serialize_data();
+       }
+       ia64_set_rr((VRN1 << VRN_SHIFT),
+                       vrrtomrr(VMX(vcpu, vrr[VRN1])));
+       ia64_dv_serialize_data();
+       ia64_set_rr((VRN2 << VRN_SHIFT),
+                       vrrtomrr(VMX(vcpu, vrr[VRN2])));
+       ia64_dv_serialize_data();
+       ia64_set_rr((VRN3 << VRN_SHIFT),
+                       vrrtomrr(VMX(vcpu, vrr[VRN3])));
+       ia64_dv_serialize_data();
+       ia64_set_rr((VRN5 << VRN_SHIFT),
+                       vrrtomrr(VMX(vcpu, vrr[VRN5])));
+       ia64_dv_serialize_data();
+       ia64_set_rr((VRN7 << VRN_SHIFT),
+                       vrrtomrr(VMX(vcpu, vrr[VRN7])));
+       ia64_dv_serialize_data();
+       ia64_srlz_d();
+       ia64_set_psr(psr);
+}
+
+int vmm_entry(void)
+{
+       struct kvm_vcpu *v;
+       v = current_vcpu;
+
+       ia64_call_vsa(PAL_VPS_RESTORE, (unsigned long)v->arch.vpd,
+                                               0, 0, 0, 0, 0, 0);
+       kvm_init_vtlb(v);
+       kvm_init_vhpt(v);
+       init_vcpu(v);
+       kvm_init_all_rr(v);
+       vmm_reset_entry();
+
+       return 0;
+}
+
+void panic_vm(struct kvm_vcpu *v)
+{
+       struct exit_ctl_data *p = &v->arch.exit_data;
+
+       p->exit_reason = EXIT_REASON_VM_PANIC;
+       vmm_transition(v);
+       /*Never to return*/
+       while (1);
+}
diff --git a/arch/ia64/kvm/vcpu.h b/arch/ia64/kvm/vcpu.h
new file mode 100644 (file)
index 0000000..b0fcfb6
--- /dev/null
@@ -0,0 +1,740 @@
+/*
+ *  vcpu.h: vcpu routines
+ *     Copyright (c) 2005, Intel Corporation.
+ *     Xuefei Xu (Anthony Xu) (Anthony.xu@intel.com)
+ *     Yaozu Dong (Eddie Dong) (Eddie.dong@intel.com)
+ *
+ *     Copyright (c) 2007, Intel Corporation.
+ *     Xuefei Xu (Anthony Xu) (Anthony.xu@intel.com)
+ *     Xiantao Zhang (xiantao.zhang@intel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+
+#ifndef __KVM_VCPU_H__
+#define __KVM_VCPU_H__
+
+#include <asm/types.h>
+#include <asm/fpu.h>
+#include <asm/processor.h>
+
+#ifndef __ASSEMBLY__
+#include "vti.h"
+
+#include <linux/kvm_host.h>
+#include <linux/spinlock.h>
+
+typedef unsigned long IA64_INST;
+
+typedef union U_IA64_BUNDLE {
+       unsigned long i64[2];
+       struct { unsigned long template:5, slot0:41, slot1a:18,
+               slot1b:23, slot2:41; };
+       /* NOTE: following doesn't work because bitfields can't cross natural
+          size boundaries
+          struct { unsigned long template:5, slot0:41, slot1:41, slot2:41; }; */
+} IA64_BUNDLE;
+
+typedef union U_INST64_A5 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, r1:7, imm7b:7, r3:2, imm5c:5,
+               imm9d:9, s:1, major:4; };
+} INST64_A5;
+
+typedef union U_INST64_B4 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, btype:3, un3:3, p:1, b2:3, un11:11, x6:6,
+               wh:2, d:1, un1:1, major:4; };
+} INST64_B4;
+
+typedef union U_INST64_B8 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, un21:21, x6:6, un4:4, major:4; };
+} INST64_B8;
+
+typedef union U_INST64_B9 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, imm20:20, :1, x6:6, :3, i:1, major:4; };
+} INST64_B9;
+
+typedef union U_INST64_I19 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, imm20:20, :1, x6:6, x3:3, i:1, major:4; };
+} INST64_I19;
+
+typedef union U_INST64_I26 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, :7, r2:7, ar3:7, x6:6, x3:3, :1, major:4; };
+} INST64_I26;
+
+typedef union U_INST64_I27 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, :7, imm:7, ar3:7, x6:6, x3:3, s:1, major:4; };
+} INST64_I27;
+
+typedef union U_INST64_I28 { /* not privileged (mov from AR) */
+       IA64_INST inst;
+       struct { unsigned long qp:6, r1:7, :7, ar3:7, x6:6, x3:3, :1, major:4; };
+} INST64_I28;
+
+typedef union U_INST64_M28 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, :14, r3:7, x6:6, x3:3, :1, major:4; };
+} INST64_M28;
+
+typedef union U_INST64_M29 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, :7, r2:7, ar3:7, x6:6, x3:3, :1, major:4; };
+} INST64_M29;
+
+typedef union U_INST64_M30 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, :7, imm:7, ar3:7, x4:4, x2:2,
+               x3:3, s:1, major:4; };
+} INST64_M30;
+
+typedef union U_INST64_M31 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, r1:7, :7, ar3:7, x6:6, x3:3, :1, major:4; };
+} INST64_M31;
+
+typedef union U_INST64_M32 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, :7, r2:7, cr3:7, x6:6, x3:3, :1, major:4; };
+} INST64_M32;
+
+typedef union U_INST64_M33 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, r1:7, :7, cr3:7, x6:6, x3:3, :1, major:4; };
+} INST64_M33;
+
+typedef union U_INST64_M35 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, :7, r2:7, :7, x6:6, x3:3, :1, major:4; };
+
+} INST64_M35;
+
+typedef union U_INST64_M36 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, r1:7, :14, x6:6, x3:3, :1, major:4; };
+} INST64_M36;
+
+typedef union U_INST64_M37 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, imm20a:20, :1, x4:4, x2:2, x3:3,
+               i:1, major:4; };
+} INST64_M37;
+
+typedef union U_INST64_M41 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, :7, r2:7, :7, x6:6, x3:3, :1, major:4; };
+} INST64_M41;
+
+typedef union U_INST64_M42 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, :7, r2:7, r3:7, x6:6, x3:3, :1, major:4; };
+} INST64_M42;
+
+typedef union U_INST64_M43 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, r1:7, :7, r3:7, x6:6, x3:3, :1, major:4; };
+} INST64_M43;
+
+typedef union U_INST64_M44 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, imm:21, x4:4, i2:2, x3:3, i:1, major:4; };
+} INST64_M44;
+
+typedef union U_INST64_M45 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, :7, r2:7, r3:7, x6:6, x3:3, :1, major:4; };
+} INST64_M45;
+
+typedef union U_INST64_M46 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, r1:7, un7:7, r3:7, x6:6,
+               x3:3, un1:1, major:4; };
+} INST64_M46;
+
+typedef union U_INST64_M47 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, un14:14, r3:7, x6:6, x3:3, un1:1, major:4; };
+} INST64_M47;
+
+typedef union U_INST64_M1{
+       IA64_INST inst;
+       struct { unsigned long qp:6, r1:7, un7:7, r3:7, x:1, hint:2,
+               x6:6, m:1, major:4; };
+} INST64_M1;
+
+typedef union U_INST64_M2{
+       IA64_INST inst;
+       struct { unsigned long qp:6, r1:7, r2:7, r3:7, x:1, hint:2,
+               x6:6, m:1, major:4; };
+} INST64_M2;
+
+typedef union U_INST64_M3{
+       IA64_INST inst;
+       struct { unsigned long qp:6, r1:7, imm7:7, r3:7, i:1, hint:2,
+               x6:6, s:1, major:4; };
+} INST64_M3;
+
+typedef union U_INST64_M4 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, un7:7, r2:7, r3:7, x:1, hint:2,
+               x6:6, m:1, major:4; };
+} INST64_M4;
+
+typedef union U_INST64_M5 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, imm7:7, r2:7, r3:7, i:1, hint:2,
+               x6:6, s:1, major:4; };
+} INST64_M5;
+
+typedef union U_INST64_M6 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, f1:7, un7:7, r3:7, x:1, hint:2,
+               x6:6, m:1, major:4; };
+} INST64_M6;
+
+typedef union U_INST64_M9 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, :7, f2:7, r3:7, x:1, hint:2,
+               x6:6, m:1, major:4; };
+} INST64_M9;
+
+typedef union U_INST64_M10 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, imm7:7, f2:7, r3:7, i:1, hint:2,
+               x6:6, s:1, major:4; };
+} INST64_M10;
+
+typedef union U_INST64_M12 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, f1:7, f2:7, r3:7, x:1, hint:2,
+               x6:6, m:1, major:4; };
+} INST64_M12;
+
+typedef union U_INST64_M15 {
+       IA64_INST inst;
+       struct { unsigned long qp:6, :7, imm7:7, r3:7, i:1, hint:2,
+               x6:6, s:1, major:4; };
+} INST64_M15;
+
+typedef union U_INST64 {
+       IA64_INST inst;
+       struct { unsigned long :37, major:4; } generic;
+       INST64_A5 A5;   /* used in build_hypercall_bundle only */
+       INST64_B4 B4;   /* used in build_hypercall_bundle only */
+       INST64_B8 B8;   /* rfi, bsw.[01] */
+       INST64_B9 B9;   /* break.b */
+       INST64_I19 I19; /* used in build_hypercall_bundle only */
+       INST64_I26 I26; /* mov register to ar (I unit) */
+       INST64_I27 I27; /* mov immediate to ar (I unit) */
+       INST64_I28 I28; /* mov from ar (I unit) */
+       INST64_M1  M1;  /* ld integer */
+       INST64_M2  M2;
+       INST64_M3  M3;
+       INST64_M4  M4;  /* st integer */
+       INST64_M5  M5;
+       INST64_M6  M6;  /* ldfd floating pointer                */
+       INST64_M9  M9;  /* stfd floating pointer                */
+       INST64_M10 M10; /* stfd floating pointer                */
+       INST64_M12 M12;     /* ldfd pair floating pointer               */
+       INST64_M15 M15; /* lfetch + imm update                  */
+       INST64_M28 M28; /* purge translation cache entry        */
+       INST64_M29 M29; /* mov register to ar (M unit)          */
+       INST64_M30 M30; /* mov immediate to ar (M unit)         */
+       INST64_M31 M31; /* mov from ar (M unit)                 */
+       INST64_M32 M32; /* mov reg to cr                        */
+       INST64_M33 M33; /* mov from cr                          */
+       INST64_M35 M35; /* mov to psr                           */
+       INST64_M36 M36; /* mov from psr                         */
+       INST64_M37 M37; /* break.m                              */
+       INST64_M41 M41; /* translation cache insert             */
+       INST64_M42 M42; /* mov to indirect reg/translation reg insert*/
+       INST64_M43 M43; /* mov from indirect reg                */
+       INST64_M44 M44; /* set/reset system mask                */
+       INST64_M45 M45; /* translation purge                    */
+       INST64_M46 M46; /* translation access (tpa,tak)         */
+       INST64_M47 M47; /* purge translation entry              */
+} INST64;
+
+#define MASK_41 ((unsigned long)0x1ffffffffff)
+
+/* Virtual address memory attributes encoding */
+#define VA_MATTR_WB         0x0
+#define VA_MATTR_UC         0x4
+#define VA_MATTR_UCE        0x5
+#define VA_MATTR_WC         0x6
+#define VA_MATTR_NATPAGE    0x7
+
+#define PMASK(size)         (~((size) - 1))
+#define PSIZE(size)         (1UL<<(size))
+#define CLEARLSB(ppn, nbits)    (((ppn) >> (nbits)) << (nbits))
+#define PAGEALIGN(va, ps)      CLEARLSB(va, ps)
+#define PAGE_FLAGS_RV_MASK   (0x2|(0x3UL<<50)|(((1UL<<11)-1)<<53))
+#define _PAGE_MA_ST     (0x1 <<  2) /* is reserved for software use */
+
+#define ARCH_PAGE_SHIFT   12
+
+#define INVALID_TI_TAG (1UL << 63)
+
+#define VTLB_PTE_P_BIT      0
+#define VTLB_PTE_IO_BIT     60
+#define VTLB_PTE_IO         (1UL<<VTLB_PTE_IO_BIT)
+#define VTLB_PTE_P          (1UL<<VTLB_PTE_P_BIT)
+
+#define vcpu_quick_region_check(_tr_regions,_ifa)              \
+       (_tr_regions & (1 << ((unsigned long)_ifa >> 61)))
+
+#define vcpu_quick_region_set(_tr_regions,_ifa)             \
+       do {_tr_regions |= (1 << ((unsigned long)_ifa >> 61)); } while (0)
+
+static inline void vcpu_set_tr(struct thash_data *trp, u64 pte, u64 itir,
+               u64 va, u64 rid)
+{
+       trp->page_flags = pte;
+       trp->itir = itir;
+       trp->vadr = va;
+       trp->rid = rid;
+}
+
+extern u64 kvm_lookup_mpa(u64 gpfn);
+extern u64 kvm_gpa_to_mpa(u64 gpa);
+
+/* Return I/O type if trye */
+#define __gpfn_is_io(gpfn)                     \
+       ({                                              \
+        u64 pte, ret = 0;                      \
+        pte = kvm_lookup_mpa(gpfn);            \
+        if (!(pte & GPFN_INV_MASK))            \
+        ret = pte & GPFN_IO_MASK;      \
+        ret;                                   \
+        })
+
+#endif
+
+#define IA64_NO_FAULT  0
+#define IA64_FAULT     1
+
+#define VMM_RBS_OFFSET  ((VMM_TASK_SIZE + 15) & ~15)
+
+#define SW_BAD  0   /* Bad mode transitition */
+#define SW_V2P  1   /* Physical emulatino is activated */
+#define SW_P2V  2   /* Exit physical mode emulation */
+#define SW_SELF 3   /* No mode transition */
+#define SW_NOP  4   /* Mode transition, but without action required */
+
+#define GUEST_IN_PHY    0x1
+#define GUEST_PHY_EMUL  0x2
+
+#define current_vcpu ((struct kvm_vcpu *) ia64_getreg(_IA64_REG_TP))
+
+#define VRN_SHIFT      61
+#define VRN_MASK       0xe000000000000000
+#define VRN0           0x0UL
+#define VRN1           0x1UL
+#define VRN2           0x2UL
+#define VRN3           0x3UL
+#define VRN4           0x4UL
+#define VRN5           0x5UL
+#define VRN6           0x6UL
+#define VRN7           0x7UL
+
+#define IRQ_NO_MASKED         0
+#define IRQ_MASKED_BY_VTPR    1
+#define IRQ_MASKED_BY_INSVC   2   /* masked by inservice IRQ */
+
+#define PTA_BASE_SHIFT      15
+
+#define IA64_PSR_VM_BIT     46
+#define IA64_PSR_VM (__IA64_UL(1) << IA64_PSR_VM_BIT)
+
+/* Interruption Function State */
+#define IA64_IFS_V_BIT      63
+#define IA64_IFS_V  (__IA64_UL(1) << IA64_IFS_V_BIT)
+
+#define PHY_PAGE_UC (_PAGE_A|_PAGE_D|_PAGE_P|_PAGE_MA_UC|_PAGE_AR_RWX)
+#define PHY_PAGE_WB (_PAGE_A|_PAGE_D|_PAGE_P|_PAGE_MA_WB|_PAGE_AR_RWX)
+
+#ifndef __ASSEMBLY__
+
+#include <asm/gcc_intrin.h>
+
+#define is_physical_mode(v)            \
+       ((v->arch.mode_flags) & GUEST_IN_PHY)
+
+#define is_virtual_mode(v)     \
+       (!is_physical_mode(v))
+
+#define MODE_IND(psr)  \
+       (((psr).it << 2) + ((psr).dt << 1) + (psr).rt)
+
+#define _vmm_raw_spin_lock(x)                                          \
+       do {                                                            \
+               __u32 *ia64_spinlock_ptr = (__u32 *) (x);               \
+               __u64 ia64_spinlock_val;                                \
+               ia64_spinlock_val = ia64_cmpxchg4_acq(ia64_spinlock_ptr, 1, 0);\
+               if (unlikely(ia64_spinlock_val)) {                      \
+                       do {                                            \
+                               while (*ia64_spinlock_ptr)              \
+                               ia64_barrier();                         \
+                               ia64_spinlock_val =                     \
+                               ia64_cmpxchg4_acq(ia64_spinlock_ptr, 1, 0);\
+                       } while (ia64_spinlock_val);                    \
+               }                                                       \
+       } while (0)
+
+#define _vmm_raw_spin_unlock(x)                                \
+       do { barrier();                         \
+               ((spinlock_t *)x)->raw_lock.lock = 0; } \
+while (0)
+
+void vmm_spin_lock(spinlock_t *lock);
+void vmm_spin_unlock(spinlock_t *lock);
+enum {
+       I_TLB = 1,
+       D_TLB = 2
+};
+
+union kvm_va {
+       struct {
+               unsigned long off : 60;         /* intra-region offset */
+               unsigned long reg :  4;         /* region number */
+       } f;
+       unsigned long l;
+       void *p;
+};
+
+#define __kvm_pa(x)     ({union kvm_va _v; _v.l = (long) (x);          \
+                                               _v.f.reg = 0; _v.l; })
+#define __kvm_va(x)     ({union kvm_va _v; _v.l = (long) (x);          \
+                               _v.f.reg = -1; _v.p; })
+
+#define _REGION_ID(x)           ({union ia64_rr _v; _v.val = (long)(x); \
+                                               _v.rid; })
+#define _REGION_PAGE_SIZE(x)    ({union ia64_rr _v; _v.val = (long)(x); \
+                                               _v.ps; })
+#define _REGION_HW_WALKER(x)    ({union ia64_rr _v; _v.val = (long)(x);        \
+                                               _v.ve; })
+
+enum vhpt_ref{ DATA_REF, NA_REF, INST_REF, RSE_REF };
+enum tlb_miss_type { INSTRUCTION, DATA, REGISTER };
+
+#define VCPU(_v, _x) ((_v)->arch.vpd->_x)
+#define VMX(_v, _x)  ((_v)->arch._x)
+
+#define VLSAPIC_INSVC(vcpu, i) ((vcpu)->arch.insvc[i])
+#define VLSAPIC_XTP(_v)        VMX(_v, xtp)
+
+static inline unsigned long itir_ps(unsigned long itir)
+{
+       return ((itir >> 2) & 0x3f);
+}
+
+
+/**************************************************************************
+  VCPU control register access routines
+ **************************************************************************/
+
+static inline u64 vcpu_get_itir(struct kvm_vcpu *vcpu)
+{
+       return ((u64)VCPU(vcpu, itir));
+}
+
+static inline void vcpu_set_itir(struct kvm_vcpu *vcpu, u64 val)
+{
+       VCPU(vcpu, itir) = val;
+}
+
+static inline u64 vcpu_get_ifa(struct kvm_vcpu *vcpu)
+{
+       return ((u64)VCPU(vcpu, ifa));
+}
+
+static inline void vcpu_set_ifa(struct kvm_vcpu *vcpu, u64 val)
+{
+       VCPU(vcpu, ifa) = val;
+}
+
+static inline u64 vcpu_get_iva(struct kvm_vcpu *vcpu)
+{
+       return ((u64)VCPU(vcpu, iva));
+}
+
+static inline u64 vcpu_get_pta(struct kvm_vcpu *vcpu)
+{
+       return ((u64)VCPU(vcpu, pta));
+}
+
+static inline u64 vcpu_get_lid(struct kvm_vcpu *vcpu)
+{
+       return ((u64)VCPU(vcpu, lid));
+}
+
+static inline u64 vcpu_get_tpr(struct kvm_vcpu *vcpu)
+{
+       return ((u64)VCPU(vcpu, tpr));
+}
+
+static inline u64 vcpu_get_eoi(struct kvm_vcpu *vcpu)
+{
+       return (0UL);           /*reads of eoi always return 0 */
+}
+
+static inline u64 vcpu_get_irr0(struct kvm_vcpu *vcpu)
+{
+       return ((u64)VCPU(vcpu, irr[0]));
+}
+
+static inline u64 vcpu_get_irr1(struct kvm_vcpu *vcpu)
+{
+       return ((u64)VCPU(vcpu, irr[1]));
+}
+
+static inline u64 vcpu_get_irr2(struct kvm_vcpu *vcpu)
+{
+       return ((u64)VCPU(vcpu, irr[2]));
+}
+
+static inline u64 vcpu_get_irr3(struct kvm_vcpu *vcpu)
+{
+       return ((u64)VCPU(vcpu, irr[3]));
+}
+
+static inline void vcpu_set_dcr(struct kvm_vcpu *vcpu, u64 val)
+{
+       ia64_setreg(_IA64_REG_CR_DCR, val);
+}
+
+static inline void vcpu_set_isr(struct kvm_vcpu *vcpu, u64 val)
+{
+       VCPU(vcpu, isr) = val;
+}
+
+static inline void vcpu_set_lid(struct kvm_vcpu *vcpu, u64 val)
+{
+       VCPU(vcpu, lid) = val;
+}
+
+static inline void vcpu_set_ipsr(struct kvm_vcpu *vcpu, u64 val)
+{
+       VCPU(vcpu, ipsr) = val;
+}
+
+static inline void vcpu_set_iip(struct kvm_vcpu *vcpu, u64 val)
+{
+       VCPU(vcpu, iip) = val;
+}
+
+static inline void vcpu_set_ifs(struct kvm_vcpu *vcpu, u64 val)
+{
+       VCPU(vcpu, ifs) = val;
+}
+
+static inline void vcpu_set_iipa(struct kvm_vcpu *vcpu, u64 val)
+{
+       VCPU(vcpu, iipa) = val;
+}
+
+static inline void vcpu_set_iha(struct kvm_vcpu *vcpu, u64 val)
+{
+       VCPU(vcpu, iha) = val;
+}
+
+
+static inline u64 vcpu_get_rr(struct kvm_vcpu *vcpu, u64 reg)
+{
+       return vcpu->arch.vrr[reg>>61];
+}
+
+/**************************************************************************
+  VCPU debug breakpoint register access routines
+ **************************************************************************/
+
+static inline void vcpu_set_dbr(struct kvm_vcpu *vcpu, u64 reg, u64 val)
+{
+       __ia64_set_dbr(reg, val);
+}
+
+static inline void vcpu_set_ibr(struct kvm_vcpu *vcpu, u64 reg, u64 val)
+{
+       ia64_set_ibr(reg, val);
+}
+
+static inline u64 vcpu_get_dbr(struct kvm_vcpu *vcpu, u64 reg)
+{
+       return ((u64)__ia64_get_dbr(reg));
+}
+
+static inline u64 vcpu_get_ibr(struct kvm_vcpu *vcpu, u64 reg)
+{
+       return ((u64)ia64_get_ibr(reg));
+}
+
+/**************************************************************************
+  VCPU performance monitor register access routines
+ **************************************************************************/
+static inline void vcpu_set_pmc(struct kvm_vcpu *vcpu, u64 reg, u64 val)
+{
+       /* NOTE: Writes to unimplemented PMC registers are discarded */
+       ia64_set_pmc(reg, val);
+}
+
+static inline void vcpu_set_pmd(struct kvm_vcpu *vcpu, u64 reg, u64 val)
+{
+       /* NOTE: Writes to unimplemented PMD registers are discarded */
+       ia64_set_pmd(reg, val);
+}
+
+static inline u64 vcpu_get_pmc(struct kvm_vcpu *vcpu, u64 reg)
+{
+       /* NOTE: Reads from unimplemented PMC registers return zero */
+       return ((u64)ia64_get_pmc(reg));
+}
+
+static inline u64 vcpu_get_pmd(struct kvm_vcpu *vcpu, u64 reg)
+{
+       /* NOTE: Reads from unimplemented PMD registers return zero */
+       return ((u64)ia64_get_pmd(reg));
+}
+
+static inline unsigned long vrrtomrr(unsigned long val)
+{
+       union ia64_rr rr;
+       rr.val = val;
+       rr.rid = (rr.rid << 4) | 0xe;
+       if (rr.ps > PAGE_SHIFT)
+               rr.ps = PAGE_SHIFT;
+       rr.ve = 1;
+       return rr.val;
+}
+
+
+static inline int highest_bits(int *dat)
+{
+       u32  bits, bitnum;
+       int i;
+
+       /* loop for all 256 bits */
+       for (i = 7; i >= 0 ; i--) {
+               bits = dat[i];
+               if (bits) {
+                       bitnum = fls(bits);
+                       return i * 32 + bitnum - 1;
+               }
+       }
+       return NULL_VECTOR;
+}
+
+/*
+ * The pending irq is higher than the inservice one.
+ *
+ */
+static inline int is_higher_irq(int pending, int inservice)
+{
+       return ((pending > inservice)
+                       || ((pending != NULL_VECTOR)
+                               && (inservice == NULL_VECTOR)));
+}
+
+static inline int is_higher_class(int pending, int mic)
+{
+       return ((pending >> 4) > mic);
+}
+
+/*
+ * Return 0-255 for pending irq.
+ *        NULL_VECTOR: when no pending.
+ */
+static inline int highest_pending_irq(struct kvm_vcpu *vcpu)
+{
+       if (VCPU(vcpu, irr[0]) & (1UL<<NMI_VECTOR))
+               return NMI_VECTOR;
+       if (VCPU(vcpu, irr[0]) & (1UL<<ExtINT_VECTOR))
+               return ExtINT_VECTOR;
+
+       return highest_bits((int *)&VCPU(vcpu, irr[0]));
+}
+
+static inline int highest_inservice_irq(struct kvm_vcpu *vcpu)
+{
+       if (VMX(vcpu, insvc[0]) & (1UL<<NMI_VECTOR))
+               return NMI_VECTOR;
+       if (VMX(vcpu, insvc[0]) & (1UL<<ExtINT_VECTOR))
+               return ExtINT_VECTOR;
+
+       return highest_bits((int *)&(VMX(vcpu, insvc[0])));
+}
+
+extern void vcpu_get_fpreg(struct kvm_vcpu *vcpu, u64 reg,
+                                       struct ia64_fpreg *val);
+extern void vcpu_set_fpreg(struct kvm_vcpu *vcpu, u64 reg,
+                                       struct ia64_fpreg *val);
+extern u64 vcpu_get_gr(struct kvm_vcpu *vcpu, u64 reg);
+extern void vcpu_set_gr(struct kvm_vcpu *vcpu, u64 reg, u64 val, int nat);
+extern u64 vcpu_get_psr(struct kvm_vcpu *vcpu);
+extern void vcpu_set_psr(struct kvm_vcpu *vcpu, u64 val);
+extern u64 vcpu_thash(struct kvm_vcpu *vcpu, u64 vadr);
+extern void vcpu_bsw0(struct kvm_vcpu *vcpu);
+extern void thash_vhpt_insert(struct kvm_vcpu *v, u64 pte,
+                                       u64 itir, u64 va, int type);
+extern struct thash_data *vhpt_lookup(u64 va);
+extern u64 guest_vhpt_lookup(u64 iha, u64 *pte);
+extern void thash_purge_entries(struct kvm_vcpu *v, u64 va, u64 ps);
+extern void thash_purge_entries_remote(struct kvm_vcpu *v, u64 va, u64 ps);
+extern u64 translate_phy_pte(u64 *pte, u64 itir, u64 va);
+extern int thash_purge_and_insert(struct kvm_vcpu *v, u64 pte,
+               u64 itir, u64 ifa, int type);
+extern void thash_purge_all(struct kvm_vcpu *v);
+extern struct thash_data *vtlb_lookup(struct kvm_vcpu *v,
+                                               u64 va, int is_data);
+extern int vtr_find_overlap(struct kvm_vcpu *vcpu, u64 va,
+                                               u64 ps, int is_data);
+
+extern void vcpu_increment_iip(struct kvm_vcpu *v);
+extern void vcpu_decrement_iip(struct kvm_vcpu *vcpu);
+extern void vcpu_pend_interrupt(struct kvm_vcpu *vcpu, u8 vec);
+extern void vcpu_unpend_interrupt(struct kvm_vcpu *vcpu, u8 vec);
+extern void data_page_not_present(struct kvm_vcpu *vcpu, u64 vadr);
+extern void dnat_page_consumption(struct kvm_vcpu *vcpu, u64 vadr);
+extern void alt_dtlb(struct kvm_vcpu *vcpu, u64 vadr);
+extern void nested_dtlb(struct kvm_vcpu *vcpu);
+extern void dvhpt_fault(struct kvm_vcpu *vcpu, u64 vadr);
+extern int vhpt_enabled(struct kvm_vcpu *vcpu, u64 vadr, enum vhpt_ref ref);
+
+extern void update_vhpi(struct kvm_vcpu *vcpu, int vec);
+extern int irq_masked(struct kvm_vcpu *vcpu, int h_pending, int h_inservice);
+
+extern int fetch_code(struct kvm_vcpu *vcpu, u64 gip, IA64_BUNDLE *pbundle);
+extern void emulate_io_inst(struct kvm_vcpu *vcpu, u64 padr, u64 ma);
+extern void vmm_transition(struct kvm_vcpu *vcpu);
+extern void vmm_trampoline(union context *from, union context *to);
+extern int vmm_entry(void);
+extern  u64 vcpu_get_itc(struct kvm_vcpu *vcpu);
+
+extern void vmm_reset_entry(void);
+void kvm_init_vtlb(struct kvm_vcpu *v);
+void kvm_init_vhpt(struct kvm_vcpu *v);
+void thash_init(struct thash_cb *hcb, u64 sz);
+
+void panic_vm(struct kvm_vcpu *v);
+
+extern u64 ia64_call_vsa(u64 proc, u64 arg1, u64 arg2, u64 arg3,
+               u64 arg4, u64 arg5, u64 arg6, u64 arg7);
+#endif
+#endif /* __VCPU_H__ */
diff --git a/arch/ia64/kvm/vmm.c b/arch/ia64/kvm/vmm.c
new file mode 100644 (file)
index 0000000..2275bf4
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * vmm.c: vmm module interface with kvm module
+ *
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ *  Xiantao Zhang (xiantao.zhang@intel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+
+#include<linux/module.h>
+#include<asm/fpswa.h>
+
+#include "vcpu.h"
+
+MODULE_AUTHOR("Intel");
+MODULE_LICENSE("GPL");
+
+extern char kvm_ia64_ivt;
+extern fpswa_interface_t *vmm_fpswa_interface;
+
+struct kvm_vmm_info vmm_info = {
+       .module      = THIS_MODULE,
+       .vmm_entry   = vmm_entry,
+       .tramp_entry = vmm_trampoline,
+       .vmm_ivt     = (unsigned long)&kvm_ia64_ivt,
+};
+
+static int __init  kvm_vmm_init(void)
+{
+
+       vmm_fpswa_interface = fpswa_interface;
+
+       /*Register vmm data to kvm side*/
+       return kvm_init(&vmm_info, 1024, THIS_MODULE);
+}
+
+static void __exit kvm_vmm_exit(void)
+{
+       kvm_exit();
+       return ;
+}
+
+void vmm_spin_lock(spinlock_t *lock)
+{
+       _vmm_raw_spin_lock(lock);
+}
+
+void vmm_spin_unlock(spinlock_t *lock)
+{
+       _vmm_raw_spin_unlock(lock);
+}
+module_init(kvm_vmm_init)
+module_exit(kvm_vmm_exit)
diff --git a/arch/ia64/kvm/vmm_ivt.S b/arch/ia64/kvm/vmm_ivt.S
new file mode 100644 (file)
index 0000000..3ee5f48
--- /dev/null
@@ -0,0 +1,1424 @@
+/*
+ * /ia64/kvm_ivt.S
+ *
+ * Copyright (C) 1998-2001, 2003 Hewlett-Packard Co
+ *      Stephane Eranian <eranian@hpl.hp.com>
+ *      David Mosberger <davidm@hpl.hp.com>
+ * Copyright (C) 2000, 2002-2003 Intel Co
+ *      Asit Mallick <asit.k.mallick@intel.com>
+ *      Suresh Siddha <suresh.b.siddha@intel.com>
+ *      Kenneth Chen <kenneth.w.chen@intel.com>
+ *      Fenghua Yu <fenghua.yu@intel.com>
+ *
+ *
+ * 00/08/23 Asit Mallick <asit.k.mallick@intel.com> TLB handling
+ * for SMP
+ * 00/12/20 David Mosberger-Tang <davidm@hpl.hp.com> DTLB/ITLB
+ * handler now uses virtual PT.
+ *
+ * 07/6/20 Xuefei Xu  (Anthony Xu) (anthony.xu@intel.com)
+ *              Supporting Intel virtualization architecture
+ *
+ */
+
+/*
+ * This file defines the interruption vector table used by the CPU.
+ * It does not include one entry per possible cause of interruption.
+ *
+ * The first 20 entries of the table contain 64 bundles each while the
+ * remaining 48 entries contain only 16 bundles each.
+ *
+ * The 64 bundles are used to allow inlining the whole handler for
+ * critical
+ * interruptions like TLB misses.
+ *
+ *  For each entry, the comment is as follows:
+ *
+ *              // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss
+ *              (12,51)
+ *  entry offset ----/     /         /                  /
+ *  /
+ *  entry number ---------/         /                  /
+ *  /
+ *  size of the entry -------------/                  /
+ *  /
+ *  vector name -------------------------------------/
+ *  /
+ *  interruptions triggering this vector
+ *  ----------------------/
+ *
+ * The table is 32KB in size and must be aligned on 32KB
+ * boundary.
+ * (The CPU ignores the 15 lower bits of the address)
+ *
+ * Table is based upon EAS2.6 (Oct 1999)
+ */
+
+
+#include <asm/asmmacro.h>
+#include <asm/cache.h>
+#include <asm/pgtable.h>
+
+#include "asm-offsets.h"
+#include "vcpu.h"
+#include "kvm_minstate.h"
+#include "vti.h"
+
+#if 1
+# define PSR_DEFAULT_BITS   psr.ac
+#else
+# define PSR_DEFAULT_BITS   0
+#endif
+
+
+#define KVM_FAULT(n)    \
+    kvm_fault_##n:;          \
+    mov r19=n;;          \
+    br.sptk.many kvm_fault_##n;         \
+    ;;                  \
+
+
+#define KVM_REFLECT(n)    \
+    mov r31=pr;           \
+    mov r19=n;       /* prepare to save predicates */ \
+    mov r29=cr.ipsr;      \
+    ;;      \
+    tbit.z p6,p7=r29,IA64_PSR_VM_BIT;       \
+(p7)br.sptk.many kvm_dispatch_reflection;        \
+    br.sptk.many kvm_panic;      \
+
+
+GLOBAL_ENTRY(kvm_panic)
+    br.sptk.many kvm_panic
+    ;;
+END(kvm_panic)
+
+
+
+
+
+    .section .text.ivt,"ax"
+
+    .align 32768    // align on 32KB boundary
+    .global kvm_ia64_ivt
+kvm_ia64_ivt:
+///////////////////////////////////////////////////////////////
+// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)
+ENTRY(kvm_vhpt_miss)
+    KVM_FAULT(0)
+END(kvm_vhpt_miss)
+
+
+    .org kvm_ia64_ivt+0x400
+////////////////////////////////////////////////////////////////
+// 0x0400 Entry 1 (size 64 bundles) ITLB (21)
+ENTRY(kvm_itlb_miss)
+    mov r31 = pr
+    mov r29=cr.ipsr;
+    ;;
+    tbit.z p6,p7=r29,IA64_PSR_VM_BIT;
+    (p6) br.sptk kvm_alt_itlb_miss
+    mov r19 = 1
+    br.sptk kvm_itlb_miss_dispatch
+    KVM_FAULT(1);
+END(kvm_itlb_miss)
+
+    .org kvm_ia64_ivt+0x0800
+//////////////////////////////////////////////////////////////////
+// 0x0800 Entry 2 (size 64 bundles) DTLB (9,48)
+ENTRY(kvm_dtlb_miss)
+    mov r31 = pr
+    mov r29=cr.ipsr;
+    ;;
+    tbit.z p6,p7=r29,IA64_PSR_VM_BIT;
+(p6)br.sptk kvm_alt_dtlb_miss
+    br.sptk kvm_dtlb_miss_dispatch
+END(kvm_dtlb_miss)
+
+     .org kvm_ia64_ivt+0x0c00
+////////////////////////////////////////////////////////////////////
+// 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19)
+ENTRY(kvm_alt_itlb_miss)
+    mov r16=cr.ifa    // get address that caused the TLB miss
+    ;;
+    movl r17=PAGE_KERNEL
+    mov r24=cr.ipsr
+    movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
+    ;;
+    and r19=r19,r16     // clear ed, reserved bits, and PTE control bits
+    ;;
+    or r19=r17,r19      // insert PTE control bits into r19
+    ;;
+    movl r20=IA64_GRANULE_SHIFT<<2
+    ;;
+    mov cr.itir=r20
+    ;;
+    itc.i r19          // insert the TLB entry
+    mov pr=r31,-1
+    rfi
+END(kvm_alt_itlb_miss)
+
+    .org kvm_ia64_ivt+0x1000
+/////////////////////////////////////////////////////////////////////
+// 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46)
+ENTRY(kvm_alt_dtlb_miss)
+    mov r16=cr.ifa             // get address that caused the TLB miss
+    ;;
+    movl r17=PAGE_KERNEL
+    movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
+    mov r24=cr.ipsr
+    ;;
+    and r19=r19,r16     // clear ed, reserved bits, and PTE control bits
+    ;;
+    or r19=r19,r17     // insert PTE control bits into r19
+    ;;
+    movl r20=IA64_GRANULE_SHIFT<<2
+    ;;
+    mov cr.itir=r20
+    ;;
+    itc.d r19          // insert the TLB entry
+    mov pr=r31,-1
+    rfi
+END(kvm_alt_dtlb_miss)
+
+    .org kvm_ia64_ivt+0x1400
+//////////////////////////////////////////////////////////////////////
+// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)
+ENTRY(kvm_nested_dtlb_miss)
+    KVM_FAULT(5)
+END(kvm_nested_dtlb_miss)
+
+    .org kvm_ia64_ivt+0x1800
+/////////////////////////////////////////////////////////////////////
+// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)
+ENTRY(kvm_ikey_miss)
+    KVM_REFLECT(6)
+END(kvm_ikey_miss)
+
+    .org kvm_ia64_ivt+0x1c00
+/////////////////////////////////////////////////////////////////////
+// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
+ENTRY(kvm_dkey_miss)
+    KVM_REFLECT(7)
+END(kvm_dkey_miss)
+
+    .org kvm_ia64_ivt+0x2000
+////////////////////////////////////////////////////////////////////
+// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)
+ENTRY(kvm_dirty_bit)
+    KVM_REFLECT(8)
+END(kvm_dirty_bit)
+
+    .org kvm_ia64_ivt+0x2400
+////////////////////////////////////////////////////////////////////
+// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)
+ENTRY(kvm_iaccess_bit)
+    KVM_REFLECT(9)
+END(kvm_iaccess_bit)
+
+    .org kvm_ia64_ivt+0x2800
+///////////////////////////////////////////////////////////////////
+// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)
+ENTRY(kvm_daccess_bit)
+    KVM_REFLECT(10)
+END(kvm_daccess_bit)
+
+    .org kvm_ia64_ivt+0x2c00
+/////////////////////////////////////////////////////////////////
+// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)
+ENTRY(kvm_break_fault)
+    mov r31=pr
+    mov r19=11
+    mov r29=cr.ipsr
+    ;;
+    KVM_SAVE_MIN_WITH_COVER_R19
+    ;;
+    alloc r14=ar.pfs,0,0,4,0 // now it's safe (must be first in insn group!)
+    mov out0=cr.ifa
+    mov out2=cr.isr     // FIXME: pity to make this slow access twice
+    mov out3=cr.iim     // FIXME: pity to make this slow access twice
+    adds r3=8,r2                // set up second base pointer
+    ;;
+    ssm psr.ic
+    ;;
+    srlz.i                  // guarantee that interruption collection is on
+    ;;
+    //(p15)ssm psr.i               // restore psr.i
+    addl r14=@gprel(ia64_leave_hypervisor),gp
+    ;;
+    KVM_SAVE_REST
+    mov rp=r14
+    ;;
+    adds out1=16,sp
+    br.call.sptk.many b6=kvm_ia64_handle_break
+    ;;
+END(kvm_break_fault)
+
+    .org kvm_ia64_ivt+0x3000
+/////////////////////////////////////////////////////////////////
+// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)
+ENTRY(kvm_interrupt)
+    mov r31=pr         // prepare to save predicates
+    mov r19=12
+    mov r29=cr.ipsr
+    ;;
+    tbit.z p6,p7=r29,IA64_PSR_VM_BIT
+    tbit.z p0,p15=r29,IA64_PSR_I_BIT
+    ;;
+(p7) br.sptk kvm_dispatch_interrupt
+    ;;
+    mov r27=ar.rsc             /* M */
+    mov r20=r1                 /* A */
+    mov r25=ar.unat            /* M */
+    mov r26=ar.pfs             /* I */
+    mov r28=cr.iip             /* M */
+    cover                      /* B (or nothing) */
+    ;;
+    mov r1=sp
+    ;;
+    invala                     /* M */
+    mov r30=cr.ifs
+    ;;
+    addl r1=-VMM_PT_REGS_SIZE,r1
+    ;;
+    adds r17=2*L1_CACHE_BYTES,r1       /* really: biggest cache-line size */
+    adds r16=PT(CR_IPSR),r1
+    ;;
+    lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES
+    st8 [r16]=r29                      /* save cr.ipsr */
+    ;;
+    lfetch.fault.excl.nt1 [r17]
+    mov r29=b0
+    ;;
+    adds r16=PT(R8),r1         /* initialize first base pointer */
+    adds r17=PT(R9),r1         /* initialize second base pointer */
+    mov r18=r0                 /* make sure r18 isn't NaT */
+    ;;
+.mem.offset 0,0; st8.spill [r16]=r8,16
+.mem.offset 8,0; st8.spill [r17]=r9,16
+        ;;
+.mem.offset 0,0; st8.spill [r16]=r10,24
+.mem.offset 8,0; st8.spill [r17]=r11,24
+        ;;
+    st8 [r16]=r28,16           /* save cr.iip */
+    st8 [r17]=r30,16           /* save cr.ifs */
+    mov r8=ar.fpsr             /* M */
+    mov r9=ar.csd
+    mov r10=ar.ssd
+    movl r11=FPSR_DEFAULT      /* L-unit */
+    ;;
+    st8 [r16]=r25,16           /* save ar.unat */
+    st8 [r17]=r26,16           /* save ar.pfs */
+    shl r18=r18,16             /* compute ar.rsc to be used for "loadrs" */
+    ;;
+    st8 [r16]=r27,16           /* save ar.rsc */
+    adds r17=16,r17            /* skip over ar_rnat field */
+    ;;
+    st8 [r17]=r31,16           /* save predicates */
+    adds r16=16,r16            /* skip over ar_bspstore field */
+    ;;
+    st8 [r16]=r29,16           /* save b0 */
+    st8 [r17]=r18,16           /* save ar.rsc value for "loadrs" */
+    ;;
+.mem.offset 0,0; st8.spill [r16]=r20,16    /* save original r1 */
+.mem.offset 8,0; st8.spill [r17]=r12,16
+    adds r12=-16,r1
+    /* switch to kernel memory stack (with 16 bytes of scratch) */
+    ;;
+.mem.offset 0,0; st8.spill [r16]=r13,16
+.mem.offset 8,0; st8.spill [r17]=r8,16 /* save ar.fpsr */
+    ;;
+.mem.offset 0,0; st8.spill [r16]=r15,16
+.mem.offset 8,0; st8.spill [r17]=r14,16
+    dep r14=-1,r0,60,4
+    ;;
+.mem.offset 0,0; st8.spill [r16]=r2,16
+.mem.offset 8,0; st8.spill [r17]=r3,16
+    adds r2=VMM_PT_REGS_R16_OFFSET,r1
+    adds r14 = VMM_VCPU_GP_OFFSET,r13
+    ;;
+    mov r8=ar.ccv
+    ld8 r14 = [r14]
+    ;;
+    mov r1=r14       /* establish kernel global pointer */
+    ;;                                          \
+    bsw.1
+    ;;
+    alloc r14=ar.pfs,0,0,1,0   // must be first in an insn group
+    mov out0=r13
+    ;;
+    ssm psr.ic
+    ;;
+    srlz.i
+    ;;
+    //(p15) ssm psr.i
+    adds r3=8,r2               // set up second base pointer for SAVE_REST
+    srlz.i                     // ensure everybody knows psr.ic is back on
+    ;;
+.mem.offset 0,0; st8.spill [r2]=r16,16
+.mem.offset 8,0; st8.spill [r3]=r17,16
+    ;;
+.mem.offset 0,0; st8.spill [r2]=r18,16
+.mem.offset 8,0; st8.spill [r3]=r19,16
+    ;;
+.mem.offset 0,0; st8.spill [r2]=r20,16
+.mem.offset 8,0; st8.spill [r3]=r21,16
+    mov r18=b6
+    ;;
+.mem.offset 0,0; st8.spill [r2]=r22,16
+.mem.offset 8,0; st8.spill [r3]=r23,16
+    mov r19=b7
+    ;;
+.mem.offset 0,0; st8.spill [r2]=r24,16
+.mem.offset 8,0; st8.spill [r3]=r25,16
+    ;;
+.mem.offset 0,0; st8.spill [r2]=r26,16
+.mem.offset 8,0; st8.spill [r3]=r27,16
+    ;;
+.mem.offset 0,0; st8.spill [r2]=r28,16
+.mem.offset 8,0; st8.spill [r3]=r29,16
+    ;;
+.mem.offset 0,0; st8.spill [r2]=r30,16
+.mem.offset 8,0; st8.spill [r3]=r31,32
+    ;;
+    mov ar.fpsr=r11       /* M-unit */
+    st8 [r2]=r8,8         /* ar.ccv */
+    adds r24=PT(B6)-PT(F7),r3
+    ;;
+    stf.spill [r2]=f6,32
+    stf.spill [r3]=f7,32
+    ;;
+    stf.spill [r2]=f8,32
+    stf.spill [r3]=f9,32
+    ;;
+    stf.spill [r2]=f10
+    stf.spill [r3]=f11
+    adds r25=PT(B7)-PT(F11),r3
+    ;;
+    st8 [r24]=r18,16       /* b6 */
+    st8 [r25]=r19,16       /* b7 */
+    ;;
+    st8 [r24]=r9           /* ar.csd */
+    st8 [r25]=r10          /* ar.ssd */
+    ;;
+    srlz.d             // make sure we see the effect of cr.ivr
+    addl r14=@gprel(ia64_leave_nested),gp
+    ;;
+    mov rp=r14
+    br.call.sptk.many b6=kvm_ia64_handle_irq
+    ;;
+END(kvm_interrupt)
+
+    .global kvm_dispatch_vexirq
+    .org kvm_ia64_ivt+0x3400
+//////////////////////////////////////////////////////////////////////
+// 0x3400 Entry 13 (size 64 bundles) Reserved
+ENTRY(kvm_virtual_exirq)
+    mov r31=pr
+    mov r19=13
+    mov r30 =r0
+    ;;
+kvm_dispatch_vexirq:
+    cmp.eq p6,p0 = 1,r30
+    ;;
+(p6)add r29 = VMM_VCPU_SAVED_GP_OFFSET,r21
+    ;;
+(p6)ld8 r1 = [r29]
+    ;;
+    KVM_SAVE_MIN_WITH_COVER_R19
+    alloc r14=ar.pfs,0,0,1,0
+    mov out0=r13
+
+    ssm psr.ic
+    ;;
+    srlz.i                  // guarantee that interruption collection is on
+    ;;
+    //(p15) ssm psr.i               // restore psr.i
+    adds r3=8,r2                // set up second base pointer
+    ;;
+    KVM_SAVE_REST
+    addl r14=@gprel(ia64_leave_hypervisor),gp
+    ;;
+    mov rp=r14
+    br.call.sptk.many b6=kvm_vexirq
+END(kvm_virtual_exirq)
+
+    .org kvm_ia64_ivt+0x3800
+/////////////////////////////////////////////////////////////////////
+// 0x3800 Entry 14 (size 64 bundles) Reserved
+    KVM_FAULT(14)
+    // this code segment is from 2.6.16.13
+
+
+    .org kvm_ia64_ivt+0x3c00
+///////////////////////////////////////////////////////////////////////
+// 0x3c00 Entry 15 (size 64 bundles) Reserved
+    KVM_FAULT(15)
+
+
+    .org kvm_ia64_ivt+0x4000
+///////////////////////////////////////////////////////////////////////
+// 0x4000 Entry 16 (size 64 bundles) Reserved
+    KVM_FAULT(16)
+
+    .org kvm_ia64_ivt+0x4400
+//////////////////////////////////////////////////////////////////////
+// 0x4400 Entry 17 (size 64 bundles) Reserved
+    KVM_FAULT(17)
+
+    .org kvm_ia64_ivt+0x4800
+//////////////////////////////////////////////////////////////////////
+// 0x4800 Entry 18 (size 64 bundles) Reserved
+    KVM_FAULT(18)
+
+    .org kvm_ia64_ivt+0x4c00
+//////////////////////////////////////////////////////////////////////
+// 0x4c00 Entry 19 (size 64 bundles) Reserved
+    KVM_FAULT(19)
+
+    .org kvm_ia64_ivt+0x5000
+//////////////////////////////////////////////////////////////////////
+// 0x5000 Entry 20 (size 16 bundles) Page Not Present
+ENTRY(kvm_page_not_present)
+    KVM_REFLECT(20)
+END(kvm_page_not_present)
+
+    .org kvm_ia64_ivt+0x5100
+///////////////////////////////////////////////////////////////////////
+// 0x5100 Entry 21 (size 16 bundles) Key Permission vector
+ENTRY(kvm_key_permission)
+    KVM_REFLECT(21)
+END(kvm_key_permission)
+
+    .org kvm_ia64_ivt+0x5200
+//////////////////////////////////////////////////////////////////////
+// 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26)
+ENTRY(kvm_iaccess_rights)
+    KVM_REFLECT(22)
+END(kvm_iaccess_rights)
+
+    .org kvm_ia64_ivt+0x5300
+//////////////////////////////////////////////////////////////////////
+// 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53)
+ENTRY(kvm_daccess_rights)
+    KVM_REFLECT(23)
+END(kvm_daccess_rights)
+
+    .org kvm_ia64_ivt+0x5400
+/////////////////////////////////////////////////////////////////////
+// 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39)
+ENTRY(kvm_general_exception)
+   KVM_REFLECT(24)
+   KVM_FAULT(24)
+END(kvm_general_exception)
+
+    .org kvm_ia64_ivt+0x5500
+//////////////////////////////////////////////////////////////////////
+// 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35)
+ENTRY(kvm_disabled_fp_reg)
+    KVM_REFLECT(25)
+END(kvm_disabled_fp_reg)
+
+    .org kvm_ia64_ivt+0x5600
+////////////////////////////////////////////////////////////////////
+// 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50)
+ENTRY(kvm_nat_consumption)
+    KVM_REFLECT(26)
+END(kvm_nat_consumption)
+
+    .org kvm_ia64_ivt+0x5700
+/////////////////////////////////////////////////////////////////////
+// 0x5700 Entry 27 (size 16 bundles) Speculation (40)
+ENTRY(kvm_speculation_vector)
+    KVM_REFLECT(27)
+END(kvm_speculation_vector)
+
+    .org kvm_ia64_ivt+0x5800
+/////////////////////////////////////////////////////////////////////
+// 0x5800 Entry 28 (size 16 bundles) Reserved
+    KVM_FAULT(28)
+
+    .org kvm_ia64_ivt+0x5900
+///////////////////////////////////////////////////////////////////
+// 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56)
+ENTRY(kvm_debug_vector)
+    KVM_FAULT(29)
+END(kvm_debug_vector)
+
+    .org kvm_ia64_ivt+0x5a00
+///////////////////////////////////////////////////////////////
+// 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57)
+ENTRY(kvm_unaligned_access)
+    KVM_REFLECT(30)
+END(kvm_unaligned_access)
+
+    .org kvm_ia64_ivt+0x5b00
+//////////////////////////////////////////////////////////////////////
+// 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57)
+ENTRY(kvm_unsupported_data_reference)
+    KVM_REFLECT(31)
+END(kvm_unsupported_data_reference)
+
+    .org kvm_ia64_ivt+0x5c00
+////////////////////////////////////////////////////////////////////
+// 0x5c00 Entry 32 (size 16 bundles) Floating Point FAULT (65)
+ENTRY(kvm_floating_point_fault)
+    KVM_REFLECT(32)
+END(kvm_floating_point_fault)
+
+    .org kvm_ia64_ivt+0x5d00
+/////////////////////////////////////////////////////////////////////
+// 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66)
+ENTRY(kvm_floating_point_trap)
+    KVM_REFLECT(33)
+END(kvm_floating_point_trap)
+
+    .org kvm_ia64_ivt+0x5e00
+//////////////////////////////////////////////////////////////////////
+// 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66)
+ENTRY(kvm_lower_privilege_trap)
+    KVM_REFLECT(34)
+END(kvm_lower_privilege_trap)
+
+    .org kvm_ia64_ivt+0x5f00
+//////////////////////////////////////////////////////////////////////
+// 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68)
+ENTRY(kvm_taken_branch_trap)
+    KVM_REFLECT(35)
+END(kvm_taken_branch_trap)
+
+    .org kvm_ia64_ivt+0x6000
+////////////////////////////////////////////////////////////////////
+// 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69)
+ENTRY(kvm_single_step_trap)
+    KVM_REFLECT(36)
+END(kvm_single_step_trap)
+    .global kvm_virtualization_fault_back
+    .org kvm_ia64_ivt+0x6100
+/////////////////////////////////////////////////////////////////////
+// 0x6100 Entry 37 (size 16 bundles) Virtualization Fault
+ENTRY(kvm_virtualization_fault)
+    mov r31=pr
+    adds r16 = VMM_VCPU_SAVED_GP_OFFSET,r21
+    ;;
+    st8 [r16] = r1
+    adds r17 = VMM_VCPU_GP_OFFSET, r21
+    ;;
+    ld8 r1 = [r17]
+    cmp.eq p6,p0=EVENT_MOV_FROM_AR,r24
+    cmp.eq p7,p0=EVENT_MOV_FROM_RR,r24
+    cmp.eq p8,p0=EVENT_MOV_TO_RR,r24
+    cmp.eq p9,p0=EVENT_RSM,r24
+    cmp.eq p10,p0=EVENT_SSM,r24
+    cmp.eq p11,p0=EVENT_MOV_TO_PSR,r24
+    cmp.eq p12,p0=EVENT_THASH,r24
+    (p6) br.dptk.many kvm_asm_mov_from_ar
+    (p7) br.dptk.many kvm_asm_mov_from_rr
+    (p8) br.dptk.many kvm_asm_mov_to_rr
+    (p9) br.dptk.many kvm_asm_rsm
+    (p10) br.dptk.many kvm_asm_ssm
+    (p11) br.dptk.many kvm_asm_mov_to_psr
+    (p12) br.dptk.many kvm_asm_thash
+    ;;
+kvm_virtualization_fault_back:
+    adds r16 = VMM_VCPU_SAVED_GP_OFFSET,r21
+    ;;
+    ld8 r1 = [r16]
+    ;;
+    mov r19=37
+    adds r16 = VMM_VCPU_CAUSE_OFFSET,r21
+    adds r17 = VMM_VCPU_OPCODE_OFFSET,r21
+    ;;
+    st8 [r16] = r24
+    st8 [r17] = r25
+    ;;
+    cmp.ne p6,p0=EVENT_RFI, r24
+    (p6) br.sptk kvm_dispatch_virtualization_fault
+    ;;
+    adds r18=VMM_VPD_BASE_OFFSET,r21
+    ;;
+    ld8 r18=[r18]
+    ;;
+    adds r18=VMM_VPD_VIFS_OFFSET,r18
+    ;;
+    ld8 r18=[r18]
+    ;;
+    tbit.z p6,p0=r18,63
+    (p6) br.sptk kvm_dispatch_virtualization_fault
+    ;;
+    //if vifs.v=1 desert current register frame
+    alloc r18=ar.pfs,0,0,0,0
+    br.sptk kvm_dispatch_virtualization_fault
+END(kvm_virtualization_fault)
+
+    .org kvm_ia64_ivt+0x6200
+//////////////////////////////////////////////////////////////
+// 0x6200 Entry 38 (size 16 bundles) Reserved
+    KVM_FAULT(38)
+
+    .org kvm_ia64_ivt+0x6300
+/////////////////////////////////////////////////////////////////
+// 0x6300 Entry 39 (size 16 bundles) Reserved
+    KVM_FAULT(39)
+
+    .org kvm_ia64_ivt+0x6400
+/////////////////////////////////////////////////////////////////
+// 0x6400 Entry 40 (size 16 bundles) Reserved
+    KVM_FAULT(40)
+
+    .org kvm_ia64_ivt+0x6500
+//////////////////////////////////////////////////////////////////
+// 0x6500 Entry 41 (size 16 bundles) Reserved
+    KVM_FAULT(41)
+
+    .org kvm_ia64_ivt+0x6600
+//////////////////////////////////////////////////////////////////
+// 0x6600 Entry 42 (size 16 bundles) Reserved
+    KVM_FAULT(42)
+
+    .org kvm_ia64_ivt+0x6700
+//////////////////////////////////////////////////////////////////
+// 0x6700 Entry 43 (size 16 bundles) Reserved
+    KVM_FAULT(43)
+
+    .org kvm_ia64_ivt+0x6800
+//////////////////////////////////////////////////////////////////
+// 0x6800 Entry 44 (size 16 bundles) Reserved
+    KVM_FAULT(44)
+
+    .org kvm_ia64_ivt+0x6900
+///////////////////////////////////////////////////////////////////
+// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception
+//(17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77)
+ENTRY(kvm_ia32_exception)
+    KVM_FAULT(45)
+END(kvm_ia32_exception)
+
+    .org kvm_ia64_ivt+0x6a00
+////////////////////////////////////////////////////////////////////
+// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept  (30,31,59,70,71)
+ENTRY(kvm_ia32_intercept)
+    KVM_FAULT(47)
+END(kvm_ia32_intercept)
+
+    .org kvm_ia64_ivt+0x6c00
+/////////////////////////////////////////////////////////////////////
+// 0x6c00 Entry 48 (size 16 bundles) Reserved
+    KVM_FAULT(48)
+
+    .org kvm_ia64_ivt+0x6d00
+//////////////////////////////////////////////////////////////////////
+// 0x6d00 Entry 49 (size 16 bundles) Reserved
+    KVM_FAULT(49)
+
+    .org kvm_ia64_ivt+0x6e00
+//////////////////////////////////////////////////////////////////////
+// 0x6e00 Entry 50 (size 16 bundles) Reserved
+    KVM_FAULT(50)
+
+    .org kvm_ia64_ivt+0x6f00
+/////////////////////////////////////////////////////////////////////
+// 0x6f00 Entry 51 (size 16 bundles) Reserved
+    KVM_FAULT(52)
+
+    .org kvm_ia64_ivt+0x7100
+////////////////////////////////////////////////////////////////////
+// 0x7100 Entry 53 (size 16 bundles) Reserved
+    KVM_FAULT(53)
+
+    .org kvm_ia64_ivt+0x7200
+/////////////////////////////////////////////////////////////////////
+// 0x7200 Entry 54 (size 16 bundles) Reserved
+    KVM_FAULT(54)
+
+    .org kvm_ia64_ivt+0x7300
+////////////////////////////////////////////////////////////////////
+// 0x7300 Entry 55 (size 16 bundles) Reserved
+    KVM_FAULT(55)
+
+    .org kvm_ia64_ivt+0x7400
+////////////////////////////////////////////////////////////////////
+// 0x7400 Entry 56 (size 16 bundles) Reserved
+    KVM_FAULT(56)
+
+    .org kvm_ia64_ivt+0x7500
+/////////////////////////////////////////////////////////////////////
+// 0x7500 Entry 57 (size 16 bundles) Reserved
+    KVM_FAULT(57)
+
+    .org kvm_ia64_ivt+0x7600
+/////////////////////////////////////////////////////////////////////
+// 0x7600 Entry 58 (size 16 bundles) Reserved
+    KVM_FAULT(58)
+
+    .org kvm_ia64_ivt+0x7700
+////////////////////////////////////////////////////////////////////
+// 0x7700 Entry 59 (size 16 bundles) Reserved
+    KVM_FAULT(59)
+
+    .org kvm_ia64_ivt+0x7800
+////////////////////////////////////////////////////////////////////
+// 0x7800 Entry 60 (size 16 bundles) Reserved
+    KVM_FAULT(60)
+
+    .org kvm_ia64_ivt+0x7900
+/////////////////////////////////////////////////////////////////////
+// 0x7900 Entry 61 (size 16 bundles) Reserved
+    KVM_FAULT(61)
+
+    .org kvm_ia64_ivt+0x7a00
+/////////////////////////////////////////////////////////////////////
+// 0x7a00 Entry 62 (size 16 bundles) Reserved
+    KVM_FAULT(62)
+
+    .org kvm_ia64_ivt+0x7b00
+/////////////////////////////////////////////////////////////////////
+// 0x7b00 Entry 63 (size 16 bundles) Reserved
+    KVM_FAULT(63)
+
+    .org kvm_ia64_ivt+0x7c00
+////////////////////////////////////////////////////////////////////
+// 0x7c00 Entry 64 (size 16 bundles) Reserved
+    KVM_FAULT(64)
+
+    .org kvm_ia64_ivt+0x7d00
+/////////////////////////////////////////////////////////////////////
+// 0x7d00 Entry 65 (size 16 bundles) Reserved
+    KVM_FAULT(65)
+
+    .org kvm_ia64_ivt+0x7e00
+/////////////////////////////////////////////////////////////////////
+// 0x7e00 Entry 66 (size 16 bundles) Reserved
+    KVM_FAULT(66)
+
+    .org kvm_ia64_ivt+0x7f00
+////////////////////////////////////////////////////////////////////
+// 0x7f00 Entry 67 (size 16 bundles) Reserved
+    KVM_FAULT(67)
+
+    .org kvm_ia64_ivt+0x8000
+// There is no particular reason for this code to be here, other than that
+// there happens to be space here that would go unused otherwise.  If this
+// fault ever gets "unreserved", simply moved the following code to a more
+// suitable spot...
+
+
+ENTRY(kvm_dtlb_miss_dispatch)
+    mov r19 = 2
+    KVM_SAVE_MIN_WITH_COVER_R19
+    alloc r14=ar.pfs,0,0,3,0
+    mov out0=cr.ifa
+    mov out1=r15
+    adds r3=8,r2                // set up second base pointer
+    ;;
+    ssm psr.ic
+    ;;
+    srlz.i                  // guarantee that interruption collection is on
+    ;;
+    //(p15) ssm psr.i               // restore psr.i
+    addl r14=@gprel(ia64_leave_hypervisor_prepare),gp
+    ;;
+    KVM_SAVE_REST
+    KVM_SAVE_EXTRA
+    mov rp=r14
+    ;;
+    adds out2=16,r12
+    br.call.sptk.many b6=kvm_page_fault
+END(kvm_dtlb_miss_dispatch)
+
+ENTRY(kvm_itlb_miss_dispatch)
+
+    KVM_SAVE_MIN_WITH_COVER_R19
+    alloc r14=ar.pfs,0,0,3,0
+    mov out0=cr.ifa
+    mov out1=r15
+    adds r3=8,r2                // set up second base pointer
+    ;;
+    ssm psr.ic
+    ;;
+    srlz.i                  // guarantee that interruption collection is on
+    ;;
+    //(p15) ssm psr.i               // restore psr.i
+    addl r14=@gprel(ia64_leave_hypervisor),gp
+    ;;
+    KVM_SAVE_REST
+    mov rp=r14
+    ;;
+    adds out2=16,r12
+    br.call.sptk.many b6=kvm_page_fault
+END(kvm_itlb_miss_dispatch)
+
+ENTRY(kvm_dispatch_reflection)
+    /*
+     * Input:
+     *  psr.ic: off
+     *  r19:    intr type (offset into ivt, see ia64_int.h)
+     *  r31:    contains saved predicates (pr)
+     */
+    KVM_SAVE_MIN_WITH_COVER_R19
+    alloc r14=ar.pfs,0,0,5,0
+    mov out0=cr.ifa
+    mov out1=cr.isr
+    mov out2=cr.iim
+    mov out3=r15
+    adds r3=8,r2                // set up second base pointer
+    ;;
+    ssm psr.ic
+    ;;
+    srlz.i                  // guarantee that interruption collection is on
+    ;;
+    //(p15) ssm psr.i               // restore psr.i
+    addl r14=@gprel(ia64_leave_hypervisor),gp
+    ;;
+    KVM_SAVE_REST
+    mov rp=r14
+    ;;
+    adds out4=16,r12
+    br.call.sptk.many b6=reflect_interruption
+END(kvm_dispatch_reflection)
+
+ENTRY(kvm_dispatch_virtualization_fault)
+    adds r16 = VMM_VCPU_CAUSE_OFFSET,r21
+    adds r17 = VMM_VCPU_OPCODE_OFFSET,r21
+    ;;
+    st8 [r16] = r24
+    st8 [r17] = r25
+    ;;
+    KVM_SAVE_MIN_WITH_COVER_R19
+    ;;
+    alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!)
+    mov out0=r13        //vcpu
+    adds r3=8,r2                // set up second base pointer
+    ;;
+    ssm psr.ic
+    ;;
+    srlz.i                  // guarantee that interruption collection is on
+    ;;
+    //(p15) ssm psr.i               // restore psr.i
+    addl r14=@gprel(ia64_leave_hypervisor_prepare),gp
+    ;;
+    KVM_SAVE_REST
+    KVM_SAVE_EXTRA
+    mov rp=r14
+    ;;
+    adds out1=16,sp         //regs
+    br.call.sptk.many b6=kvm_emulate
+END(kvm_dispatch_virtualization_fault)
+
+
+ENTRY(kvm_dispatch_interrupt)
+    KVM_SAVE_MIN_WITH_COVER_R19        // uses r31; defines r2 and r3
+    ;;
+    alloc r14=ar.pfs,0,0,1,0 // must be first in an insn group
+    //mov out0=cr.ivr          // pass cr.ivr as first arg
+    adds r3=8,r2               // set up second base pointer for SAVE_REST
+    ;;
+    ssm psr.ic
+    ;;
+    srlz.i
+    ;;
+    //(p15) ssm psr.i
+    addl r14=@gprel(ia64_leave_hypervisor),gp
+    ;;
+    KVM_SAVE_REST
+    mov rp=r14
+    ;;
+    mov out0=r13               // pass pointer to pt_regs as second arg
+    br.call.sptk.many b6=kvm_ia64_handle_irq
+END(kvm_dispatch_interrupt)
+
+
+
+
+GLOBAL_ENTRY(ia64_leave_nested)
+       rsm psr.i
+       ;;
+       adds r21=PT(PR)+16,r12
+       ;;
+       lfetch [r21],PT(CR_IPSR)-PT(PR)
+       adds r2=PT(B6)+16,r12
+       adds r3=PT(R16)+16,r12
+       ;;
+       lfetch [r21]
+       ld8 r28=[r2],8          // load b6
+       adds r29=PT(R24)+16,r12
+
+       ld8.fill r16=[r3]
+       adds r3=PT(AR_CSD)-PT(R16),r3
+       adds r30=PT(AR_CCV)+16,r12
+       ;;
+       ld8.fill r24=[r29]
+       ld8 r15=[r30]           // load ar.ccv
+       ;;
+       ld8 r29=[r2],16         // load b7
+       ld8 r30=[r3],16         // load ar.csd
+       ;;
+       ld8 r31=[r2],16         // load ar.ssd
+       ld8.fill r8=[r3],16
+       ;;
+       ld8.fill r9=[r2],16
+       ld8.fill r10=[r3],PT(R17)-PT(R10)
+       ;;
+       ld8.fill r11=[r2],PT(R18)-PT(R11)
+       ld8.fill r17=[r3],16
+       ;;
+       ld8.fill r18=[r2],16
+       ld8.fill r19=[r3],16
+       ;;
+       ld8.fill r20=[r2],16
+       ld8.fill r21=[r3],16
+       mov ar.csd=r30
+       mov ar.ssd=r31
+       ;;
+       rsm psr.i | psr.ic
+       // initiate turning off of interrupt and interruption collection
+       invala                  // invalidate ALAT
+       ;;
+       srlz.i
+       ;;
+       ld8.fill r22=[r2],24
+       ld8.fill r23=[r3],24
+       mov b6=r28
+       ;;
+       ld8.fill r25=[r2],16
+       ld8.fill r26=[r3],16
+       mov b7=r29
+       ;;
+       ld8.fill r27=[r2],16
+       ld8.fill r28=[r3],16
+       ;;
+       ld8.fill r29=[r2],16
+       ld8.fill r30=[r3],24
+       ;;
+       ld8.fill r31=[r2],PT(F9)-PT(R31)
+       adds r3=PT(F10)-PT(F6),r3
+       ;;
+       ldf.fill f9=[r2],PT(F6)-PT(F9)
+       ldf.fill f10=[r3],PT(F8)-PT(F10)
+       ;;
+       ldf.fill f6=[r2],PT(F7)-PT(F6)
+       ;;
+       ldf.fill f7=[r2],PT(F11)-PT(F7)
+       ldf.fill f8=[r3],32
+       ;;
+       srlz.i                  // ensure interruption collection is off
+       mov ar.ccv=r15
+       ;;
+       bsw.0   // switch back to bank 0 (no stop bit required beforehand...)
+       ;;
+       ldf.fill f11=[r2]
+//     mov r18=r13
+//    mov r21=r13
+       adds r16=PT(CR_IPSR)+16,r12
+       adds r17=PT(CR_IIP)+16,r12
+       ;;
+       ld8 r29=[r16],16        // load cr.ipsr
+       ld8 r28=[r17],16        // load cr.iip
+       ;;
+       ld8 r30=[r16],16        // load cr.ifs
+       ld8 r25=[r17],16        // load ar.unat
+       ;;
+       ld8 r26=[r16],16        // load ar.pfs
+       ld8 r27=[r17],16        // load ar.rsc
+       cmp.eq p9,p0=r0,r0
+       // set p9 to indicate that we should restore cr.ifs
+       ;;
+       ld8 r24=[r16],16        // load ar.rnat (may be garbage)
+       ld8 r23=[r17],16// load ar.bspstore (may be garbage)
+       ;;
+       ld8 r31=[r16],16        // load predicates
+       ld8 r22=[r17],16        // load b0
+       ;;
+       ld8 r19=[r16],16        // load ar.rsc value for "loadrs"
+       ld8.fill r1=[r17],16    // load r1
+       ;;
+       ld8.fill r12=[r16],16
+       ld8.fill r13=[r17],16
+       ;;
+       ld8 r20=[r16],16        // ar.fpsr
+       ld8.fill r15=[r17],16
+       ;;
+       ld8.fill r14=[r16],16
+       ld8.fill r2=[r17]
+       ;;
+       ld8.fill r3=[r16]
+       ;;
+       mov r16=ar.bsp          // get existing backing store pointer
+       ;;
+       mov b0=r22
+       mov ar.pfs=r26
+       mov cr.ifs=r30
+       mov cr.ipsr=r29
+       mov ar.fpsr=r20
+       mov cr.iip=r28
+       ;;
+       mov ar.rsc=r27
+       mov ar.unat=r25
+       mov pr=r31,-1
+       rfi
+END(ia64_leave_nested)
+
+
+
+GLOBAL_ENTRY(ia64_leave_hypervisor_prepare)
+    /*
+     * work.need_resched etc. mustn't get changed
+     *by this CPU before it returns to
+    ;;
+     * user- or fsys-mode, hence we disable interrupts early on:
+     */
+    adds r2 = PT(R4)+16,r12
+    adds r3 = PT(R5)+16,r12
+    adds r8 = PT(EML_UNAT)+16,r12
+    ;;
+    ld8 r8 = [r8]
+    ;;
+    mov ar.unat=r8
+    ;;
+    ld8.fill r4=[r2],16    //load r4
+    ld8.fill r5=[r3],16    //load r5
+    ;;
+    ld8.fill r6=[r2]    //load r6
+    ld8.fill r7=[r3]    //load r7
+    ;;
+END(ia64_leave_hypervisor_prepare)
+//fall through
+GLOBAL_ENTRY(ia64_leave_hypervisor)
+    rsm psr.i
+    ;;
+    br.call.sptk.many b0=leave_hypervisor_tail
+    ;;
+    adds r20=PT(PR)+16,r12
+    adds r8=PT(EML_UNAT)+16,r12
+    ;;
+    ld8 r8=[r8]
+    ;;
+    mov ar.unat=r8
+    ;;
+    lfetch [r20],PT(CR_IPSR)-PT(PR)
+    adds r2 = PT(B6)+16,r12
+    adds r3 = PT(B7)+16,r12
+    ;;
+    lfetch [r20]
+    ;;
+    ld8 r24=[r2],16        /* B6 */
+    ld8 r25=[r3],16        /* B7 */
+    ;;
+    ld8 r26=[r2],16        /* ar_csd */
+    ld8 r27=[r3],16        /* ar_ssd */
+    mov b6 = r24
+    ;;
+    ld8.fill r8=[r2],16
+    ld8.fill r9=[r3],16
+    mov b7 = r25
+    ;;
+    mov ar.csd = r26
+    mov ar.ssd = r27
+    ;;
+    ld8.fill r10=[r2],PT(R15)-PT(R10)
+    ld8.fill r11=[r3],PT(R14)-PT(R11)
+    ;;
+    ld8.fill r15=[r2],PT(R16)-PT(R15)
+    ld8.fill r14=[r3],PT(R17)-PT(R14)
+    ;;
+    ld8.fill r16=[r2],16
+    ld8.fill r17=[r3],16
+    ;;
+    ld8.fill r18=[r2],16
+    ld8.fill r19=[r3],16
+    ;;
+    ld8.fill r20=[r2],16
+    ld8.fill r21=[r3],16
+    ;;
+    ld8.fill r22=[r2],16
+    ld8.fill r23=[r3],16
+    ;;
+    ld8.fill r24=[r2],16
+    ld8.fill r25=[r3],16
+    ;;
+    ld8.fill r26=[r2],16
+    ld8.fill r27=[r3],16
+    ;;
+    ld8.fill r28=[r2],16
+    ld8.fill r29=[r3],16
+    ;;
+    ld8.fill r30=[r2],PT(F6)-PT(R30)
+    ld8.fill r31=[r3],PT(F7)-PT(R31)
+    ;;
+    rsm psr.i | psr.ic
+    // initiate turning off of interrupt and interruption collection
+    invala          // invalidate ALAT
+    ;;
+    srlz.i          // ensure interruption collection is off
+    ;;
+    bsw.0
+    ;;
+    adds r16 = PT(CR_IPSR)+16,r12
+    adds r17 = PT(CR_IIP)+16,r12
+    mov r21=r13                // get current
+    ;;
+    ld8 r31=[r16],16    // load cr.ipsr
+    ld8 r30=[r17],16    // load cr.iip
+    ;;
+    ld8 r29=[r16],16    // load cr.ifs
+    ld8 r28=[r17],16    // load ar.unat
+    ;;
+    ld8 r27=[r16],16    // load ar.pfs
+    ld8 r26=[r17],16    // load ar.rsc
+    ;;
+    ld8 r25=[r16],16    // load ar.rnat
+    ld8 r24=[r17],16    // load ar.bspstore
+    ;;
+    ld8 r23=[r16],16    // load predicates
+    ld8 r22=[r17],16    // load b0
+    ;;
+    ld8 r20=[r16],16    // load ar.rsc value for "loadrs"
+    ld8.fill r1=[r17],16    //load r1
+    ;;
+    ld8.fill r12=[r16],16    //load r12
+    ld8.fill r13=[r17],PT(R2)-PT(R13)    //load r13
+    ;;
+    ld8 r19=[r16],PT(R3)-PT(AR_FPSR)    //load ar_fpsr
+    ld8.fill r2=[r17],PT(AR_CCV)-PT(R2)    //load r2
+    ;;
+    ld8.fill r3=[r16]  //load r3
+    ld8 r18=[r17]      //load ar_ccv
+    ;;
+    mov ar.fpsr=r19
+    mov ar.ccv=r18
+    shr.u r18=r20,16
+    ;;
+kvm_rbs_switch:
+    mov r19=96
+
+kvm_dont_preserve_current_frame:
+/*
+    * To prevent leaking bits between the hypervisor and guest domain,
+    * we must clear the stacked registers in the "invalid" partition here.
+    * 5 registers/cycle on McKinley).
+    */
+#   define pRecurse    p6
+#   define pReturn     p7
+#   define Nregs       14
+
+    alloc loc0=ar.pfs,2,Nregs-2,2,0
+    shr.u loc1=r18,9           // RNaTslots <= floor(dirtySize / (64*8))
+    sub r19=r19,r18            // r19 = (physStackedSize + 8) - dirtySize
+    ;;
+    mov ar.rsc=r20             // load ar.rsc to be used for "loadrs"
+    shladd in0=loc1,3,r19
+    mov in1=0
+    ;;
+    TEXT_ALIGN(32)
+kvm_rse_clear_invalid:
+    alloc loc0=ar.pfs,2,Nregs-2,2,0
+    cmp.lt pRecurse,p0=Nregs*8,in0
+    // if more than Nregs regs left to clear, (re)curse
+    add out0=-Nregs*8,in0
+    add out1=1,in1             // increment recursion count
+    mov loc1=0
+    mov loc2=0
+    ;;
+    mov loc3=0
+    mov loc4=0
+    mov loc5=0
+    mov loc6=0
+    mov loc7=0
+(pRecurse) br.call.dptk.few b0=kvm_rse_clear_invalid
+    ;;
+    mov loc8=0
+    mov loc9=0
+    cmp.ne pReturn,p0=r0,in1
+    // if recursion count != 0, we need to do a br.ret
+    mov loc10=0
+    mov loc11=0
+(pReturn) br.ret.dptk.many b0
+
+#      undef pRecurse
+#      undef pReturn
+
+// loadrs has already been shifted
+    alloc r16=ar.pfs,0,0,0,0    // drop current register frame
+    ;;
+    loadrs
+    ;;
+    mov ar.bspstore=r24
+    ;;
+    mov ar.unat=r28
+    mov ar.rnat=r25
+    mov ar.rsc=r26
+    ;;
+    mov cr.ipsr=r31
+    mov cr.iip=r30
+    mov cr.ifs=r29
+    mov ar.pfs=r27
+    adds r18=VMM_VPD_BASE_OFFSET,r21
+    ;;
+    ld8 r18=[r18]   //vpd
+    adds r17=VMM_VCPU_ISR_OFFSET,r21
+    ;;
+    ld8 r17=[r17]
+    adds r19=VMM_VPD_VPSR_OFFSET,r18
+    ;;
+    ld8 r19=[r19]        //vpsr
+    adds r20=VMM_VCPU_VSA_BASE_OFFSET,r21
+    ;;
+    ld8 r20=[r20]
+    ;;
+//vsa_sync_write_start
+    mov r25=r18
+    adds r16= VMM_VCPU_GP_OFFSET,r21
+    ;;
+    ld8 r16= [r16] // Put gp in r24
+    movl r24=@gprel(ia64_vmm_entry)  // calculate return address
+    ;;
+    add  r24=r24,r16
+    ;;
+    add r16=PAL_VPS_SYNC_WRITE,r20
+    ;;
+    mov b0=r16
+    br.cond.sptk b0         // call the service
+    ;;
+END(ia64_leave_hypervisor)
+// fall through
+GLOBAL_ENTRY(ia64_vmm_entry)
+/*
+ *  must be at bank 0
+ *  parameter:
+ *  r17:cr.isr
+ *  r18:vpd
+ *  r19:vpsr
+ *  r20:__vsa_base
+ *  r22:b0
+ *  r23:predicate
+ */
+    mov r24=r22
+    mov r25=r18
+    tbit.nz p1,p2 = r19,IA64_PSR_IC_BIT        // p1=vpsr.ic
+    ;;
+    (p1) add r29=PAL_VPS_RESUME_NORMAL,r20
+    (p1) br.sptk.many ia64_vmm_entry_out
+    ;;
+    tbit.nz p1,p2 = r17,IA64_ISR_IR_BIT                //p1=cr.isr.ir
+    ;;
+    (p1) add r29=PAL_VPS_RESUME_NORMAL,r20
+    (p2) add r29=PAL_VPS_RESUME_HANDLER,r20
+    (p2) ld8 r26=[r25]
+    ;;
+ia64_vmm_entry_out:
+    mov pr=r23,-2
+    mov b0=r29
+    ;;
+    br.cond.sptk b0             // call pal service
+END(ia64_vmm_entry)
+
+
+
+/*
+ * extern u64 ia64_call_vsa(u64 proc, u64 arg1, u64 arg2,
+ *                  u64 arg3, u64 arg4, u64 arg5,
+ *                  u64 arg6, u64 arg7);
+ *
+ * XXX: The currently defined services use only 4 args at the max. The
+ *  rest are not consumed.
+ */
+GLOBAL_ENTRY(ia64_call_vsa)
+    .regstk 4,4,0,0
+
+rpsave  =   loc0
+pfssave =   loc1
+psrsave =   loc2
+entry   =   loc3
+hostret =   r24
+
+    alloc   pfssave=ar.pfs,4,4,0,0
+    mov rpsave=rp
+    adds entry=VMM_VCPU_VSA_BASE_OFFSET, r13
+    ;;
+    ld8 entry=[entry]
+1:  mov hostret=ip
+    mov r25=in1         // copy arguments
+    mov r26=in2
+    mov r27=in3
+    mov psrsave=psr
+    ;;
+    tbit.nz p6,p0=psrsave,14    // IA64_PSR_I
+    tbit.nz p7,p0=psrsave,13    // IA64_PSR_IC
+    ;;
+    add hostret=2f-1b,hostret   // calculate return address
+    add entry=entry,in0
+    ;;
+    rsm psr.i | psr.ic
+    ;;
+    srlz.i
+    mov b6=entry
+    br.cond.sptk b6         // call the service
+2:
+    // Architectural sequence for enabling interrupts if necessary
+(p7)    ssm psr.ic
+    ;;
+(p7)    srlz.i
+    ;;
+//(p6)    ssm psr.i
+    ;;
+    mov rp=rpsave
+    mov ar.pfs=pfssave
+    mov r8=r31
+    ;;
+    srlz.d
+    br.ret.sptk rp
+
+END(ia64_call_vsa)
+
+#define  INIT_BSPSTORE  ((4<<30)-(12<<20)-0x100)
+
+GLOBAL_ENTRY(vmm_reset_entry)
+    //set up ipsr, iip, vpd.vpsr, dcr
+    // For IPSR: it/dt/rt=1, i/ic=1, si=1, vm/bn=1
+    // For DCR: all bits 0
+    adds r14=-VMM_PT_REGS_SIZE, r12
+    ;;
+    movl r6=0x501008826000      // IPSR dt/rt/it:1;i/ic:1, si:1, vm/bn:1
+    movl r10=0x8000000000000000
+    adds r16=PT(CR_IIP), r14
+    adds r20=PT(R1), r14
+    ;;
+    rsm psr.ic | psr.i
+    ;;
+    srlz.i
+    ;;
+    bsw.0
+    ;;
+    mov r21 =r13
+    ;;
+    bsw.1
+    ;;
+    mov ar.rsc = 0
+    ;;
+    flushrs
+    ;;
+    mov ar.bspstore = 0
+    // clear BSPSTORE
+    ;;
+    mov cr.ipsr=r6
+    mov cr.ifs=r10
+    ld8 r4 = [r16] // Set init iip for first run.
+    ld8 r1 = [r20]
+    ;;
+    mov cr.iip=r4
+    ;;
+    adds r16=VMM_VPD_BASE_OFFSET,r13
+    adds r20=VMM_VCPU_VSA_BASE_OFFSET,r13
+    ;;
+    ld8 r18=[r16]
+    ld8 r20=[r20]
+    ;;
+    adds r19=VMM_VPD_VPSR_OFFSET,r18
+    ;;
+    ld8 r19=[r19]
+    mov r17=r0
+    mov r22=r0
+    mov r23=r0
+    br.cond.sptk ia64_vmm_entry
+    br.ret.sptk  b0
+END(vmm_reset_entry)
diff --git a/arch/ia64/kvm/vti.h b/arch/ia64/kvm/vti.h
new file mode 100644 (file)
index 0000000..f6c5617
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * vti.h: prototype for generial vt related interface
+ *     Copyright (c) 2004, Intel Corporation.
+ *
+ *     Xuefei Xu (Anthony Xu) (anthony.xu@intel.com)
+ *     Fred Yang (fred.yang@intel.com)
+ *     Kun Tian (Kevin Tian) (kevin.tian@intel.com)
+ *
+ *     Copyright (c) 2007, Intel Corporation.
+ *     Zhang xiantao <xiantao.zhang@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef _KVM_VT_I_H
+#define _KVM_VT_I_H
+
+#ifndef __ASSEMBLY__
+#include <asm/page.h>
+
+#include <linux/kvm_host.h>
+
+/* define itr.i and itr.d  in ia64_itr function */
+#define        ITR     0x01
+#define        DTR     0x02
+#define        IaDTR   0x03
+
+#define IA64_TR_VMM       6 /*itr6, dtr6 : maps vmm code, vmbuffer*/
+#define IA64_TR_VM_DATA   7 /*dtr7       : maps current vm data*/
+
+#define RR6 (6UL<<61)
+#define RR7 (7UL<<61)
+
+
+/* config_options in pal_vp_init_env */
+#define        VP_INITIALIZE   1UL
+#define        VP_FR_PMC       1UL<<1
+#define        VP_OPCODE       1UL<<8
+#define        VP_CAUSE        1UL<<9
+#define VP_FW_ACC      1UL<<63
+
+/* init vp env with initializing vm_buffer */
+#define        VP_INIT_ENV_INITALIZE  (VP_INITIALIZE | VP_FR_PMC |\
+       VP_OPCODE | VP_CAUSE | VP_FW_ACC)
+/* init vp env without initializing vm_buffer */
+#define        VP_INIT_ENV  VP_FR_PMC | VP_OPCODE | VP_CAUSE | VP_FW_ACC
+
+#define                PAL_VP_CREATE   265
+/* Stacked Virt. Initializes a new VPD for the operation of
+ * a new virtual processor in the virtual environment.
+ */
+#define                PAL_VP_ENV_INFO 266
+/*Stacked Virt. Returns the parameters needed to enter a virtual environment.*/
+#define                PAL_VP_EXIT_ENV 267
+/*Stacked Virt. Allows a logical processor to exit a virtual environment.*/
+#define                PAL_VP_INIT_ENV 268
+/*Stacked Virt. Allows a logical processor to enter a virtual environment.*/
+#define                PAL_VP_REGISTER 269
+/*Stacked Virt. Register a different host IVT for the virtual processor.*/
+#define                PAL_VP_RESUME   270
+/* Renamed from PAL_VP_RESUME */
+#define                PAL_VP_RESTORE  270
+/*Stacked Virt. Resumes virtual processor operation on the logical processor.*/
+#define                PAL_VP_SUSPEND  271
+/* Renamed from PAL_VP_SUSPEND */
+#define                PAL_VP_SAVE     271
+/* Stacked Virt. Suspends operation for the specified virtual processor on
+ * the logical processor.
+ */
+#define                PAL_VP_TERMINATE 272
+/* Stacked Virt. Terminates operation for the specified virtual processor.*/
+
+union vac {
+       unsigned long value;
+       struct {
+               int a_int:1;
+               int a_from_int_cr:1;
+               int a_to_int_cr:1;
+               int a_from_psr:1;
+               int a_from_cpuid:1;
+               int a_cover:1;
+               int a_bsw:1;
+               long reserved:57;
+       };
+};
+
+union vdc {
+       unsigned long value;
+       struct {
+               int d_vmsw:1;
+               int d_extint:1;
+               int d_ibr_dbr:1;
+               int d_pmc:1;
+               int d_to_pmd:1;
+               int d_itm:1;
+               long reserved:58;
+       };
+};
+
+struct vpd {
+       union vac   vac;
+       union vdc   vdc;
+       unsigned long  virt_env_vaddr;
+       unsigned long  reserved1[29];
+       unsigned long  vhpi;
+       unsigned long  reserved2[95];
+       unsigned long  vgr[16];
+       unsigned long  vbgr[16];
+       unsigned long  vnat;
+       unsigned long  vbnat;
+       unsigned long  vcpuid[5];
+       unsigned long  reserved3[11];
+       unsigned long  vpsr;
+       unsigned long  vpr;
+       unsigned long  reserved4[76];
+       union {
+               unsigned long  vcr[128];
+               struct {
+                       unsigned long dcr;
+                       unsigned long itm;
+                       unsigned long iva;
+                       unsigned long rsv1[5];
+                       unsigned long pta;
+                       unsigned long rsv2[7];
+                       unsigned long ipsr;
+                       unsigned long isr;
+                       unsigned long rsv3;
+                       unsigned long iip;
+                       unsigned long ifa;
+                       unsigned long itir;
+                       unsigned long iipa;
+                       unsigned long ifs;
+                       unsigned long iim;
+                       unsigned long iha;
+                       unsigned long rsv4[38];
+                       unsigned long lid;
+                       unsigned long ivr;
+                       unsigned long tpr;
+                       unsigned long eoi;
+                       unsigned long irr[4];
+                       unsigned long itv;
+                       unsigned long pmv;
+                       unsigned long cmcv;
+                       unsigned long rsv5[5];
+                       unsigned long lrr0;
+                       unsigned long lrr1;
+                       unsigned long rsv6[46];
+               };
+       };
+       unsigned long  reserved5[128];
+       unsigned long  reserved6[3456];
+       unsigned long  vmm_avail[128];
+       unsigned long  reserved7[4096];
+};
+
+#define PAL_PROC_VM_BIT                (1UL << 40)
+#define PAL_PROC_VMSW_BIT      (1UL << 54)
+
+static inline s64 ia64_pal_vp_env_info(u64 *buffer_size,
+               u64 *vp_env_info)
+{
+       struct ia64_pal_retval iprv;
+       PAL_CALL_STK(iprv, PAL_VP_ENV_INFO, 0, 0, 0);
+       *buffer_size = iprv.v0;
+       *vp_env_info = iprv.v1;
+       return iprv.status;
+}
+
+static inline s64 ia64_pal_vp_exit_env(u64 iva)
+{
+       struct ia64_pal_retval iprv;
+
+       PAL_CALL_STK(iprv, PAL_VP_EXIT_ENV, (u64)iva, 0, 0);
+       return iprv.status;
+}
+
+static inline s64 ia64_pal_vp_init_env(u64 config_options, u64 pbase_addr,
+                       u64 vbase_addr, u64 *vsa_base)
+{
+       struct ia64_pal_retval iprv;
+
+       PAL_CALL_STK(iprv, PAL_VP_INIT_ENV, config_options, pbase_addr,
+                       vbase_addr);
+       *vsa_base = iprv.v0;
+
+       return iprv.status;
+}
+
+static inline s64 ia64_pal_vp_restore(u64 *vpd, u64 pal_proc_vector)
+{
+       struct ia64_pal_retval iprv;
+
+       PAL_CALL_STK(iprv, PAL_VP_RESTORE, (u64)vpd, pal_proc_vector, 0);
+
+       return iprv.status;
+}
+
+static inline s64 ia64_pal_vp_save(u64 *vpd, u64 pal_proc_vector)
+{
+       struct ia64_pal_retval iprv;
+
+       PAL_CALL_STK(iprv, PAL_VP_SAVE, (u64)vpd, pal_proc_vector, 0);
+
+       return iprv.status;
+}
+
+#endif
+
+/*VPD field offset*/
+#define VPD_VAC_START_OFFSET           0
+#define VPD_VDC_START_OFFSET           8
+#define VPD_VHPI_START_OFFSET          256
+#define VPD_VGR_START_OFFSET           1024
+#define VPD_VBGR_START_OFFSET          1152
+#define VPD_VNAT_START_OFFSET          1280
+#define VPD_VBNAT_START_OFFSET         1288
+#define VPD_VCPUID_START_OFFSET                1296
+#define VPD_VPSR_START_OFFSET          1424
+#define VPD_VPR_START_OFFSET           1432
+#define VPD_VRSE_CFLE_START_OFFSET     1440
+#define VPD_VCR_START_OFFSET           2048
+#define VPD_VTPR_START_OFFSET          2576
+#define VPD_VRR_START_OFFSET           3072
+#define VPD_VMM_VAIL_START_OFFSET      31744
+
+/*Virtualization faults*/
+
+#define EVENT_MOV_TO_AR                         1
+#define EVENT_MOV_TO_AR_IMM             2
+#define EVENT_MOV_FROM_AR               3
+#define EVENT_MOV_TO_CR                         4
+#define EVENT_MOV_FROM_CR               5
+#define EVENT_MOV_TO_PSR                6
+#define EVENT_MOV_FROM_PSR              7
+#define EVENT_ITC_D                     8
+#define EVENT_ITC_I                     9
+#define EVENT_MOV_TO_RR                         10
+#define EVENT_MOV_TO_DBR                11
+#define EVENT_MOV_TO_IBR                12
+#define EVENT_MOV_TO_PKR                13
+#define EVENT_MOV_TO_PMC                14
+#define EVENT_MOV_TO_PMD                15
+#define EVENT_ITR_D                     16
+#define EVENT_ITR_I                     17
+#define EVENT_MOV_FROM_RR               18
+#define EVENT_MOV_FROM_DBR              19
+#define EVENT_MOV_FROM_IBR              20
+#define EVENT_MOV_FROM_PKR              21
+#define EVENT_MOV_FROM_PMC              22
+#define EVENT_MOV_FROM_CPUID            23
+#define EVENT_SSM                       24
+#define EVENT_RSM                       25
+#define EVENT_PTC_L                     26
+#define EVENT_PTC_G                     27
+#define EVENT_PTC_GA                    28
+#define EVENT_PTR_D                     29
+#define EVENT_PTR_I                     30
+#define EVENT_THASH                     31
+#define EVENT_TTAG                      32
+#define EVENT_TPA                       33
+#define EVENT_TAK                       34
+#define EVENT_PTC_E                     35
+#define EVENT_COVER                     36
+#define EVENT_RFI                       37
+#define EVENT_BSW_0                     38
+#define EVENT_BSW_1                     39
+#define EVENT_VMSW                      40
+
+/**PAL virtual services offsets */
+#define PAL_VPS_RESUME_NORMAL           0x0000
+#define PAL_VPS_RESUME_HANDLER          0x0400
+#define PAL_VPS_SYNC_READ               0x0800
+#define PAL_VPS_SYNC_WRITE              0x0c00
+#define PAL_VPS_SET_PENDING_INTERRUPT   0x1000
+#define PAL_VPS_THASH                   0x1400
+#define PAL_VPS_TTAG                    0x1800
+#define PAL_VPS_RESTORE                 0x1c00
+#define PAL_VPS_SAVE                    0x2000
+
+#endif/* _VT_I_H*/
diff --git a/arch/ia64/kvm/vtlb.c b/arch/ia64/kvm/vtlb.c
new file mode 100644 (file)
index 0000000..def4576
--- /dev/null
@@ -0,0 +1,636 @@
+/*
+ * vtlb.c: guest virtual tlb handling module.
+ * Copyright (c) 2004, Intel Corporation.
+ *  Yaozu Dong (Eddie Dong) <Eddie.dong@intel.com>
+ *  Xuefei Xu (Anthony Xu) <anthony.xu@intel.com>
+ *
+ * Copyright (c) 2007, Intel Corporation.
+ *  Xuefei Xu (Anthony Xu) <anthony.xu@intel.com>
+ *  Xiantao Zhang <xiantao.zhang@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include "vcpu.h"
+
+#include <linux/rwsem.h>
+
+#include <asm/tlb.h>
+
+/*
+ * Check to see if the address rid:va is translated by the TLB
+ */
+
+static int __is_tr_translated(struct thash_data *trp, u64 rid, u64 va)
+{
+       return ((trp->p) && (trp->rid == rid)
+                               && ((va-trp->vadr) < PSIZE(trp->ps)));
+}
+
+/*
+ * Only for GUEST TR format.
+ */
+static int __is_tr_overlap(struct thash_data *trp, u64 rid, u64 sva, u64 eva)
+{
+       u64 sa1, ea1;
+
+       if (!trp->p || trp->rid != rid)
+               return 0;
+
+       sa1 = trp->vadr;
+       ea1 = sa1 + PSIZE(trp->ps) - 1;
+       eva -= 1;
+       if ((sva > ea1) || (sa1 > eva))
+               return 0;
+       else
+               return 1;
+
+}
+
+void machine_tlb_purge(u64 va, u64 ps)
+{
+       ia64_ptcl(va, ps << 2);
+}
+
+void local_flush_tlb_all(void)
+{
+       int i, j;
+       unsigned long flags, count0, count1;
+       unsigned long stride0, stride1, addr;
+
+       addr    = current_vcpu->arch.ptce_base;
+       count0  = current_vcpu->arch.ptce_count[0];
+       count1  = current_vcpu->arch.ptce_count[1];
+       stride0 = current_vcpu->arch.ptce_stride[0];
+       stride1 = current_vcpu->arch.ptce_stride[1];
+
+       local_irq_save(flags);
+       for (i = 0; i < count0; ++i) {
+               for (j = 0; j < count1; ++j) {
+                       ia64_ptce(addr);
+                       addr += stride1;
+               }
+               addr += stride0;
+       }
+       local_irq_restore(flags);
+       ia64_srlz_i();          /* srlz.i implies srlz.d */
+}
+
+int vhpt_enabled(struct kvm_vcpu *vcpu, u64 vadr, enum vhpt_ref ref)
+{
+       union ia64_rr    vrr;
+       union ia64_pta   vpta;
+       struct  ia64_psr   vpsr;
+
+       vpsr = *(struct ia64_psr *)&VCPU(vcpu, vpsr);
+       vrr.val = vcpu_get_rr(vcpu, vadr);
+       vpta.val = vcpu_get_pta(vcpu);
+
+       if (vrr.ve & vpta.ve) {
+               switch (ref) {
+               case DATA_REF:
+               case NA_REF:
+                       return vpsr.dt;
+               case INST_REF:
+                       return vpsr.dt && vpsr.it && vpsr.ic;
+               case RSE_REF:
+                       return vpsr.dt && vpsr.rt;
+
+               }
+       }
+       return 0;
+}
+
+struct thash_data *vsa_thash(union ia64_pta vpta, u64 va, u64 vrr, u64 *tag)
+{
+       u64 index, pfn, rid, pfn_bits;
+
+       pfn_bits = vpta.size - 5 - 8;
+       pfn = REGION_OFFSET(va) >> _REGION_PAGE_SIZE(vrr);
+       rid = _REGION_ID(vrr);
+       index = ((rid & 0xff) << pfn_bits)|(pfn & ((1UL << pfn_bits) - 1));
+       *tag = ((rid >> 8) & 0xffff) | ((pfn >> pfn_bits) << 16);
+
+       return (struct thash_data *)((vpta.base << PTA_BASE_SHIFT) +
+                               (index << 5));
+}
+
+struct thash_data *__vtr_lookup(struct kvm_vcpu *vcpu, u64 va, int type)
+{
+
+       struct thash_data *trp;
+       int  i;
+       u64 rid;
+
+       rid = vcpu_get_rr(vcpu, va);
+       rid = rid & RR_RID_MASK;;
+       if (type == D_TLB) {
+               if (vcpu_quick_region_check(vcpu->arch.dtr_regions, va)) {
+                       for (trp = (struct thash_data *)&vcpu->arch.dtrs, i = 0;
+                                               i < NDTRS; i++, trp++) {
+                               if (__is_tr_translated(trp, rid, va))
+                                       return trp;
+                       }
+               }
+       } else {
+               if (vcpu_quick_region_check(vcpu->arch.itr_regions, va)) {
+                       for (trp = (struct thash_data *)&vcpu->arch.itrs, i = 0;
+                                       i < NITRS; i++, trp++) {
+                               if (__is_tr_translated(trp, rid, va))
+                                       return trp;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
+static void vhpt_insert(u64 pte, u64 itir, u64 ifa, u64 gpte)
+{
+       union ia64_rr rr;
+       struct thash_data *head;
+       unsigned long ps, gpaddr;
+
+       ps = itir_ps(itir);
+
+       gpaddr = ((gpte & _PAGE_PPN_MASK) >> ps << ps) |
+               (ifa & ((1UL << ps) - 1));
+
+       rr.val = ia64_get_rr(ifa);
+       head = (struct thash_data *)ia64_thash(ifa);
+       head->etag = INVALID_TI_TAG;
+       ia64_mf();
+       head->page_flags = pte & ~PAGE_FLAGS_RV_MASK;
+       head->itir = rr.ps << 2;
+       head->etag = ia64_ttag(ifa);
+       head->gpaddr = gpaddr;
+}
+
+void mark_pages_dirty(struct kvm_vcpu *v, u64 pte, u64 ps)
+{
+       u64 i, dirty_pages = 1;
+       u64 base_gfn = (pte&_PAGE_PPN_MASK) >> PAGE_SHIFT;
+       spinlock_t *lock = __kvm_va(v->arch.dirty_log_lock_pa);
+       void *dirty_bitmap = (void *)v - (KVM_VCPU_OFS + v->vcpu_id * VCPU_SIZE)
+                                               + KVM_MEM_DIRTY_LOG_OFS;
+       dirty_pages <<= ps <= PAGE_SHIFT ? 0 : ps - PAGE_SHIFT;
+
+       vmm_spin_lock(lock);
+       for (i = 0; i < dirty_pages; i++) {
+               /* avoid RMW */
+               if (!test_bit(base_gfn + i, dirty_bitmap))
+                       set_bit(base_gfn + i , dirty_bitmap);
+       }
+       vmm_spin_unlock(lock);
+}
+
+void thash_vhpt_insert(struct kvm_vcpu *v, u64 pte, u64 itir, u64 va, int type)
+{
+       u64 phy_pte, psr;
+       union ia64_rr mrr;
+
+       mrr.val = ia64_get_rr(va);
+       phy_pte = translate_phy_pte(&pte, itir, va);
+
+       if (itir_ps(itir) >= mrr.ps) {
+               vhpt_insert(phy_pte, itir, va, pte);
+       } else {
+               phy_pte  &= ~PAGE_FLAGS_RV_MASK;
+               psr = ia64_clear_ic();
+               ia64_itc(type, va, phy_pte, itir_ps(itir));
+               ia64_set_psr(psr);
+       }
+
+       if (!(pte&VTLB_PTE_IO))
+               mark_pages_dirty(v, pte, itir_ps(itir));
+}
+
+/*
+ *   vhpt lookup
+ */
+struct thash_data *vhpt_lookup(u64 va)
+{
+       struct thash_data *head;
+       u64 tag;
+
+       head = (struct thash_data *)ia64_thash(va);
+       tag = ia64_ttag(va);
+       if (head->etag == tag)
+               return head;
+       return NULL;
+}
+
+u64 guest_vhpt_lookup(u64 iha, u64 *pte)
+{
+       u64 ret;
+       struct thash_data *data;
+
+       data = __vtr_lookup(current_vcpu, iha, D_TLB);
+       if (data != NULL)
+               thash_vhpt_insert(current_vcpu, data->page_flags,
+                       data->itir, iha, D_TLB);
+
+       asm volatile ("rsm psr.ic|psr.i;;"
+                       "srlz.d;;"
+                       "ld8.s r9=[%1];;"
+                       "tnat.nz p6,p7=r9;;"
+                       "(p6) mov %0=1;"
+                       "(p6) mov r9=r0;"
+                       "(p7) extr.u r9=r9,0,53;;"
+                       "(p7) mov %0=r0;"
+                       "(p7) st8 [%2]=r9;;"
+                       "ssm psr.ic;;"
+                       "srlz.d;;"
+                       /* "ssm psr.i;;" Once interrupts in vmm open, need fix*/
+                       : "=r"(ret) : "r"(iha), "r"(pte):"memory");
+
+       return ret;
+}
+
+/*
+ *  purge software guest tlb
+ */
+
+static void vtlb_purge(struct kvm_vcpu *v, u64 va, u64 ps)
+{
+       struct thash_data *cur;
+       u64 start, curadr, size, psbits, tag, rr_ps, num;
+       union ia64_rr vrr;
+       struct thash_cb *hcb = &v->arch.vtlb;
+
+       vrr.val = vcpu_get_rr(v, va);
+       psbits = VMX(v, psbits[(va >> 61)]);
+       start = va & ~((1UL << ps) - 1);
+       while (psbits) {
+               curadr = start;
+               rr_ps = __ffs(psbits);
+               psbits &= ~(1UL << rr_ps);
+               num = 1UL << ((ps < rr_ps) ? 0 : (ps - rr_ps));
+               size = PSIZE(rr_ps);
+               vrr.ps = rr_ps;
+               while (num) {
+                       cur = vsa_thash(hcb->pta, curadr, vrr.val, &tag);
+                       if (cur->etag == tag && cur->ps == rr_ps)
+                               cur->etag = INVALID_TI_TAG;
+                       curadr += size;
+                       num--;
+               }
+       }
+}
+
+
+/*
+ *  purge VHPT and machine TLB
+ */
+static void vhpt_purge(struct kvm_vcpu *v, u64 va, u64 ps)
+{
+       struct thash_data *cur;
+       u64 start, size, tag, num;
+       union ia64_rr rr;
+
+       start = va & ~((1UL << ps) - 1);
+       rr.val = ia64_get_rr(va);
+       size = PSIZE(rr.ps);
+       num = 1UL << ((ps < rr.ps) ? 0 : (ps - rr.ps));
+       while (num) {
+               cur = (struct thash_data *)ia64_thash(start);
+               tag = ia64_ttag(start);
+               if (cur->etag == tag)
+                       cur->etag = INVALID_TI_TAG;
+               start += size;
+               num--;
+       }
+       machine_tlb_purge(va, ps);
+}
+
+/*
+ * Insert an entry into hash TLB or VHPT.
+ * NOTES:
+ *  1: When inserting VHPT to thash, "va" is a must covered
+ *  address by the inserted machine VHPT entry.
+ *  2: The format of entry is always in TLB.
+ *  3: The caller need to make sure the new entry will not overlap
+ *     with any existed entry.
+ */
+void vtlb_insert(struct kvm_vcpu *v, u64 pte, u64 itir, u64 va)
+{
+       struct thash_data *head;
+       union ia64_rr vrr;
+       u64 tag;
+       struct thash_cb *hcb = &v->arch.vtlb;
+
+       vrr.val = vcpu_get_rr(v, va);
+       vrr.ps = itir_ps(itir);
+       VMX(v, psbits[va >> 61]) |= (1UL << vrr.ps);
+       head = vsa_thash(hcb->pta, va, vrr.val, &tag);
+       head->page_flags = pte;
+       head->itir = itir;
+       head->etag = tag;
+}
+
+int vtr_find_overlap(struct kvm_vcpu *vcpu, u64 va, u64 ps, int type)
+{
+       struct thash_data  *trp;
+       int  i;
+       u64 end, rid;
+
+       rid = vcpu_get_rr(vcpu, va);
+       rid = rid & RR_RID_MASK;
+       end = va + PSIZE(ps);
+       if (type == D_TLB) {
+               if (vcpu_quick_region_check(vcpu->arch.dtr_regions, va)) {
+                       for (trp = (struct thash_data *)&vcpu->arch.dtrs, i = 0;
+                                       i < NDTRS; i++, trp++) {
+                               if (__is_tr_overlap(trp, rid, va, end))
+                                       return i;
+                       }
+               }
+       } else {
+               if (vcpu_quick_region_check(vcpu->arch.itr_regions, va)) {
+                       for (trp = (struct thash_data *)&vcpu->arch.itrs, i = 0;
+                                       i < NITRS; i++, trp++) {
+                               if (__is_tr_overlap(trp, rid, va, end))
+                                       return i;
+                       }
+               }
+       }
+       return -1;
+}
+
+/*
+ * Purge entries in VTLB and VHPT
+ */
+void thash_purge_entries(struct kvm_vcpu *v, u64 va, u64 ps)
+{
+       if (vcpu_quick_region_check(v->arch.tc_regions, va))
+               vtlb_purge(v, va, ps);
+       vhpt_purge(v, va, ps);
+}
+
+void thash_purge_entries_remote(struct kvm_vcpu *v, u64 va, u64 ps)
+{
+       u64 old_va = va;
+       va = REGION_OFFSET(va);
+       if (vcpu_quick_region_check(v->arch.tc_regions, old_va))
+               vtlb_purge(v, va, ps);
+       vhpt_purge(v, va, ps);
+}
+
+u64 translate_phy_pte(u64 *pte, u64 itir, u64 va)
+{
+       u64 ps, ps_mask, paddr, maddr;
+       union pte_flags phy_pte;
+
+       ps = itir_ps(itir);
+       ps_mask = ~((1UL << ps) - 1);
+       phy_pte.val = *pte;
+       paddr = *pte;
+       paddr = ((paddr & _PAGE_PPN_MASK) & ps_mask) | (va & ~ps_mask);
+       maddr = kvm_lookup_mpa(paddr >> PAGE_SHIFT);
+       if (maddr & GPFN_IO_MASK) {
+               *pte |= VTLB_PTE_IO;
+               return -1;
+       }
+       maddr = ((maddr & _PAGE_PPN_MASK) & PAGE_MASK) |
+                                       (paddr & ~PAGE_MASK);
+       phy_pte.ppn = maddr >> ARCH_PAGE_SHIFT;
+       return phy_pte.val;
+}
+
+/*
+ * Purge overlap TCs and then insert the new entry to emulate itc ops.
+ *    Notes: Only TC entry can purge and insert.
+ *    1 indicates this is MMIO
+ */
+int thash_purge_and_insert(struct kvm_vcpu *v, u64 pte, u64 itir,
+                                               u64 ifa, int type)
+{
+       u64 ps;
+       u64 phy_pte;
+       union ia64_rr vrr, mrr;
+       int ret = 0;
+
+       ps = itir_ps(itir);
+       vrr.val = vcpu_get_rr(v, ifa);
+       mrr.val = ia64_get_rr(ifa);
+
+       phy_pte = translate_phy_pte(&pte, itir, ifa);
+
+       /* Ensure WB attribute if pte is related to a normal mem page,
+        * which is required by vga acceleration since qemu maps shared
+        * vram buffer with WB.
+        */
+       if (!(pte & VTLB_PTE_IO) && ((pte & _PAGE_MA_MASK) != _PAGE_MA_NAT)) {
+               pte &= ~_PAGE_MA_MASK;
+               phy_pte &= ~_PAGE_MA_MASK;
+       }
+
+       if (pte & VTLB_PTE_IO)
+               ret = 1;
+
+       vtlb_purge(v, ifa, ps);
+       vhpt_purge(v, ifa, ps);
+
+       if (ps == mrr.ps) {
+               if (!(pte&VTLB_PTE_IO)) {
+                       vhpt_insert(phy_pte, itir, ifa, pte);
+               } else {
+                       vtlb_insert(v, pte, itir, ifa);
+                       vcpu_quick_region_set(VMX(v, tc_regions), ifa);
+               }
+       } else if (ps > mrr.ps) {
+               vtlb_insert(v, pte, itir, ifa);
+               vcpu_quick_region_set(VMX(v, tc_regions), ifa);
+               if (!(pte&VTLB_PTE_IO))
+                       vhpt_insert(phy_pte, itir, ifa, pte);
+       } else {
+               u64 psr;
+               phy_pte  &= ~PAGE_FLAGS_RV_MASK;
+               psr = ia64_clear_ic();
+               ia64_itc(type, ifa, phy_pte, ps);
+               ia64_set_psr(psr);
+       }
+       if (!(pte&VTLB_PTE_IO))
+               mark_pages_dirty(v, pte, ps);
+
+       return ret;
+}
+
+/*
+ * Purge all TCs or VHPT entries including those in Hash table.
+ *
+ */
+
+void thash_purge_all(struct kvm_vcpu *v)
+{
+       int i;
+       struct thash_data *head;
+       struct thash_cb  *vtlb, *vhpt;
+       vtlb = &v->arch.vtlb;
+       vhpt = &v->arch.vhpt;
+
+       for (i = 0; i < 8; i++)
+               VMX(v, psbits[i]) = 0;
+
+       head = vtlb->hash;
+       for (i = 0; i < vtlb->num; i++) {
+               head->page_flags = 0;
+               head->etag = INVALID_TI_TAG;
+               head->itir = 0;
+               head->next = 0;
+               head++;
+       };
+
+       head = vhpt->hash;
+       for (i = 0; i < vhpt->num; i++) {
+               head->page_flags = 0;
+               head->etag = INVALID_TI_TAG;
+               head->itir = 0;
+               head->next = 0;
+               head++;
+       };
+
+       local_flush_tlb_all();
+}
+
+
+/*
+ * Lookup the hash table and its collision chain to find an entry
+ * covering this address rid:va or the entry.
+ *
+ * INPUT:
+ *  in: TLB format for both VHPT & TLB.
+ */
+
+struct thash_data *vtlb_lookup(struct kvm_vcpu *v, u64 va, int is_data)
+{
+       struct thash_data  *cch;
+       u64    psbits, ps, tag;
+       union ia64_rr vrr;
+
+       struct thash_cb *hcb = &v->arch.vtlb;
+
+       cch = __vtr_lookup(v, va, is_data);;
+       if (cch)
+               return cch;
+
+       if (vcpu_quick_region_check(v->arch.tc_regions, va) == 0)
+               return NULL;
+
+       psbits = VMX(v, psbits[(va >> 61)]);
+       vrr.val = vcpu_get_rr(v, va);
+       while (psbits) {
+               ps = __ffs(psbits);
+               psbits &= ~(1UL << ps);
+               vrr.ps = ps;
+               cch = vsa_thash(hcb->pta, va, vrr.val, &tag);
+               if (cch->etag == tag && cch->ps == ps)
+                       return cch;
+       }
+
+       return NULL;
+}
+
+
+/*
+ * Initialize internal control data before service.
+ */
+void thash_init(struct thash_cb *hcb, u64 sz)
+{
+       int i;
+       struct thash_data *head;
+
+       hcb->pta.val = (unsigned long)hcb->hash;
+       hcb->pta.vf = 1;
+       hcb->pta.ve = 1;
+       hcb->pta.size = sz;
+       head = hcb->hash;
+       for (i = 0; i < hcb->num; i++) {
+               head->page_flags = 0;
+               head->itir = 0;
+               head->etag = INVALID_TI_TAG;
+               head->next = 0;
+               head++;
+       }
+}
+
+u64 kvm_lookup_mpa(u64 gpfn)
+{
+       u64 *base = (u64 *) KVM_P2M_BASE;
+       return *(base + gpfn);
+}
+
+u64 kvm_gpa_to_mpa(u64 gpa)
+{
+       u64 pte = kvm_lookup_mpa(gpa >> PAGE_SHIFT);
+       return (pte >> PAGE_SHIFT << PAGE_SHIFT) | (gpa & ~PAGE_MASK);
+}
+
+
+/*
+ * Fetch guest bundle code.
+ * INPUT:
+ *  gip: guest ip
+ *  pbundle: used to return fetched bundle.
+ */
+int fetch_code(struct kvm_vcpu *vcpu, u64 gip, IA64_BUNDLE *pbundle)
+{
+       u64     gpip = 0;   /* guest physical IP*/
+       u64     *vpa;
+       struct thash_data    *tlb;
+       u64     maddr;
+
+       if (!(VCPU(vcpu, vpsr) & IA64_PSR_IT)) {
+               /* I-side physical mode */
+               gpip = gip;
+       } else {
+               tlb = vtlb_lookup(vcpu, gip, I_TLB);
+               if (tlb)
+                       gpip = (tlb->ppn >> (tlb->ps - 12) << tlb->ps) |
+                               (gip & (PSIZE(tlb->ps) - 1));
+       }
+       if (gpip) {
+               maddr = kvm_gpa_to_mpa(gpip);
+       } else {
+               tlb = vhpt_lookup(gip);
+               if (tlb == NULL) {
+                       ia64_ptcl(gip, ARCH_PAGE_SHIFT << 2);
+                       return IA64_FAULT;
+               }
+               maddr = (tlb->ppn >> (tlb->ps - 12) << tlb->ps)
+                                       | (gip & (PSIZE(tlb->ps) - 1));
+       }
+       vpa = (u64 *)__kvm_va(maddr);
+
+       pbundle->i64[0] = *vpa++;
+       pbundle->i64[1] = *vpa;
+
+       return IA64_NO_FAULT;
+}
+
+
+void kvm_init_vhpt(struct kvm_vcpu *v)
+{
+       v->arch.vhpt.num = VHPT_NUM_ENTRIES;
+       thash_init(&v->arch.vhpt, VHPT_SHIFT);
+       ia64_set_pta(v->arch.vhpt.pta.val);
+       /*Enable VHPT here?*/
+}
+
+void kvm_init_vtlb(struct kvm_vcpu *v)
+{
+       v->arch.vtlb.num = VTLB_NUM_ENTRIES;
+       thash_init(&v->arch.vtlb, VTLB_SHIFT);
+}
index 4bb2e9310a569d092835cf6cb7ba528444adac7d..4e40c122bf26568db0fdfe36c3f55d89f526f9e1 100644 (file)
@@ -626,20 +626,6 @@ config ADVANCED_OPTIONS
 comment "Default settings for advanced configuration options are used"
        depends on !ADVANCED_OPTIONS
 
-config HIGHMEM_START_BOOL
-       bool "Set high memory pool address"
-       depends on ADVANCED_OPTIONS && HIGHMEM
-       help
-         This option allows you to set the base address of the kernel virtual
-         area used to map high memory pages.  This can be useful in
-         optimizing the layout of kernel virtual memory.
-
-         Say N here unless you know what you are doing.
-
-config HIGHMEM_START
-       hex "Virtual start address of high memory pool" if HIGHMEM_START_BOOL
-       default "0xfe000000"
-
 config LOWMEM_SIZE_BOOL
        bool "Set maximum low memory"
        depends on ADVANCED_OPTIONS
@@ -656,21 +642,76 @@ config LOWMEM_SIZE
        hex "Maximum low memory size (in bytes)" if LOWMEM_SIZE_BOOL
        default "0x30000000"
 
+config RELOCATABLE
+       bool "Build a relocatable kernel (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE
+       help
+         This builds a kernel image that is capable of running at the
+         location the kernel is loaded at (some alignment restrictions may
+         exist).
+
+         One use is for the kexec on panic case where the recovery kernel
+         must live at a different physical address than the primary
+         kernel.
+
+         Note: If CONFIG_RELOCATABLE=y, then the kernel runs from the address
+         it has been loaded at and the compile time physical addresses
+         CONFIG_PHYSICAL_START is ignored.  However CONFIG_PHYSICAL_START
+         setting can still be useful to bootwrappers that need to know the
+         load location of the kernel (eg. u-boot/mkimage).
+
+config PAGE_OFFSET_BOOL
+       bool "Set custom page offset address"
+       depends on ADVANCED_OPTIONS
+       help
+         This option allows you to set the kernel virtual address at which
+         the kernel will map low memory.  This can be useful in optimizing
+         the virtual memory layout of the system.
+
+         Say N here unless you know what you are doing.
+
+config PAGE_OFFSET
+       hex "Virtual address of memory base" if PAGE_OFFSET_BOOL
+       default "0xc0000000"
+
 config KERNEL_START_BOOL
        bool "Set custom kernel base address"
        depends on ADVANCED_OPTIONS
        help
          This option allows you to set the kernel virtual address at which
-         the kernel will map low memory (the kernel image will be linked at
-         this address).  This can be useful in optimizing the virtual memory
-         layout of the system.
+         the kernel will be loaded.  Normally this should match PAGE_OFFSET
+         however there are times (like kdump) that one might not want them
+         to be the same.
 
          Say N here unless you know what you are doing.
 
 config KERNEL_START
        hex "Virtual address of kernel base" if KERNEL_START_BOOL
+       default PAGE_OFFSET if PAGE_OFFSET_BOOL
+       default "0xc2000000" if CRASH_DUMP
        default "0xc0000000"
 
+config PHYSICAL_START_BOOL
+       bool "Set physical address where the kernel is loaded"
+       depends on ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE
+       help
+         This gives the physical address where the kernel is loaded.
+
+         Say N here unless you know what you are doing.
+
+config PHYSICAL_START
+       hex "Physical address where the kernel is loaded" if PHYSICAL_START_BOOL
+       default "0x02000000" if PPC_STD_MMU && CRASH_DUMP
+       default "0x00000000"
+
+config PHYSICAL_ALIGN
+       hex
+       default "0x10000000" if FSL_BOOKE
+       help
+         This value puts the alignment restrictions on physical address
+         where kernel is loaded and run from. Kernel is compiled for an
+         address which meets above alignment restriction.
+
 config TASK_SIZE_BOOL
        bool "Set custom user task size"
        depends on ADVANCED_OPTIONS
@@ -717,9 +758,17 @@ config PIN_TLB
 endmenu
 
 if PPC64
+config PAGE_OFFSET
+       hex
+       default "0xc000000000000000"
 config KERNEL_START
        hex
+       default "0xc000000002000000" if CRASH_DUMP
        default "0xc000000000000000"
+config PHYSICAL_START
+       hex
+       default "0x02000000" if CRASH_DUMP
+       default "0x00000000"
 endif
 
 source "net/Kconfig"
@@ -754,3 +803,4 @@ config PPC_CLOCK
 config PPC_LIB_RHEAP
        bool
 
+source "arch/powerpc/kvm/Kconfig"
index a86d8d853214a37c6e807c3e5515c7cf21ef36c6..807a2dce626381997dcd65a6ac0cd9c0931a91d6 100644 (file)
@@ -151,6 +151,9 @@ config BOOTX_TEXT
 
 config PPC_EARLY_DEBUG
        bool "Early debugging (dangerous)"
+       # PPC_EARLY_DEBUG on 440 leaves AS=1 mappings above the TLB high water
+       # mark, which doesn't work with current 440 KVM.
+       depends on !KVM
        help
          Say Y to enable some early debugging facilities that may be available
          for your processor/board combination. Those facilities are hacks
index e2ec4a91ccefee1b68b22a4b2c834ebc578983f7..9dcdc036cdf7ff13a6e09ad02d61b01c888e7d6f 100644 (file)
@@ -145,6 +145,7 @@ core-y                              += arch/powerpc/kernel/ \
                                   arch/powerpc/platforms/
 core-$(CONFIG_MATH_EMULATION)  += arch/powerpc/math-emu/
 core-$(CONFIG_XMON)            += arch/powerpc/xmon/
+core-$(CONFIG_KVM)             += arch/powerpc/kvm/
 
 drivers-$(CONFIG_OPROFILE)     += arch/powerpc/oprofile/
 
index 5ef2bdf8d18926db9de9f37d595c3e43770fc039..2347294ff35b6639792f98115d593480d60ce351 100644 (file)
@@ -27,6 +27,7 @@ zImage.chrp
 zImage.coff
 zImage.coff.lds
 zImage.ep*
+zImage.iseries
 zImage.*lds
 zImage.miboot
 zImage.pmac
index 5ba50c673390312eca8a5f1a817ccf1ace781712..7822d25c9d3140b10594076dde86c6d4c8acd0bc 100644 (file)
@@ -40,7 +40,7 @@ $(obj)/ebony.o: BOOTCFLAGS += -mcpu=405
 $(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=405
 $(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405
 $(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405
-$(obj)/virtex405-head.o: BOOTCFLAGS += -mcpu=405
+$(obj)/virtex405-head.o: BOOTAFLAGS += -mcpu=405
 
 
 zlib       := inffast.c inflate.c inftrees.c
index 6f3d38a1554f56c020f97721734882ea1233d943..39634124929b263aaa682ccfccb1d94739115038 100644 (file)
                                #address-cells = <2>;
                                #size-cells = <1>;
                                clock-frequency = <0>; /* Filled in by U-Boot */
+                               /* ranges property is supplied by U-Boot */
                                interrupts = <6 4>;
                                interrupt-parent = <&UIC1>;
+
+                               nor_flash@0,0 {
+                                       compatible = "amd,s29gl512n", "cfi-flash";
+                                       bank-width = <2>;
+                                       reg = <0 000000 4000000>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+                                       partition@0 {
+                                               label = "kernel";
+                                               reg = <0 1e0000>;
+                                       };
+                                       partition@1e0000 {
+                                               label = "dtb";
+                                               reg = <1e0000 20000>;
+                                       };
+                                       partition@200000 {
+                                               label = "ramdisk";
+                                               reg = <200000 1400000>;
+                                       };
+                                       partition@1600000 {
+                                               label = "jffs2";
+                                               reg = <1600000 400000>;
+                                       };
+                                       partition@1a00000 {
+                                               label = "user";
+                                               reg = <1a00000 2560000>;
+                                       };
+                                       partition@3f60000 {
+                                               label = "env";
+                                               reg = <3f60000 40000>;
+                                       };
+                                       partition@3fa0000 {
+                                               label = "u-boot";
+                                               reg = <3fa0000 60000>;
+                                       };
+                               };
                        };
 
                        UART0: serial@ef600300 {
index 958a5ca53d353833952c9dfe47d86c620dfe011c..0f2fc077d8db4c181593e7bc836e60c647d18c3b 100644 (file)
                                #address-cells = <2>;
                                #size-cells = <1>;
                                clock-frequency = <0>; /* Filled in by U-Boot */
+                               /* ranges property is supplied by U-Boot */
                                interrupts = <6 4>;
                                interrupt-parent = <&UIC1>;
+
+                               nor_flash@0,0 {
+                                       compatible = "amd,s29gl512n", "cfi-flash";
+                                       bank-width = <2>;
+                                       reg = <0 000000 4000000>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+                                       partition@0 {
+                                               label = "kernel";
+                                               reg = <0 1e0000>;
+                                       };
+                                       partition@1e0000 {
+                                               label = "dtb";
+                                               reg = <1e0000 20000>;
+                                       };
+                                       partition@200000 {
+                                               label = "ramdisk";
+                                               reg = <200000 1400000>;
+                                       };
+                                       partition@1600000 {
+                                               label = "jffs2";
+                                               reg = <1600000 400000>;
+                                       };
+                                       partition@1a00000 {
+                                               label = "user";
+                                               reg = <1a00000 2560000>;
+                                       };
+                                       partition@3f60000 {
+                                               label = "env";
+                                               reg = <3f60000 40000>;
+                                       };
+                                       partition@3fa0000 {
+                                               label = "u-boot";
+                                               reg = <3fa0000 60000>;
+                                       };
+                               };
                        };
 
                        UART0: serial@ef600300 {
index aef3bdc891605d30e664689bec5d7af43fae54d2..8c9ead94be06f70b891a6bd90b39f98a0d4bbbd4 100644 (file)
@@ -55,10 +55,15 @@ static u8 ns16550_tstc(void)
 int ns16550_console_init(void *devp, struct serial_console_data *scdp)
 {
        int n;
+       u32 reg_offset;
 
        if (dt_get_virtual_reg(devp, (void **)&reg_base, 1) < 1)
                return -1;
 
+       n = getprop(devp, "reg-offset", &reg_offset, sizeof(reg_offset));
+       if (n == sizeof(reg_offset))
+               reg_base += reg_offset;
+
        n = getprop(devp, "reg-shift", &reg_shift, sizeof(reg_shift));
        if (n != sizeof(reg_shift))
                reg_shift = 0;
index ce1e8d24e747c3ee56c19793700a5721df64c8b0..9177b21b1a954a17b531fc1884e6b8bc61510cb1 100644 (file)
@@ -106,4 +106,13 @@ PHONY += systbl_chk
 systbl_chk: $(src)/systbl_chk.sh $(obj)/systbl_chk.i
        $(call cmd,systbl_chk)
 
+$(obj)/built-in.o:             prom_init_check
+
+quiet_cmd_prom_init_check = CALL    $<
+      cmd_prom_init_check = $(CONFIG_SHELL) $< "$(NM)" "$(obj)/prom_init.o"
+
+PHONY += prom_init_check
+prom_init_check: $(src)/prom_init_check.sh $(obj)/prom_init.o
+       $(call cmd,prom_init_check)
+
 clean-files := vmlinux.lds
index 292c6d8db0e1af76d5d0b8af7bca83385c0b05e1..62134845af081e529f88ea80820ea3d286a2f0f5 100644 (file)
@@ -23,6 +23,9 @@
 #include <linux/mm.h>
 #include <linux/suspend.h>
 #include <linux/hrtimer.h>
+#ifdef CONFIG_KVM
+#include <linux/kvm_host.h>
+#endif
 #ifdef CONFIG_PPC64
 #include <linux/time.h>
 #include <linux/hardirq.h>
@@ -93,10 +96,7 @@ int main(void)
        DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
        DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
        DEFINE(TI_TASK, offsetof(struct thread_info, task));
-#ifdef CONFIG_PPC32
-       DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
        DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
-#endif /* CONFIG_PPC32 */
 
 #ifdef CONFIG_PPC64
        DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size));
@@ -165,13 +165,9 @@ int main(void)
 
        /* Interrupt register frame */
        DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
-#ifndef CONFIG_PPC64
-       DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
-#else /* CONFIG_PPC64 */
+       DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE);
+#ifdef CONFIG_PPC64
        DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
-       /* 288 = # of volatile regs, int & fp, for leaf routines */
-       /* which do not stack a frame.  See the PPC64 ABI.       */
-       DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 288);
        /* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */
        DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
        DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
@@ -331,5 +327,30 @@ int main(void)
 
        DEFINE(PGD_TABLE_SIZE, PGD_TABLE_SIZE);
 
+#ifdef CONFIG_KVM
+       DEFINE(TLBE_BYTES, sizeof(struct tlbe));
+
+       DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack));
+       DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid));
+       DEFINE(VCPU_HOST_TLB, offsetof(struct kvm_vcpu, arch.host_tlb));
+       DEFINE(VCPU_SHADOW_TLB, offsetof(struct kvm_vcpu, arch.shadow_tlb));
+       DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
+       DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
+       DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
+       DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
+       DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
+       DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc));
+       DEFINE(VCPU_MSR, offsetof(struct kvm_vcpu, arch.msr));
+       DEFINE(VCPU_SPRG4, offsetof(struct kvm_vcpu, arch.sprg4));
+       DEFINE(VCPU_SPRG5, offsetof(struct kvm_vcpu, arch.sprg5));
+       DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6));
+       DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7));
+       DEFINE(VCPU_PID, offsetof(struct kvm_vcpu, arch.pid));
+
+       DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
+       DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear));
+       DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr));
+#endif
+
        return 0;
 }
index 5465e8de0e61a547fed18f14222199b311b0dfee..e3623e3e34514d8aed247024ebbf2673416d0060 100644 (file)
@@ -33,7 +33,6 @@ _GLOBAL(__setup_cpu_440grx)
        mtlr    r4
        blr
 _GLOBAL(__setup_cpu_460ex)
-_GLOBAL(__setup_cpu_460gt)
        b       __init_fpu_44x
 _GLOBAL(__setup_cpu_440gx)
 _GLOBAL(__setup_cpu_440spe)
index f1ee0b3f78f26fc1e0364244b2819486e637191f..72d1d739525425e023ee719f45ce2ee3f1da6646 100644 (file)
 #include <asm/cache.h>
 
 _GLOBAL(__setup_cpu_603)
-       b       setup_common_caches
+       mflr    r4
+BEGIN_FTR_SECTION
+       bl      __init_fpu_registers
+END_FTR_SECTION_IFCLR(CPU_FTR_FPU_UNAVAILABLE)
+       bl      setup_common_caches
+       mtlr    r4
+       blr
 _GLOBAL(__setup_cpu_604)
        mflr    r4
        bl      setup_common_caches
index 26ffb44e2701ec5500ca1543e1169a2a9edd35ae..36080d4d1922ba1d47621916f84fa528fe615816 100644 (file)
@@ -37,7 +37,6 @@ extern void __setup_cpu_440gx(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_440grx(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_440spe(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_460ex(unsigned long offset, struct cpu_spec* spec);
-extern void __setup_cpu_460gt(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec);
@@ -1416,10 +1415,9 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .pvr_value              = 0x13020000,
                .cpu_name               = "460GT",
                .cpu_features           = CPU_FTRS_44X,
-               .cpu_user_features      = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
+               .cpu_user_features      = COMMON_USER_BOOKE,
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
-               .cpu_setup              = __setup_cpu_460gt,
                .machine_check          = machine_check_440A,
                .platform               = "ppc440",
        },
index 4ff7441435660631f5b5bad2359ebcc0af07003f..e581524d85bc9ee040bef175426d85c4a03b0cc6 100644 (file)
@@ -371,6 +371,17 @@ skpinv:    addi    r6,r6,1                         /* Increment */
 
        bl      early_init
 
+#ifdef CONFIG_RELOCATABLE
+       lis     r3,kernstart_addr@ha
+       la      r3,kernstart_addr@l(r3)
+#ifdef CONFIG_PHYS_64BIT
+       stw     r23,0(r3)
+       stw     r25,4(r3)
+#else
+       stw     r25,0(r3)
+#endif
+#endif
+
        mfspr   r3,SPRN_TLB1CFG
        andi.   r3,r3,0xfff
        lis     r4,num_tlbcam_entries@ha
index 9d2c56621f1ea0ad18ee1a0d89e46931ece7e7a5..92ccc6fcc5b03ba87f0e6b52e9dedeece2d874cc 100644 (file)
@@ -152,7 +152,7 @@ _GLOBAL(low_choose_750fx_pll)
        mtspr   SPRN_HID1,r4
 
        /* Store new HID1 image */
-       rlwinm  r6,r1,0,0,18
+       rlwinm  r6,r1,0,0,(31-THREAD_SHIFT)
        lwz     r6,TI_CPU(r6)
        slwi    r6,r6,2
        addis   r6,r6,nap_save_hid1@ha
@@ -281,7 +281,7 @@ _GLOBAL(_tlbia)
 #endif /* CONFIG_SMP */
 #else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
 #if defined(CONFIG_SMP)
-       rlwinm  r8,r1,0,0,18
+       rlwinm  r8,r1,0,0,(31-THREAD_SHIFT)
        lwz     r8,TI_CPU(r8)
        oris    r8,r8,10
        mfmsr   r10
@@ -377,7 +377,7 @@ _GLOBAL(_tlbie)
 #endif /* CONFIG_SMP */
 #else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
 #if defined(CONFIG_SMP)
-       rlwinm  r8,r1,0,0,18
+       rlwinm  r8,r1,0,0,(31-THREAD_SHIFT)
        lwz     r8,TI_CPU(r8)
        oris    r8,r8,11
        mfmsr   r10
index a3c491e88a72853a34b56121d31818002aeee882..942951e7658643f7d8a1bd33ebcad449d4f6d5de 100644 (file)
 
        .text
 
-_GLOBAL(get_msr)
-       mfmsr   r3
-       blr
-
-_GLOBAL(get_srr0)
-       mfsrr0  r3
-       blr
-
-_GLOBAL(get_srr1)
-       mfsrr1  r3
-       blr
-
 #ifdef CONFIG_IRQSTACKS
 _GLOBAL(call_do_softirq)
        mflr    r0
        std     r0,16(r1)
-       stdu    r1,THREAD_SIZE-112(r3)
+       stdu    r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
        mr      r1,r3
        bl      .__do_softirq
        ld      r1,0(r1)
@@ -56,7 +44,7 @@ _GLOBAL(call_handle_irq)
        mflr    r0
        std     r0,16(r1)
        mtctr   r8
-       stdu    r1,THREAD_SIZE-112(r5)
+       stdu    r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r5)
        mr      r1,r5
        bctrl
        ld      r1,0(r1)
@@ -599,7 +587,7 @@ _GLOBAL(kexec_sequence)
        std     r0,16(r1)
 
        /* switch stacks to newstack -- &kexec_stack.stack */
-       stdu    r1,THREAD_SIZE-112(r3)
+       stdu    r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
        mr      r1,r3
 
        li      r0,0
@@ -616,7 +604,7 @@ _GLOBAL(kexec_sequence)
        std     r26,-48(r1)
        std     r25,-56(r1)
 
-       stdu    r1,-112-64(r1)
+       stdu    r1,-STACK_FRAME_OVERHEAD-64(r1)
 
        /* save args into preserved regs */
        mr      r31,r3                  /* newstack (both) */
index fb698d47082d3d10c17edcdff354ce4f832858b6..e79ad8afda0737fed27aa043fa8ca726b8a5411a 100644 (file)
@@ -275,6 +275,8 @@ static int __devinit of_pci_phb_probe(struct of_device *dev,
 
        /* Scan the bus */
        scan_phb(phb);
+       if (phb->bus == NULL)
+               return -ENXIO;
 
        /* Claim resources. This might need some rework as well depending
         * wether we are doing probe-only or not, like assigning unassigned
index ac163bd46cfdaf99d7a5da904d9f455cf6a220dc..c9bf17eec31b1d14c5fd144b18e372e05e6b5868 100644 (file)
@@ -7,17 +7,11 @@
  *      2 of the License, or (at your option) any later version.
  */
 
-#include <linux/types.h>
 #include <linux/threads.h>
 #include <linux/module.h>
 
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-#include <asm/page.h>
 #include <asm/lppaca.h>
 #include <asm/paca.h>
-#include <asm/mmu.h>
-
 
 /* This symbol is provided by the linker - let it fill in the paca
  * field correctly */
@@ -65,60 +59,29 @@ struct slb_shadow slb_shadow[] __cacheline_aligned = {
  * processors.  The processor VPD array needs one entry per physical
  * processor (not thread).
  */
-#define PACA_INIT(number)                                                  \
-{                                                                          \
-       .lppaca_ptr = &lppaca[number],                                      \
-       .lock_token = 0x8000,                                               \
-       .paca_index = (number),         /* Paca Index */                    \
-       .kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL,             \
-       .hw_cpu_id = 0xffff,                                                \
-       .slb_shadow_ptr = &slb_shadow[number],                              \
-       .__current = &init_task,                                            \
-}
-
-struct paca_struct paca[] = {
-       PACA_INIT(0),
-#if NR_CPUS > 1
-       PACA_INIT(  1), PACA_INIT(  2), PACA_INIT(  3),
-#if NR_CPUS > 4
-       PACA_INIT(  4), PACA_INIT(  5), PACA_INIT(  6), PACA_INIT(  7),
-#if NR_CPUS > 8
-       PACA_INIT(  8), PACA_INIT(  9), PACA_INIT( 10), PACA_INIT( 11),
-       PACA_INIT( 12), PACA_INIT( 13), PACA_INIT( 14), PACA_INIT( 15),
-       PACA_INIT( 16), PACA_INIT( 17), PACA_INIT( 18), PACA_INIT( 19),
-       PACA_INIT( 20), PACA_INIT( 21), PACA_INIT( 22), PACA_INIT( 23),
-       PACA_INIT( 24), PACA_INIT( 25), PACA_INIT( 26), PACA_INIT( 27),
-       PACA_INIT( 28), PACA_INIT( 29), PACA_INIT( 30), PACA_INIT( 31),
-#if NR_CPUS > 32
-       PACA_INIT( 32), PACA_INIT( 33), PACA_INIT( 34), PACA_INIT( 35),
-       PACA_INIT( 36), PACA_INIT( 37), PACA_INIT( 38), PACA_INIT( 39),
-       PACA_INIT( 40), PACA_INIT( 41), PACA_INIT( 42), PACA_INIT( 43),
-       PACA_INIT( 44), PACA_INIT( 45), PACA_INIT( 46), PACA_INIT( 47),
-       PACA_INIT( 48), PACA_INIT( 49), PACA_INIT( 50), PACA_INIT( 51),
-       PACA_INIT( 52), PACA_INIT( 53), PACA_INIT( 54), PACA_INIT( 55),
-       PACA_INIT( 56), PACA_INIT( 57), PACA_INIT( 58), PACA_INIT( 59),
-       PACA_INIT( 60), PACA_INIT( 61), PACA_INIT( 62), PACA_INIT( 63),
-#if NR_CPUS > 64
-       PACA_INIT( 64), PACA_INIT( 65), PACA_INIT( 66), PACA_INIT( 67),
-       PACA_INIT( 68), PACA_INIT( 69), PACA_INIT( 70), PACA_INIT( 71),
-       PACA_INIT( 72), PACA_INIT( 73), PACA_INIT( 74), PACA_INIT( 75),
-       PACA_INIT( 76), PACA_INIT( 77), PACA_INIT( 78), PACA_INIT( 79),
-       PACA_INIT( 80), PACA_INIT( 81), PACA_INIT( 82), PACA_INIT( 83),
-       PACA_INIT( 84), PACA_INIT( 85), PACA_INIT( 86), PACA_INIT( 87),
-       PACA_INIT( 88), PACA_INIT( 89), PACA_INIT( 90), PACA_INIT( 91),
-       PACA_INIT( 92), PACA_INIT( 93), PACA_INIT( 94), PACA_INIT( 95),
-       PACA_INIT( 96), PACA_INIT( 97), PACA_INIT( 98), PACA_INIT( 99),
-       PACA_INIT(100), PACA_INIT(101), PACA_INIT(102), PACA_INIT(103),
-       PACA_INIT(104), PACA_INIT(105), PACA_INIT(106), PACA_INIT(107),
-       PACA_INIT(108), PACA_INIT(109), PACA_INIT(110), PACA_INIT(111),
-       PACA_INIT(112), PACA_INIT(113), PACA_INIT(114), PACA_INIT(115),
-       PACA_INIT(116), PACA_INIT(117), PACA_INIT(118), PACA_INIT(119),
-       PACA_INIT(120), PACA_INIT(121), PACA_INIT(122), PACA_INIT(123),
-       PACA_INIT(124), PACA_INIT(125), PACA_INIT(126), PACA_INIT(127),
-#endif
-#endif
-#endif
-#endif
-#endif
-};
+struct paca_struct paca[NR_CPUS];
 EXPORT_SYMBOL(paca);
+
+void __init initialise_pacas(void)
+{
+       int cpu;
+
+       /* The TOC register (GPR2) points 32kB into the TOC, so that 64kB
+        * of the TOC can be addressed using a single machine instruction.
+        */
+       unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL;
+
+       /* Can't use for_each_*_cpu, as they aren't functional yet */
+       for (cpu = 0; cpu < NR_CPUS; cpu++) {
+               struct paca_struct *new_paca = &paca[cpu];
+
+               new_paca->lppaca_ptr = &lppaca[cpu];
+               new_paca->lock_token = 0x8000;
+               new_paca->paca_index = cpu;
+               new_paca->kernel_toc = kernel_toc;
+               new_paca->hw_cpu_id = 0xffff;
+               new_paca->slb_shadow_ptr = &slb_shadow[cpu];
+               new_paca->__current = &init_task;
+
+       }
+}
index fda05e2211d69765820dce45dc0affc89d1bf68b..90e5627717911a6bdb80c761d71183a4d7ec61e6 100644 (file)
@@ -135,6 +135,4 @@ struct ucontext32 {
        struct mcontext32       uc_mcontext;
 };
 
-extern int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s);
-
 #endif  /* _PPC64_PPC32_H */
index 703100d5e4589c4e1f7566d0b720e05c560bf07d..6caad17ea72e6b0159461a84023c28ab454c637f 100644 (file)
@@ -1033,3 +1033,34 @@ void ppc64_runlatch_off(void)
        }
 }
 #endif
+
+#if THREAD_SHIFT < PAGE_SHIFT
+
+static struct kmem_cache *thread_info_cache;
+
+struct thread_info *alloc_thread_info(struct task_struct *tsk)
+{
+       struct thread_info *ti;
+
+       ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL);
+       if (unlikely(ti == NULL))
+               return NULL;
+#ifdef CONFIG_DEBUG_STACK_USAGE
+       memset(ti, 0, THREAD_SIZE);
+#endif
+       return ti;
+}
+
+void free_thread_info(struct thread_info *ti)
+{
+       kmem_cache_free(thread_info_cache, ti);
+}
+
+void thread_info_cache_init(void)
+{
+       thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
+                                             THREAD_SIZE, 0, NULL);
+       BUG_ON(thread_info_cache == NULL);
+}
+
+#endif /* THREAD_SHIFT < PAGE_SHIFT */
index 3bfe7837e8207978062b0d8426a0f50b04b6c448..2aefe2a4129a7fc4bd563db0a92f5a8ded54801e 100644 (file)
@@ -53,6 +53,7 @@
 #include <asm/pci-bridge.h>
 #include <asm/phyp_dump.h>
 #include <asm/kexec.h>
+#include <mm/mmu_decl.h>
 
 #ifdef DEBUG
 #define DBG(fmt...) printk(KERN_ERR fmt)
@@ -978,7 +979,10 @@ static int __init early_init_dt_scan_memory(unsigned long node,
                }
 #endif
                lmb_add(base, size);
+
+               memstart_addr = min((u64)memstart_addr, base);
        }
+
        return 0;
 }
 
diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh
new file mode 100644 (file)
index 0000000..8e24fc1
--- /dev/null
@@ -0,0 +1,58 @@
+#!/bin/sh
+#
+# Copyright Â© 2008 IBM Corporation
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+
+# This script checks prom_init.o to see what external symbols it
+# is using, if it finds symbols not in the whitelist it returns
+# an error. The point of this is to discourage people from
+# intentionally or accidentally adding new code to prom_init.c
+# which has side effects on other parts of the kernel.
+
+# If you really need to reference something from prom_init.o add
+# it to the list below:
+
+WHITELIST="add_reloc_offset __bss_start __bss_stop copy_and_flush
+_end enter_prom memcpy memset reloc_offset __secondary_hold
+__secondary_hold_acknowledge __secondary_hold_spinloop __start
+strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224
+reloc_got2"
+
+NM="$1"
+OBJ="$2"
+
+ERROR=0
+
+for UNDEF in $($NM -u $OBJ | awk '{print $2}')
+do
+       # On 64-bit nm gives us the function descriptors, which have
+       # a leading . on the name, so strip it off here.
+       UNDEF="${UNDEF#.}"
+
+       if [ $KBUILD_VERBOSE ]; then
+               if [ $KBUILD_VERBOSE -ne 0 ]; then
+                       echo "Checking prom_init.o symbol '$UNDEF'"
+               fi
+       fi
+
+       OK=0
+       for WHITE in $WHITELIST
+       do
+               if [ "$UNDEF" = "$WHITE" ]; then
+                       OK=1
+                       break
+               fi
+       done
+
+       if [ $OK -eq 0 ]; then
+               ERROR=1
+               echo "Error: External symbol '$UNDEF' referenced" \
+                    "from prom_init.c" >&2
+       fi
+done
+
+exit $ERROR
index 9d30e10970ac5b12d522fe30834f270ddf560571..4c1de6af4c092da35128e6ae553af27a3dcb9baf 100644 (file)
 #include <linux/security.h>
 #include <linux/signal.h>
 #include <linux/compat.h>
-#include <linux/elf.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 
-#include "ppc32.h"
-
 /*
  * does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
@@ -67,27 +64,6 @@ static long compat_ptrace_old(struct task_struct *child, long request,
        return -EPERM;
 }
 
-static int compat_ptrace_getsiginfo(struct task_struct *child, compat_siginfo_t __user *data)
-{
-       siginfo_t lastinfo;
-       int error = -ESRCH;
-
-       read_lock(&tasklist_lock);
-       if (likely(child->sighand != NULL)) {
-               error = -EINVAL;
-               spin_lock_irq(&child->sighand->siglock);
-               if (likely(child->last_siginfo != NULL)) {
-                       lastinfo = *child->last_siginfo;
-                       error = 0;
-               }
-               spin_unlock_irq(&child->sighand->siglock);
-       }
-       read_unlock(&tasklist_lock);
-       if (!error)
-               return copy_siginfo_to_user32(data, &lastinfo);
-       return error;
-}
-
 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                        compat_ulong_t caddr, compat_ulong_t cdata)
 {
@@ -306,9 +282,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                        0, PT_REGS_COUNT * sizeof(compat_long_t),
                        compat_ptr(data));
 
-       case PTRACE_GETSIGINFO:
-               return compat_ptrace_getsiginfo(child, compat_ptr(data));
-
        case PTRACE_GETFPREGS:
        case PTRACE_SETFPREGS:
        case PTRACE_GETVRREGS:
index 31ada9fdfc5c960a01d331f47574ad3ffcf5df96..dff6308d1b5eb524f44fbaf5dfa0a0866e5e58b5 100644 (file)
@@ -170,6 +170,9 @@ void __init setup_paca(int cpu)
 
 void __init early_setup(unsigned long dt_ptr)
 {
+       /* Fill in any unititialised pacas */
+       initialise_pacas();
+
        /* Identify CPU type */
        identify_cpu(0, mfspr(SPRN_PVR));
 
@@ -435,7 +438,7 @@ void __init setup_system(void)
                printk("htab_address                  = 0x%p\n", htab_address);
        printk("htab_hash_mask                = 0x%lx\n", htab_hash_mask);
 #if PHYSICAL_START > 0
-       printk("physical_start                = 0x%x\n", PHYSICAL_START);
+       printk("physical_start                = 0x%lx\n", PHYSICAL_START);
 #endif
        printk("-----------------------------------------------------\n");
 
index e3638eeaaae7e9e1a1d8ad1b41a201ff0e3dcba1..962944038430f69861181623763abb5f16f98049 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/sched.h>
 #include <linux/stacktrace.h>
 #include <asm/ptrace.h>
-#include <asm/asm-offsets.h>
 
 /*
  * Save stack-backtrace addresses into a stack_trace buffer.
index 7aad6203e411e926580dba0517deb918d3558a83..7d6c9bb8c77fe4f6f220b81d82b282f70e26b83f 100644 (file)
@@ -154,8 +154,8 @@ static void udbg_console_write(struct console *con, const char *s,
 static struct console udbg_console = {
        .name   = "udbg",
        .write  = udbg_console_write,
-       .flags  = CON_PRINTBUFFER | CON_ENABLED | CON_BOOT,
-       .index  = -1,
+       .flags  = CON_PRINTBUFFER | CON_ENABLED | CON_BOOT | CON_ANYTIME,
+       .index  = 0,
 };
 
 static int early_console_initialized;
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c
new file mode 100644 (file)
index 0000000..f5d7a5e
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kvm_host.h>
+#include <linux/highmem.h>
+#include <asm/mmu-44x.h>
+#include <asm/kvm_ppc.h>
+
+#include "44x_tlb.h"
+
+#define PPC44x_TLB_USER_PERM_MASK (PPC44x_TLB_UX|PPC44x_TLB_UR|PPC44x_TLB_UW)
+#define PPC44x_TLB_SUPER_PERM_MASK (PPC44x_TLB_SX|PPC44x_TLB_SR|PPC44x_TLB_SW)
+
+static unsigned int kvmppc_tlb_44x_pos;
+
+static u32 kvmppc_44x_tlb_shadow_attrib(u32 attrib, int usermode)
+{
+       /* Mask off reserved bits. */
+       attrib &= PPC44x_TLB_PERM_MASK|PPC44x_TLB_ATTR_MASK;
+
+       if (!usermode) {
+               /* Guest is in supervisor mode, so we need to translate guest
+                * supervisor permissions into user permissions. */
+               attrib &= ~PPC44x_TLB_USER_PERM_MASK;
+               attrib |= (attrib & PPC44x_TLB_SUPER_PERM_MASK) << 3;
+       }
+
+       /* Make sure host can always access this memory. */
+       attrib |= PPC44x_TLB_SX|PPC44x_TLB_SR|PPC44x_TLB_SW;
+
+       return attrib;
+}
+
+/* Search the guest TLB for a matching entry. */
+int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr, unsigned int pid,
+                         unsigned int as)
+{
+       int i;
+
+       /* XXX Replace loop with fancy data structures. */
+       for (i = 0; i < PPC44x_TLB_SIZE; i++) {
+               struct tlbe *tlbe = &vcpu->arch.guest_tlb[i];
+               unsigned int tid;
+
+               if (eaddr < get_tlb_eaddr(tlbe))
+                       continue;
+
+               if (eaddr > get_tlb_end(tlbe))
+                       continue;
+
+               tid = get_tlb_tid(tlbe);
+               if (tid && (tid != pid))
+                       continue;
+
+               if (!get_tlb_v(tlbe))
+                       continue;
+
+               if (get_tlb_ts(tlbe) != as)
+                       continue;
+
+               return i;
+       }
+
+       return -1;
+}
+
+struct tlbe *kvmppc_44x_itlb_search(struct kvm_vcpu *vcpu, gva_t eaddr)
+{
+       unsigned int as = !!(vcpu->arch.msr & MSR_IS);
+       unsigned int index;
+
+       index = kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
+       if (index == -1)
+               return NULL;
+       return &vcpu->arch.guest_tlb[index];
+}
+
+struct tlbe *kvmppc_44x_dtlb_search(struct kvm_vcpu *vcpu, gva_t eaddr)
+{
+       unsigned int as = !!(vcpu->arch.msr & MSR_DS);
+       unsigned int index;
+
+       index = kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
+       if (index == -1)
+               return NULL;
+       return &vcpu->arch.guest_tlb[index];
+}
+
+static int kvmppc_44x_tlbe_is_writable(struct tlbe *tlbe)
+{
+       return tlbe->word2 & (PPC44x_TLB_SW|PPC44x_TLB_UW);
+}
+
+/* Must be called with mmap_sem locked for writing. */
+static void kvmppc_44x_shadow_release(struct kvm_vcpu *vcpu,
+                                      unsigned int index)
+{
+       struct tlbe *stlbe = &vcpu->arch.shadow_tlb[index];
+       struct page *page = vcpu->arch.shadow_pages[index];
+
+       kunmap(vcpu->arch.shadow_pages[index]);
+
+       if (get_tlb_v(stlbe)) {
+               if (kvmppc_44x_tlbe_is_writable(stlbe))
+                       kvm_release_page_dirty(page);
+               else
+                       kvm_release_page_clean(page);
+       }
+}
+
+/* Caller must ensure that the specified guest TLB entry is safe to insert into
+ * the shadow TLB. */
+void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid,
+                    u32 flags)
+{
+       struct page *new_page;
+       struct tlbe *stlbe;
+       hpa_t hpaddr;
+       unsigned int victim;
+
+       /* Future optimization: don't overwrite the TLB entry containing the
+        * current PC (or stack?). */
+       victim = kvmppc_tlb_44x_pos++;
+       if (kvmppc_tlb_44x_pos > tlb_44x_hwater)
+               kvmppc_tlb_44x_pos = 0;
+       stlbe = &vcpu->arch.shadow_tlb[victim];
+
+       /* Get reference to new page. */
+       down_write(&current->mm->mmap_sem);
+       new_page = gfn_to_page(vcpu->kvm, gfn);
+       if (is_error_page(new_page)) {
+               printk(KERN_ERR "Couldn't get guest page!\n");
+               kvm_release_page_clean(new_page);
+               return;
+       }
+       hpaddr = page_to_phys(new_page);
+
+       /* Drop reference to old page. */
+       kvmppc_44x_shadow_release(vcpu, victim);
+       up_write(&current->mm->mmap_sem);
+
+       vcpu->arch.shadow_pages[victim] = new_page;
+
+       /* XXX Make sure (va, size) doesn't overlap any other
+        * entries. 440x6 user manual says the result would be
+        * "undefined." */
+
+       /* XXX what about AS? */
+
+       stlbe->tid = asid & 0xff;
+
+       /* Force TS=1 for all guest mappings. */
+       /* For now we hardcode 4KB mappings, but it will be important to
+        * use host large pages in the future. */
+       stlbe->word0 = (gvaddr & PAGE_MASK) | PPC44x_TLB_VALID | PPC44x_TLB_TS
+                      | PPC44x_TLB_4K;
+
+       stlbe->word1 = (hpaddr & 0xfffffc00) | ((hpaddr >> 32) & 0xf);
+       stlbe->word2 = kvmppc_44x_tlb_shadow_attrib(flags,
+                                                   vcpu->arch.msr & MSR_PR);
+}
+
+void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, u64 eaddr, u64 asid)
+{
+       unsigned int pid = asid & 0xff;
+       int i;
+
+       /* XXX Replace loop with fancy data structures. */
+       down_write(&current->mm->mmap_sem);
+       for (i = 0; i <= tlb_44x_hwater; i++) {
+               struct tlbe *stlbe = &vcpu->arch.shadow_tlb[i];
+               unsigned int tid;
+
+               if (!get_tlb_v(stlbe))
+                       continue;
+
+               if (eaddr < get_tlb_eaddr(stlbe))
+                       continue;
+
+               if (eaddr > get_tlb_end(stlbe))
+                       continue;
+
+               tid = get_tlb_tid(stlbe);
+               if (tid && (tid != pid))
+                       continue;
+
+               kvmppc_44x_shadow_release(vcpu, i);
+               stlbe->word0 = 0;
+       }
+       up_write(&current->mm->mmap_sem);
+}
+
+/* Invalidate all mappings, so that when they fault back in they will get the
+ * proper permission bits. */
+void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode)
+{
+       int i;
+
+       /* XXX Replace loop with fancy data structures. */
+       down_write(&current->mm->mmap_sem);
+       for (i = 0; i <= tlb_44x_hwater; i++) {
+               kvmppc_44x_shadow_release(vcpu, i);
+               vcpu->arch.shadow_tlb[i].word0 = 0;
+       }
+       up_write(&current->mm->mmap_sem);
+}
diff --git a/arch/powerpc/kvm/44x_tlb.h b/arch/powerpc/kvm/44x_tlb.h
new file mode 100644 (file)
index 0000000..2ccd46b
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#ifndef __KVM_POWERPC_TLB_H__
+#define __KVM_POWERPC_TLB_H__
+
+#include <linux/kvm_host.h>
+#include <asm/mmu-44x.h>
+
+extern int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr,
+                                unsigned int pid, unsigned int as);
+extern struct tlbe *kvmppc_44x_dtlb_search(struct kvm_vcpu *vcpu, gva_t eaddr);
+extern struct tlbe *kvmppc_44x_itlb_search(struct kvm_vcpu *vcpu, gva_t eaddr);
+
+/* TLB helper functions */
+static inline unsigned int get_tlb_size(const struct tlbe *tlbe)
+{
+       return (tlbe->word0 >> 4) & 0xf;
+}
+
+static inline gva_t get_tlb_eaddr(const struct tlbe *tlbe)
+{
+       return tlbe->word0 & 0xfffffc00;
+}
+
+static inline gva_t get_tlb_bytes(const struct tlbe *tlbe)
+{
+       unsigned int pgsize = get_tlb_size(tlbe);
+       return 1 << 10 << (pgsize << 1);
+}
+
+static inline gva_t get_tlb_end(const struct tlbe *tlbe)
+{
+       return get_tlb_eaddr(tlbe) + get_tlb_bytes(tlbe) - 1;
+}
+
+static inline u64 get_tlb_raddr(const struct tlbe *tlbe)
+{
+       u64 word1 = tlbe->word1;
+       return ((word1 & 0xf) << 32) | (word1 & 0xfffffc00);
+}
+
+static inline unsigned int get_tlb_tid(const struct tlbe *tlbe)
+{
+       return tlbe->tid & 0xff;
+}
+
+static inline unsigned int get_tlb_ts(const struct tlbe *tlbe)
+{
+       return (tlbe->word0 >> 8) & 0x1;
+}
+
+static inline unsigned int get_tlb_v(const struct tlbe *tlbe)
+{
+       return (tlbe->word0 >> 9) & 0x1;
+}
+
+static inline unsigned int get_mmucr_stid(const struct kvm_vcpu *vcpu)
+{
+       return vcpu->arch.mmucr & 0xff;
+}
+
+static inline unsigned int get_mmucr_sts(const struct kvm_vcpu *vcpu)
+{
+       return (vcpu->arch.mmucr >> 16) & 0x1;
+}
+
+static inline gpa_t tlb_xlate(struct tlbe *tlbe, gva_t eaddr)
+{
+       unsigned int pgmask = get_tlb_bytes(tlbe) - 1;
+
+       return get_tlb_raddr(tlbe) | (eaddr & pgmask);
+}
+
+#endif /* __KVM_POWERPC_TLB_H__ */
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
new file mode 100644 (file)
index 0000000..6b07601
--- /dev/null
@@ -0,0 +1,42 @@
+#
+# KVM configuration
+#
+
+menuconfig VIRTUALIZATION
+       bool "Virtualization"
+       ---help---
+         Say Y here to get to see options for using your Linux host to run
+         other operating systems inside virtual machines (guests).
+         This option alone does not add any kernel code.
+
+         If you say N, all options in this submenu will be skipped and
+         disabled.
+
+if VIRTUALIZATION
+
+config KVM
+       bool "Kernel-based Virtual Machine (KVM) support"
+       depends on 44x && EXPERIMENTAL
+       select PREEMPT_NOTIFIERS
+       select ANON_INODES
+       # We can only run on Book E hosts so far
+       select KVM_BOOKE_HOST
+       ---help---
+         Support hosting virtualized guest machines. You will also
+         need to select one or more of the processor modules below.
+
+         This module provides access to the hardware capabilities through
+         a character device node named /dev/kvm.
+
+         If unsure, say N.
+
+config KVM_BOOKE_HOST
+       bool "KVM host support for Book E PowerPC processors"
+       depends on KVM && 44x
+       ---help---
+         Provides host support for KVM on Book E PowerPC processors. Currently
+         this works on 440 processors only.
+
+source drivers/virtio/Kconfig
+
+endif # VIRTUALIZATION
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
new file mode 100644 (file)
index 0000000..d0d358d
--- /dev/null
@@ -0,0 +1,15 @@
+#
+# Makefile for Kernel-based Virtual Machine module
+#
+
+EXTRA_CFLAGS += -Ivirt/kvm -Iarch/powerpc/kvm
+
+common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o)
+
+kvm-objs := $(common-objs) powerpc.o emulate.o booke_guest.o
+obj-$(CONFIG_KVM) += kvm.o
+
+AFLAGS_booke_interrupts.o := -I$(obj)
+
+kvm-booke-host-objs := booke_host.o booke_interrupts.o 44x_tlb.o
+obj-$(CONFIG_KVM_BOOKE_HOST) += kvm-booke-host.o
diff --git a/arch/powerpc/kvm/booke_guest.c b/arch/powerpc/kvm/booke_guest.c
new file mode 100644 (file)
index 0000000..6d9884a
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ *          Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
+ */
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/kvm_host.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <asm/cputable.h>
+#include <asm/uaccess.h>
+#include <asm/kvm_ppc.h>
+
+#include "44x_tlb.h"
+
+#define VM_STAT(x) offsetof(struct kvm, stat.x), KVM_STAT_VM
+#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
+
+struct kvm_stats_debugfs_item debugfs_entries[] = {
+       { "exits",      VCPU_STAT(sum_exits) },
+       { "mmio",       VCPU_STAT(mmio_exits) },
+       { "dcr",        VCPU_STAT(dcr_exits) },
+       { "sig",        VCPU_STAT(signal_exits) },
+       { "light",      VCPU_STAT(light_exits) },
+       { "itlb_r",     VCPU_STAT(itlb_real_miss_exits) },
+       { "itlb_v",     VCPU_STAT(itlb_virt_miss_exits) },
+       { "dtlb_r",     VCPU_STAT(dtlb_real_miss_exits) },
+       { "dtlb_v",     VCPU_STAT(dtlb_virt_miss_exits) },
+       { "sysc",       VCPU_STAT(syscall_exits) },
+       { "isi",        VCPU_STAT(isi_exits) },
+       { "dsi",        VCPU_STAT(dsi_exits) },
+       { "inst_emu",   VCPU_STAT(emulated_inst_exits) },
+       { "dec",        VCPU_STAT(dec_exits) },
+       { "ext_intr",   VCPU_STAT(ext_intr_exits) },
+       { NULL }
+};
+
+static const u32 interrupt_msr_mask[16] = {
+       [BOOKE_INTERRUPT_CRITICAL]      = MSR_ME,
+       [BOOKE_INTERRUPT_MACHINE_CHECK] = 0,
+       [BOOKE_INTERRUPT_DATA_STORAGE]  = MSR_CE|MSR_ME|MSR_DE,
+       [BOOKE_INTERRUPT_INST_STORAGE]  = MSR_CE|MSR_ME|MSR_DE,
+       [BOOKE_INTERRUPT_EXTERNAL]      = MSR_CE|MSR_ME|MSR_DE,
+       [BOOKE_INTERRUPT_ALIGNMENT]     = MSR_CE|MSR_ME|MSR_DE,
+       [BOOKE_INTERRUPT_PROGRAM]       = MSR_CE|MSR_ME|MSR_DE,
+       [BOOKE_INTERRUPT_FP_UNAVAIL]    = MSR_CE|MSR_ME|MSR_DE,
+       [BOOKE_INTERRUPT_SYSCALL]       = MSR_CE|MSR_ME|MSR_DE,
+       [BOOKE_INTERRUPT_AP_UNAVAIL]    = MSR_CE|MSR_ME|MSR_DE,
+       [BOOKE_INTERRUPT_DECREMENTER]   = MSR_CE|MSR_ME|MSR_DE,
+       [BOOKE_INTERRUPT_FIT]           = MSR_CE|MSR_ME|MSR_DE,
+       [BOOKE_INTERRUPT_WATCHDOG]      = MSR_ME,
+       [BOOKE_INTERRUPT_DTLB_MISS]     = MSR_CE|MSR_ME|MSR_DE,
+       [BOOKE_INTERRUPT_ITLB_MISS]     = MSR_CE|MSR_ME|MSR_DE,
+       [BOOKE_INTERRUPT_DEBUG]         = MSR_ME,
+};
+
+const unsigned char exception_priority[] = {
+       [BOOKE_INTERRUPT_DATA_STORAGE] = 0,
+       [BOOKE_INTERRUPT_INST_STORAGE] = 1,
+       [BOOKE_INTERRUPT_ALIGNMENT] = 2,
+       [BOOKE_INTERRUPT_PROGRAM] = 3,
+       [BOOKE_INTERRUPT_FP_UNAVAIL] = 4,
+       [BOOKE_INTERRUPT_SYSCALL] = 5,
+       [BOOKE_INTERRUPT_AP_UNAVAIL] = 6,
+       [BOOKE_INTERRUPT_DTLB_MISS] = 7,
+       [BOOKE_INTERRUPT_ITLB_MISS] = 8,
+       [BOOKE_INTERRUPT_MACHINE_CHECK] = 9,
+       [BOOKE_INTERRUPT_DEBUG] = 10,
+       [BOOKE_INTERRUPT_CRITICAL] = 11,
+       [BOOKE_INTERRUPT_WATCHDOG] = 12,
+       [BOOKE_INTERRUPT_EXTERNAL] = 13,
+       [BOOKE_INTERRUPT_FIT] = 14,
+       [BOOKE_INTERRUPT_DECREMENTER] = 15,
+};
+
+const unsigned char priority_exception[] = {
+       BOOKE_INTERRUPT_DATA_STORAGE,
+       BOOKE_INTERRUPT_INST_STORAGE,
+       BOOKE_INTERRUPT_ALIGNMENT,
+       BOOKE_INTERRUPT_PROGRAM,
+       BOOKE_INTERRUPT_FP_UNAVAIL,
+       BOOKE_INTERRUPT_SYSCALL,
+       BOOKE_INTERRUPT_AP_UNAVAIL,
+       BOOKE_INTERRUPT_DTLB_MISS,
+       BOOKE_INTERRUPT_ITLB_MISS,
+       BOOKE_INTERRUPT_MACHINE_CHECK,
+       BOOKE_INTERRUPT_DEBUG,
+       BOOKE_INTERRUPT_CRITICAL,
+       BOOKE_INTERRUPT_WATCHDOG,
+       BOOKE_INTERRUPT_EXTERNAL,
+       BOOKE_INTERRUPT_FIT,
+       BOOKE_INTERRUPT_DECREMENTER,
+};
+
+
+void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu)
+{
+       struct tlbe *tlbe;
+       int i;
+
+       printk("vcpu %d TLB dump:\n", vcpu->vcpu_id);
+       printk("| %2s | %3s | %8s | %8s | %8s |\n",
+                       "nr", "tid", "word0", "word1", "word2");
+
+       for (i = 0; i < PPC44x_TLB_SIZE; i++) {
+               tlbe = &vcpu->arch.guest_tlb[i];
+               if (tlbe->word0 & PPC44x_TLB_VALID)
+                       printk(" G%2d |  %02X | %08X | %08X | %08X |\n",
+                              i, tlbe->tid, tlbe->word0, tlbe->word1,
+                              tlbe->word2);
+       }
+
+       for (i = 0; i < PPC44x_TLB_SIZE; i++) {
+               tlbe = &vcpu->arch.shadow_tlb[i];
+               if (tlbe->word0 & PPC44x_TLB_VALID)
+                       printk(" S%2d | %02X | %08X | %08X | %08X |\n",
+                              i, tlbe->tid, tlbe->word0, tlbe->word1,
+                              tlbe->word2);
+       }
+}
+
+/* TODO: use vcpu_printf() */
+void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu)
+{
+       int i;
+
+       printk("pc:   %08x msr:  %08x\n", vcpu->arch.pc, vcpu->arch.msr);
+       printk("lr:   %08x ctr:  %08x\n", vcpu->arch.lr, vcpu->arch.ctr);
+       printk("srr0: %08x srr1: %08x\n", vcpu->arch.srr0, vcpu->arch.srr1);
+
+       printk("exceptions: %08lx\n", vcpu->arch.pending_exceptions);
+
+       for (i = 0; i < 32; i += 4) {
+               printk("gpr%02d: %08x %08x %08x %08x\n", i,
+                      vcpu->arch.gpr[i],
+                      vcpu->arch.gpr[i+1],
+                      vcpu->arch.gpr[i+2],
+                      vcpu->arch.gpr[i+3]);
+       }
+}
+
+/* Check if we are ready to deliver the interrupt */
+static int kvmppc_can_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt)
+{
+       int r;
+
+       switch (interrupt) {
+       case BOOKE_INTERRUPT_CRITICAL:
+               r = vcpu->arch.msr & MSR_CE;
+               break;
+       case BOOKE_INTERRUPT_MACHINE_CHECK:
+               r = vcpu->arch.msr & MSR_ME;
+               break;
+       case BOOKE_INTERRUPT_EXTERNAL:
+               r = vcpu->arch.msr & MSR_EE;
+               break;
+       case BOOKE_INTERRUPT_DECREMENTER:
+               r = vcpu->arch.msr & MSR_EE;
+               break;
+       case BOOKE_INTERRUPT_FIT:
+               r = vcpu->arch.msr & MSR_EE;
+               break;
+       case BOOKE_INTERRUPT_WATCHDOG:
+               r = vcpu->arch.msr & MSR_CE;
+               break;
+       case BOOKE_INTERRUPT_DEBUG:
+               r = vcpu->arch.msr & MSR_DE;
+               break;
+       default:
+               r = 1;
+       }
+
+       return r;
+}
+
+static void kvmppc_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt)
+{
+       switch (interrupt) {
+       case BOOKE_INTERRUPT_DECREMENTER:
+               vcpu->arch.tsr |= TSR_DIS;
+               break;
+       }
+
+       vcpu->arch.srr0 = vcpu->arch.pc;
+       vcpu->arch.srr1 = vcpu->arch.msr;
+       vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[interrupt];
+       kvmppc_set_msr(vcpu, vcpu->arch.msr & interrupt_msr_mask[interrupt]);
+}
+
+/* Check pending exceptions and deliver one, if possible. */
+void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu)
+{
+       unsigned long *pending = &vcpu->arch.pending_exceptions;
+       unsigned int exception;
+       unsigned int priority;
+
+       priority = find_first_bit(pending, BITS_PER_BYTE * sizeof(*pending));
+       while (priority <= BOOKE_MAX_INTERRUPT) {
+               exception = priority_exception[priority];
+               if (kvmppc_can_deliver_interrupt(vcpu, exception)) {
+                       kvmppc_clear_exception(vcpu, exception);
+                       kvmppc_deliver_interrupt(vcpu, exception);
+                       break;
+               }
+
+               priority = find_next_bit(pending,
+                                        BITS_PER_BYTE * sizeof(*pending),
+                                        priority + 1);
+       }
+}
+
+static int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+       enum emulation_result er;
+       int r;
+
+       er = kvmppc_emulate_instruction(run, vcpu);
+       switch (er) {
+       case EMULATE_DONE:
+               /* Future optimization: only reload non-volatiles if they were
+                * actually modified. */
+               r = RESUME_GUEST_NV;
+               break;
+       case EMULATE_DO_MMIO:
+               run->exit_reason = KVM_EXIT_MMIO;
+               /* We must reload nonvolatiles because "update" load/store
+                * instructions modify register state. */
+               /* Future optimization: only reload non-volatiles if they were
+                * actually modified. */
+               r = RESUME_HOST_NV;
+               break;
+       case EMULATE_FAIL:
+               /* XXX Deliver Program interrupt to guest. */
+               printk(KERN_EMERG "%s: emulation failed (%08x)\n", __func__,
+                      vcpu->arch.last_inst);
+               r = RESUME_HOST;
+               break;
+       default:
+               BUG();
+       }
+
+       return r;
+}
+
+/**
+ * kvmppc_handle_exit
+ *
+ * Return value is in the form (errcode<<2 | RESUME_FLAG_HOST | RESUME_FLAG_NV)
+ */
+int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
+                       unsigned int exit_nr)
+{
+       enum emulation_result er;
+       int r = RESUME_HOST;
+
+       local_irq_enable();
+
+       run->exit_reason = KVM_EXIT_UNKNOWN;
+       run->ready_for_interrupt_injection = 1;
+
+       switch (exit_nr) {
+       case BOOKE_INTERRUPT_MACHINE_CHECK:
+               printk("MACHINE CHECK: %lx\n", mfspr(SPRN_MCSR));
+               kvmppc_dump_vcpu(vcpu);
+               r = RESUME_HOST;
+               break;
+
+       case BOOKE_INTERRUPT_EXTERNAL:
+       case BOOKE_INTERRUPT_DECREMENTER:
+               /* Since we switched IVPR back to the host's value, the host
+                * handled this interrupt the moment we enabled interrupts.
+                * Now we just offer it a chance to reschedule the guest. */
+
+               /* XXX At this point the TLB still holds our shadow TLB, so if
+                * we do reschedule the host will fault over it. Perhaps we
+                * should politely restore the host's entries to minimize
+                * misses before ceding control. */
+               if (need_resched())
+                       cond_resched();
+               if (exit_nr == BOOKE_INTERRUPT_DECREMENTER)
+                       vcpu->stat.dec_exits++;
+               else
+                       vcpu->stat.ext_intr_exits++;
+               r = RESUME_GUEST;
+               break;
+
+       case BOOKE_INTERRUPT_PROGRAM:
+               if (vcpu->arch.msr & MSR_PR) {
+                       /* Program traps generated by user-level software must be handled
+                        * by the guest kernel. */
+                       vcpu->arch.esr = vcpu->arch.fault_esr;
+                       kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM);
+                       r = RESUME_GUEST;
+                       break;
+               }
+
+               er = kvmppc_emulate_instruction(run, vcpu);
+               switch (er) {
+               case EMULATE_DONE:
+                       /* Future optimization: only reload non-volatiles if
+                        * they were actually modified by emulation. */
+                       vcpu->stat.emulated_inst_exits++;
+                       r = RESUME_GUEST_NV;
+                       break;
+               case EMULATE_DO_DCR:
+                       run->exit_reason = KVM_EXIT_DCR;
+                       r = RESUME_HOST;
+                       break;
+               case EMULATE_FAIL:
+                       /* XXX Deliver Program interrupt to guest. */
+                       printk(KERN_CRIT "%s: emulation at %x failed (%08x)\n",
+                              __func__, vcpu->arch.pc, vcpu->arch.last_inst);
+                       /* For debugging, encode the failing instruction and
+                        * report it to userspace. */
+                       run->hw.hardware_exit_reason = ~0ULL << 32;
+                       run->hw.hardware_exit_reason |= vcpu->arch.last_inst;
+                       r = RESUME_HOST;
+                       break;
+               default:
+                       BUG();
+               }
+               break;
+
+       case BOOKE_INTERRUPT_DATA_STORAGE:
+               vcpu->arch.dear = vcpu->arch.fault_dear;
+               vcpu->arch.esr = vcpu->arch.fault_esr;
+               kvmppc_queue_exception(vcpu, exit_nr);
+               vcpu->stat.dsi_exits++;
+               r = RESUME_GUEST;
+               break;
+
+       case BOOKE_INTERRUPT_INST_STORAGE:
+               vcpu->arch.esr = vcpu->arch.fault_esr;
+               kvmppc_queue_exception(vcpu, exit_nr);
+               vcpu->stat.isi_exits++;
+               r = RESUME_GUEST;
+               break;
+
+       case BOOKE_INTERRUPT_SYSCALL:
+               kvmppc_queue_exception(vcpu, exit_nr);
+               vcpu->stat.syscall_exits++;
+               r = RESUME_GUEST;
+               break;
+
+       case BOOKE_INTERRUPT_DTLB_MISS: {
+               struct tlbe *gtlbe;
+               unsigned long eaddr = vcpu->arch.fault_dear;
+               gfn_t gfn;
+
+               /* Check the guest TLB. */
+               gtlbe = kvmppc_44x_dtlb_search(vcpu, eaddr);
+               if (!gtlbe) {
+                       /* The guest didn't have a mapping for it. */
+                       kvmppc_queue_exception(vcpu, exit_nr);
+                       vcpu->arch.dear = vcpu->arch.fault_dear;
+                       vcpu->arch.esr = vcpu->arch.fault_esr;
+                       vcpu->stat.dtlb_real_miss_exits++;
+                       r = RESUME_GUEST;
+                       break;
+               }
+
+               vcpu->arch.paddr_accessed = tlb_xlate(gtlbe, eaddr);
+               gfn = vcpu->arch.paddr_accessed >> PAGE_SHIFT;
+
+               if (kvm_is_visible_gfn(vcpu->kvm, gfn)) {
+                       /* The guest TLB had a mapping, but the shadow TLB
+                        * didn't, and it is RAM. This could be because:
+                        * a) the entry is mapping the host kernel, or
+                        * b) the guest used a large mapping which we're faking
+                        * Either way, we need to satisfy the fault without
+                        * invoking the guest. */
+                       kvmppc_mmu_map(vcpu, eaddr, gfn, gtlbe->tid,
+                                      gtlbe->word2);
+                       vcpu->stat.dtlb_virt_miss_exits++;
+                       r = RESUME_GUEST;
+               } else {
+                       /* Guest has mapped and accessed a page which is not
+                        * actually RAM. */
+                       r = kvmppc_emulate_mmio(run, vcpu);
+               }
+
+               break;
+       }
+
+       case BOOKE_INTERRUPT_ITLB_MISS: {
+               struct tlbe *gtlbe;
+               unsigned long eaddr = vcpu->arch.pc;
+               gfn_t gfn;
+
+               r = RESUME_GUEST;
+
+               /* Check the guest TLB. */
+               gtlbe = kvmppc_44x_itlb_search(vcpu, eaddr);
+               if (!gtlbe) {
+                       /* The guest didn't have a mapping for it. */
+                       kvmppc_queue_exception(vcpu, exit_nr);
+                       vcpu->stat.itlb_real_miss_exits++;
+                       break;
+               }
+
+               vcpu->stat.itlb_virt_miss_exits++;
+
+               gfn = tlb_xlate(gtlbe, eaddr) >> PAGE_SHIFT;
+
+               if (kvm_is_visible_gfn(vcpu->kvm, gfn)) {
+                       /* The guest TLB had a mapping, but the shadow TLB
+                        * didn't. This could be because:
+                        * a) the entry is mapping the host kernel, or
+                        * b) the guest used a large mapping which we're faking
+                        * Either way, we need to satisfy the fault without
+                        * invoking the guest. */
+                       kvmppc_mmu_map(vcpu, eaddr, gfn, gtlbe->tid,
+                                      gtlbe->word2);
+               } else {
+                       /* Guest mapped and leaped at non-RAM! */
+                       kvmppc_queue_exception(vcpu,
+                                              BOOKE_INTERRUPT_MACHINE_CHECK);
+               }
+
+               break;
+       }
+
+       default:
+               printk(KERN_EMERG "exit_nr %d\n", exit_nr);
+               BUG();
+       }
+
+       local_irq_disable();
+
+       kvmppc_check_and_deliver_interrupts(vcpu);
+
+       /* Do some exit accounting. */
+       vcpu->stat.sum_exits++;
+       if (!(r & RESUME_HOST)) {
+               /* To avoid clobbering exit_reason, only check for signals if
+                * we aren't already exiting to userspace for some other
+                * reason. */
+               if (signal_pending(current)) {
+                       run->exit_reason = KVM_EXIT_INTR;
+                       r = (-EINTR << 2) | RESUME_HOST | (r & RESUME_FLAG_NV);
+
+                       vcpu->stat.signal_exits++;
+               } else {
+                       vcpu->stat.light_exits++;
+               }
+       } else {
+               switch (run->exit_reason) {
+               case KVM_EXIT_MMIO:
+                       vcpu->stat.mmio_exits++;
+                       break;
+               case KVM_EXIT_DCR:
+                       vcpu->stat.dcr_exits++;
+                       break;
+               case KVM_EXIT_INTR:
+                       vcpu->stat.signal_exits++;
+                       break;
+               }
+       }
+
+       return r;
+}
+
+/* Initial guest state: 16MB mapping 0 -> 0, PC = 0, MSR = 0, R1 = 16MB */
+int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
+{
+       struct tlbe *tlbe = &vcpu->arch.guest_tlb[0];
+
+       tlbe->tid = 0;
+       tlbe->word0 = PPC44x_TLB_16M | PPC44x_TLB_VALID;
+       tlbe->word1 = 0;
+       tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR;
+
+       tlbe++;
+       tlbe->tid = 0;
+       tlbe->word0 = 0xef600000 | PPC44x_TLB_4K | PPC44x_TLB_VALID;
+       tlbe->word1 = 0xef600000;
+       tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR
+                     | PPC44x_TLB_I | PPC44x_TLB_G;
+
+       vcpu->arch.pc = 0;
+       vcpu->arch.msr = 0;
+       vcpu->arch.gpr[1] = (16<<20) - 8; /* -8 for the callee-save LR slot */
+
+       /* Eye-catching number so we know if the guest takes an interrupt
+        * before it's programmed its own IVPR. */
+       vcpu->arch.ivpr = 0x55550000;
+
+       /* Since the guest can directly access the timebase, it must know the
+        * real timebase frequency. Accordingly, it must see the state of
+        * CCR1[TCS]. */
+       vcpu->arch.ccr1 = mfspr(SPRN_CCR1);
+
+       return 0;
+}
+
+int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+       int i;
+
+       regs->pc = vcpu->arch.pc;
+       regs->cr = vcpu->arch.cr;
+       regs->ctr = vcpu->arch.ctr;
+       regs->lr = vcpu->arch.lr;
+       regs->xer = vcpu->arch.xer;
+       regs->msr = vcpu->arch.msr;
+       regs->srr0 = vcpu->arch.srr0;
+       regs->srr1 = vcpu->arch.srr1;
+       regs->pid = vcpu->arch.pid;
+       regs->sprg0 = vcpu->arch.sprg0;
+       regs->sprg1 = vcpu->arch.sprg1;
+       regs->sprg2 = vcpu->arch.sprg2;
+       regs->sprg3 = vcpu->arch.sprg3;
+       regs->sprg5 = vcpu->arch.sprg4;
+       regs->sprg6 = vcpu->arch.sprg5;
+       regs->sprg7 = vcpu->arch.sprg6;
+
+       for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
+               regs->gpr[i] = vcpu->arch.gpr[i];
+
+       return 0;
+}
+
+int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+       int i;
+
+       vcpu->arch.pc = regs->pc;
+       vcpu->arch.cr = regs->cr;
+       vcpu->arch.ctr = regs->ctr;
+       vcpu->arch.lr = regs->lr;
+       vcpu->arch.xer = regs->xer;
+       vcpu->arch.msr = regs->msr;
+       vcpu->arch.srr0 = regs->srr0;
+       vcpu->arch.srr1 = regs->srr1;
+       vcpu->arch.sprg0 = regs->sprg0;
+       vcpu->arch.sprg1 = regs->sprg1;
+       vcpu->arch.sprg2 = regs->sprg2;
+       vcpu->arch.sprg3 = regs->sprg3;
+       vcpu->arch.sprg5 = regs->sprg4;
+       vcpu->arch.sprg6 = regs->sprg5;
+       vcpu->arch.sprg7 = regs->sprg6;
+
+       for (i = 0; i < ARRAY_SIZE(vcpu->arch.gpr); i++)
+               vcpu->arch.gpr[i] = regs->gpr[i];
+
+       return 0;
+}
+
+int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
+                                  struct kvm_sregs *sregs)
+{
+       return -ENOTSUPP;
+}
+
+int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
+                                  struct kvm_sregs *sregs)
+{
+       return -ENOTSUPP;
+}
+
+int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+       return -ENOTSUPP;
+}
+
+int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+       return -ENOTSUPP;
+}
+
+/* 'linear_address' is actually an encoding of AS|PID|EADDR . */
+int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
+                                  struct kvm_translation *tr)
+{
+       struct tlbe *gtlbe;
+       int index;
+       gva_t eaddr;
+       u8 pid;
+       u8 as;
+
+       eaddr = tr->linear_address;
+       pid = (tr->linear_address >> 32) & 0xff;
+       as = (tr->linear_address >> 40) & 0x1;
+
+       index = kvmppc_44x_tlb_index(vcpu, eaddr, pid, as);
+       if (index == -1) {
+               tr->valid = 0;
+               return 0;
+       }
+
+       gtlbe = &vcpu->arch.guest_tlb[index];
+
+       tr->physical_address = tlb_xlate(gtlbe, eaddr);
+       /* XXX what does "writeable" and "usermode" even mean? */
+       tr->valid = 1;
+
+       return 0;
+}
diff --git a/arch/powerpc/kvm/booke_host.c b/arch/powerpc/kvm/booke_host.c
new file mode 100644 (file)
index 0000000..b480341
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#include <linux/errno.h>
+#include <linux/kvm_host.h>
+#include <linux/module.h>
+#include <asm/cacheflush.h>
+#include <asm/kvm_ppc.h>
+
+unsigned long kvmppc_booke_handlers;
+
+static int kvmppc_booke_init(void)
+{
+       unsigned long ivor[16];
+       unsigned long max_ivor = 0;
+       int i;
+
+       /* We install our own exception handlers by hijacking IVPR. IVPR must
+        * be 16-bit aligned, so we need a 64KB allocation. */
+       kvmppc_booke_handlers = __get_free_pages(GFP_KERNEL | __GFP_ZERO,
+                                                VCPU_SIZE_ORDER);
+       if (!kvmppc_booke_handlers)
+               return -ENOMEM;
+
+       /* XXX make sure our handlers are smaller than Linux's */
+
+       /* Copy our interrupt handlers to match host IVORs. That way we don't
+        * have to swap the IVORs on every guest/host transition. */
+       ivor[0] = mfspr(SPRN_IVOR0);
+       ivor[1] = mfspr(SPRN_IVOR1);
+       ivor[2] = mfspr(SPRN_IVOR2);
+       ivor[3] = mfspr(SPRN_IVOR3);
+       ivor[4] = mfspr(SPRN_IVOR4);
+       ivor[5] = mfspr(SPRN_IVOR5);
+       ivor[6] = mfspr(SPRN_IVOR6);
+       ivor[7] = mfspr(SPRN_IVOR7);
+       ivor[8] = mfspr(SPRN_IVOR8);
+       ivor[9] = mfspr(SPRN_IVOR9);
+       ivor[10] = mfspr(SPRN_IVOR10);
+       ivor[11] = mfspr(SPRN_IVOR11);
+       ivor[12] = mfspr(SPRN_IVOR12);
+       ivor[13] = mfspr(SPRN_IVOR13);
+       ivor[14] = mfspr(SPRN_IVOR14);
+       ivor[15] = mfspr(SPRN_IVOR15);
+
+       for (i = 0; i < 16; i++) {
+               if (ivor[i] > max_ivor)
+                       max_ivor = ivor[i];
+
+               memcpy((void *)kvmppc_booke_handlers + ivor[i],
+                      kvmppc_handlers_start + i * kvmppc_handler_len,
+                      kvmppc_handler_len);
+       }
+       flush_icache_range(kvmppc_booke_handlers,
+                          kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
+
+       return kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE);
+}
+
+static void __exit kvmppc_booke_exit(void)
+{
+       free_pages(kvmppc_booke_handlers, VCPU_SIZE_ORDER);
+       kvm_exit();
+}
+
+module_init(kvmppc_booke_init)
+module_exit(kvmppc_booke_exit)
diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S
new file mode 100644 (file)
index 0000000..3b653b5
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/kvm_asm.h>
+#include <asm/reg.h>
+#include <asm/mmu-44x.h>
+#include <asm/page.h>
+#include <asm/asm-offsets.h>
+
+#define KVMPPC_MSR_MASK (MSR_CE|MSR_EE|MSR_PR|MSR_DE|MSR_ME|MSR_IS|MSR_DS)
+
+#define VCPU_GPR(n)     (VCPU_GPRS + (n * 4))
+
+/* The host stack layout: */
+#define HOST_R1         0 /* Implied by stwu. */
+#define HOST_CALLEE_LR  4
+#define HOST_RUN        8
+/* r2 is special: it holds 'current', and it made nonvolatile in the
+ * kernel with the -ffixed-r2 gcc option. */
+#define HOST_R2         12
+#define HOST_NV_GPRS    16
+#define HOST_NV_GPR(n)  (HOST_NV_GPRS + ((n - 14) * 4))
+#define HOST_MIN_STACK_SIZE (HOST_NV_GPR(31) + 4)
+#define HOST_STACK_SIZE (((HOST_MIN_STACK_SIZE + 15) / 16) * 16) /* Align. */
+#define HOST_STACK_LR   (HOST_STACK_SIZE + 4) /* In caller stack frame. */
+
+#define NEED_INST_MASK ((1<<BOOKE_INTERRUPT_PROGRAM) | \
+                        (1<<BOOKE_INTERRUPT_DTLB_MISS))
+
+#define NEED_DEAR_MASK ((1<<BOOKE_INTERRUPT_DATA_STORAGE) | \
+                        (1<<BOOKE_INTERRUPT_DTLB_MISS))
+
+#define NEED_ESR_MASK ((1<<BOOKE_INTERRUPT_DATA_STORAGE) | \
+                       (1<<BOOKE_INTERRUPT_INST_STORAGE) | \
+                       (1<<BOOKE_INTERRUPT_PROGRAM) | \
+                       (1<<BOOKE_INTERRUPT_DTLB_MISS))
+
+.macro KVM_HANDLER ivor_nr
+_GLOBAL(kvmppc_handler_\ivor_nr)
+       /* Get pointer to vcpu and record exit number. */
+       mtspr   SPRN_SPRG0, r4
+       mfspr   r4, SPRN_SPRG1
+       stw     r5, VCPU_GPR(r5)(r4)
+       stw     r6, VCPU_GPR(r6)(r4)
+       mfctr   r5
+       lis     r6, kvmppc_resume_host@h
+       stw     r5, VCPU_CTR(r4)
+       li      r5, \ivor_nr
+       ori     r6, r6, kvmppc_resume_host@l
+       mtctr   r6
+       bctr
+.endm
+
+_GLOBAL(kvmppc_handlers_start)
+KVM_HANDLER BOOKE_INTERRUPT_CRITICAL
+KVM_HANDLER BOOKE_INTERRUPT_MACHINE_CHECK
+KVM_HANDLER BOOKE_INTERRUPT_DATA_STORAGE
+KVM_HANDLER BOOKE_INTERRUPT_INST_STORAGE
+KVM_HANDLER BOOKE_INTERRUPT_EXTERNAL
+KVM_HANDLER BOOKE_INTERRUPT_ALIGNMENT
+KVM_HANDLER BOOKE_INTERRUPT_PROGRAM
+KVM_HANDLER BOOKE_INTERRUPT_FP_UNAVAIL
+KVM_HANDLER BOOKE_INTERRUPT_SYSCALL
+KVM_HANDLER BOOKE_INTERRUPT_AP_UNAVAIL
+KVM_HANDLER BOOKE_INTERRUPT_DECREMENTER
+KVM_HANDLER BOOKE_INTERRUPT_FIT
+KVM_HANDLER BOOKE_INTERRUPT_WATCHDOG
+KVM_HANDLER BOOKE_INTERRUPT_DTLB_MISS
+KVM_HANDLER BOOKE_INTERRUPT_ITLB_MISS
+KVM_HANDLER BOOKE_INTERRUPT_DEBUG
+
+_GLOBAL(kvmppc_handler_len)
+       .long kvmppc_handler_1 - kvmppc_handler_0
+
+
+/* Registers:
+ *  SPRG0: guest r4
+ *  r4: vcpu pointer
+ *  r5: KVM exit number
+ */
+_GLOBAL(kvmppc_resume_host)
+       stw     r3, VCPU_GPR(r3)(r4)
+       mfcr    r3
+       stw     r3, VCPU_CR(r4)
+       stw     r7, VCPU_GPR(r7)(r4)
+       stw     r8, VCPU_GPR(r8)(r4)
+       stw     r9, VCPU_GPR(r9)(r4)
+
+       li      r6, 1
+       slw     r6, r6, r5
+
+       /* Save the faulting instruction and all GPRs for emulation. */
+       andi.   r7, r6, NEED_INST_MASK
+       beq     ..skip_inst_copy
+       mfspr   r9, SPRN_SRR0
+       mfmsr   r8
+       ori     r7, r8, MSR_DS
+       mtmsr   r7
+       isync
+       lwz     r9, 0(r9)
+       mtmsr   r8
+       isync
+       stw     r9, VCPU_LAST_INST(r4)
+
+       stw     r15, VCPU_GPR(r15)(r4)
+       stw     r16, VCPU_GPR(r16)(r4)
+       stw     r17, VCPU_GPR(r17)(r4)
+       stw     r18, VCPU_GPR(r18)(r4)
+       stw     r19, VCPU_GPR(r19)(r4)
+       stw     r20, VCPU_GPR(r20)(r4)
+       stw     r21, VCPU_GPR(r21)(r4)
+       stw     r22, VCPU_GPR(r22)(r4)
+       stw     r23, VCPU_GPR(r23)(r4)
+       stw     r24, VCPU_GPR(r24)(r4)
+       stw     r25, VCPU_GPR(r25)(r4)
+       stw     r26, VCPU_GPR(r26)(r4)
+       stw     r27, VCPU_GPR(r27)(r4)
+       stw     r28, VCPU_GPR(r28)(r4)
+       stw     r29, VCPU_GPR(r29)(r4)
+       stw     r30, VCPU_GPR(r30)(r4)
+       stw     r31, VCPU_GPR(r31)(r4)
+..skip_inst_copy:
+
+       /* Also grab DEAR and ESR before the host can clobber them. */
+
+       andi.   r7, r6, NEED_DEAR_MASK
+       beq     ..skip_dear
+       mfspr   r9, SPRN_DEAR
+       stw     r9, VCPU_FAULT_DEAR(r4)
+..skip_dear:
+
+       andi.   r7, r6, NEED_ESR_MASK
+       beq     ..skip_esr
+       mfspr   r9, SPRN_ESR
+       stw     r9, VCPU_FAULT_ESR(r4)
+..skip_esr:
+
+       /* Save remaining volatile guest register state to vcpu. */
+       stw     r0, VCPU_GPR(r0)(r4)
+       stw     r1, VCPU_GPR(r1)(r4)
+       stw     r2, VCPU_GPR(r2)(r4)
+       stw     r10, VCPU_GPR(r10)(r4)
+       stw     r11, VCPU_GPR(r11)(r4)
+       stw     r12, VCPU_GPR(r12)(r4)
+       stw     r13, VCPU_GPR(r13)(r4)
+       stw     r14, VCPU_GPR(r14)(r4) /* We need a NV GPR below. */
+       mflr    r3
+       stw     r3, VCPU_LR(r4)
+       mfxer   r3
+       stw     r3, VCPU_XER(r4)
+       mfspr   r3, SPRN_SPRG0
+       stw     r3, VCPU_GPR(r4)(r4)
+       mfspr   r3, SPRN_SRR0
+       stw     r3, VCPU_PC(r4)
+
+       /* Restore host stack pointer and PID before IVPR, since the host
+        * exception handlers use them. */
+       lwz     r1, VCPU_HOST_STACK(r4)
+       lwz     r3, VCPU_HOST_PID(r4)
+       mtspr   SPRN_PID, r3
+
+       /* Restore host IVPR before re-enabling interrupts. We cheat and know
+        * that Linux IVPR is always 0xc0000000. */
+       lis     r3, 0xc000
+       mtspr   SPRN_IVPR, r3
+
+       /* Switch to kernel stack and jump to handler. */
+       LOAD_REG_ADDR(r3, kvmppc_handle_exit)
+       mtctr   r3
+       lwz     r3, HOST_RUN(r1)
+       lwz     r2, HOST_R2(r1)
+       mr      r14, r4 /* Save vcpu pointer. */
+
+       bctrl   /* kvmppc_handle_exit() */
+
+       /* Restore vcpu pointer and the nonvolatiles we used. */
+       mr      r4, r14
+       lwz     r14, VCPU_GPR(r14)(r4)
+
+       /* Sometimes instruction emulation must restore complete GPR state. */
+       andi.   r5, r3, RESUME_FLAG_NV
+       beq     ..skip_nv_load
+       lwz     r15, VCPU_GPR(r15)(r4)
+       lwz     r16, VCPU_GPR(r16)(r4)
+       lwz     r17, VCPU_GPR(r17)(r4)
+       lwz     r18, VCPU_GPR(r18)(r4)
+       lwz     r19, VCPU_GPR(r19)(r4)
+       lwz     r20, VCPU_GPR(r20)(r4)
+       lwz     r21, VCPU_GPR(r21)(r4)
+       lwz     r22, VCPU_GPR(r22)(r4)
+       lwz     r23, VCPU_GPR(r23)(r4)
+       lwz     r24, VCPU_GPR(r24)(r4)
+       lwz     r25, VCPU_GPR(r25)(r4)
+       lwz     r26, VCPU_GPR(r26)(r4)
+       lwz     r27, VCPU_GPR(r27)(r4)
+       lwz     r28, VCPU_GPR(r28)(r4)
+       lwz     r29, VCPU_GPR(r29)(r4)
+       lwz     r30, VCPU_GPR(r30)(r4)
+       lwz     r31, VCPU_GPR(r31)(r4)
+..skip_nv_load:
+
+       /* Should we return to the guest? */
+       andi.   r5, r3, RESUME_FLAG_HOST
+       beq     lightweight_exit
+
+       srawi   r3, r3, 2 /* Shift -ERR back down. */
+
+heavyweight_exit:
+       /* Not returning to guest. */
+
+       /* We already saved guest volatile register state; now save the
+        * non-volatiles. */
+       stw     r15, VCPU_GPR(r15)(r4)
+       stw     r16, VCPU_GPR(r16)(r4)
+       stw     r17, VCPU_GPR(r17)(r4)
+       stw     r18, VCPU_GPR(r18)(r4)
+       stw     r19, VCPU_GPR(r19)(r4)
+       stw     r20, VCPU_GPR(r20)(r4)
+       stw     r21, VCPU_GPR(r21)(r4)
+       stw     r22, VCPU_GPR(r22)(r4)
+       stw     r23, VCPU_GPR(r23)(r4)
+       stw     r24, VCPU_GPR(r24)(r4)
+       stw     r25, VCPU_GPR(r25)(r4)
+       stw     r26, VCPU_GPR(r26)(r4)
+       stw     r27, VCPU_GPR(r27)(r4)
+       stw     r28, VCPU_GPR(r28)(r4)
+       stw     r29, VCPU_GPR(r29)(r4)
+       stw     r30, VCPU_GPR(r30)(r4)
+       stw     r31, VCPU_GPR(r31)(r4)
+
+       /* Load host non-volatile register state from host stack. */
+       lwz     r14, HOST_NV_GPR(r14)(r1)
+       lwz     r15, HOST_NV_GPR(r15)(r1)
+       lwz     r16, HOST_NV_GPR(r16)(r1)
+       lwz     r17, HOST_NV_GPR(r17)(r1)
+       lwz     r18, HOST_NV_GPR(r18)(r1)
+       lwz     r19, HOST_NV_GPR(r19)(r1)
+       lwz     r20, HOST_NV_GPR(r20)(r1)
+       lwz     r21, HOST_NV_GPR(r21)(r1)
+       lwz     r22, HOST_NV_GPR(r22)(r1)
+       lwz     r23, HOST_NV_GPR(r23)(r1)
+       lwz     r24, HOST_NV_GPR(r24)(r1)
+       lwz     r25, HOST_NV_GPR(r25)(r1)
+       lwz     r26, HOST_NV_GPR(r26)(r1)
+       lwz     r27, HOST_NV_GPR(r27)(r1)
+       lwz     r28, HOST_NV_GPR(r28)(r1)
+       lwz     r29, HOST_NV_GPR(r29)(r1)
+       lwz     r30, HOST_NV_GPR(r30)(r1)
+       lwz     r31, HOST_NV_GPR(r31)(r1)
+
+       /* Return to kvm_vcpu_run(). */
+       lwz     r4, HOST_STACK_LR(r1)
+       addi    r1, r1, HOST_STACK_SIZE
+       mtlr    r4
+       /* r3 still contains the return code from kvmppc_handle_exit(). */
+       blr
+
+
+/* Registers:
+ *  r3: kvm_run pointer
+ *  r4: vcpu pointer
+ */
+_GLOBAL(__kvmppc_vcpu_run)
+       stwu    r1, -HOST_STACK_SIZE(r1)
+       stw     r1, VCPU_HOST_STACK(r4) /* Save stack pointer to vcpu. */
+
+       /* Save host state to stack. */
+       stw     r3, HOST_RUN(r1)
+       mflr    r3
+       stw     r3, HOST_STACK_LR(r1)
+
+       /* Save host non-volatile register state to stack. */
+       stw     r14, HOST_NV_GPR(r14)(r1)
+       stw     r15, HOST_NV_GPR(r15)(r1)
+       stw     r16, HOST_NV_GPR(r16)(r1)
+       stw     r17, HOST_NV_GPR(r17)(r1)
+       stw     r18, HOST_NV_GPR(r18)(r1)
+       stw     r19, HOST_NV_GPR(r19)(r1)
+       stw     r20, HOST_NV_GPR(r20)(r1)
+       stw     r21, HOST_NV_GPR(r21)(r1)
+       stw     r22, HOST_NV_GPR(r22)(r1)
+       stw     r23, HOST_NV_GPR(r23)(r1)
+       stw     r24, HOST_NV_GPR(r24)(r1)
+       stw     r25, HOST_NV_GPR(r25)(r1)
+       stw     r26, HOST_NV_GPR(r26)(r1)
+       stw     r27, HOST_NV_GPR(r27)(r1)
+       stw     r28, HOST_NV_GPR(r28)(r1)
+       stw     r29, HOST_NV_GPR(r29)(r1)
+       stw     r30, HOST_NV_GPR(r30)(r1)
+       stw     r31, HOST_NV_GPR(r31)(r1)
+
+       /* Load guest non-volatiles. */
+       lwz     r14, VCPU_GPR(r14)(r4)
+       lwz     r15, VCPU_GPR(r15)(r4)
+       lwz     r16, VCPU_GPR(r16)(r4)
+       lwz     r17, VCPU_GPR(r17)(r4)
+       lwz     r18, VCPU_GPR(r18)(r4)
+       lwz     r19, VCPU_GPR(r19)(r4)
+       lwz     r20, VCPU_GPR(r20)(r4)
+       lwz     r21, VCPU_GPR(r21)(r4)
+       lwz     r22, VCPU_GPR(r22)(r4)
+       lwz     r23, VCPU_GPR(r23)(r4)
+       lwz     r24, VCPU_GPR(r24)(r4)
+       lwz     r25, VCPU_GPR(r25)(r4)
+       lwz     r26, VCPU_GPR(r26)(r4)
+       lwz     r27, VCPU_GPR(r27)(r4)
+       lwz     r28, VCPU_GPR(r28)(r4)
+       lwz     r29, VCPU_GPR(r29)(r4)
+       lwz     r30, VCPU_GPR(r30)(r4)
+       lwz     r31, VCPU_GPR(r31)(r4)
+
+lightweight_exit:
+       stw     r2, HOST_R2(r1)
+
+       mfspr   r3, SPRN_PID
+       stw     r3, VCPU_HOST_PID(r4)
+       lwz     r3, VCPU_PID(r4)
+       mtspr   SPRN_PID, r3
+
+       /* Prevent all TLB updates. */
+       mfmsr   r5
+       lis     r6, (MSR_EE|MSR_CE|MSR_ME|MSR_DE)@h
+       ori     r6, r6, (MSR_EE|MSR_CE|MSR_ME|MSR_DE)@l
+       andc    r6, r5, r6
+       mtmsr   r6
+
+       /* Save the host's non-pinned TLB mappings, and load the guest mappings
+        * over them. Leave the host's "pinned" kernel mappings in place. */
+       /* XXX optimization: use generation count to avoid swapping unmodified
+        * entries. */
+       mfspr   r10, SPRN_MMUCR                 /* Save host MMUCR. */
+       lis     r8, tlb_44x_hwater@ha
+       lwz     r8, tlb_44x_hwater@l(r8)
+       addi    r3, r4, VCPU_HOST_TLB - 4
+       addi    r9, r4, VCPU_SHADOW_TLB - 4
+       li      r6, 0
+1:
+       /* Save host entry. */
+       tlbre   r7, r6, PPC44x_TLB_PAGEID
+       mfspr   r5, SPRN_MMUCR
+       stwu    r5, 4(r3)
+       stwu    r7, 4(r3)
+       tlbre   r7, r6, PPC44x_TLB_XLAT
+       stwu    r7, 4(r3)
+       tlbre   r7, r6, PPC44x_TLB_ATTRIB
+       stwu    r7, 4(r3)
+       /* Load guest entry. */
+       lwzu    r7, 4(r9)
+       mtspr   SPRN_MMUCR, r7
+       lwzu    r7, 4(r9)
+       tlbwe   r7, r6, PPC44x_TLB_PAGEID
+       lwzu    r7, 4(r9)
+       tlbwe   r7, r6, PPC44x_TLB_XLAT
+       lwzu    r7, 4(r9)
+       tlbwe   r7, r6, PPC44x_TLB_ATTRIB
+       /* Increment index. */
+       addi    r6, r6, 1
+       cmpw    r6, r8
+       blt     1b
+       mtspr   SPRN_MMUCR, r10                 /* Restore host MMUCR. */
+
+       iccci   0, 0 /* XXX hack */
+
+       /* Load some guest volatiles. */
+       lwz     r0, VCPU_GPR(r0)(r4)
+       lwz     r2, VCPU_GPR(r2)(r4)
+       lwz     r9, VCPU_GPR(r9)(r4)
+       lwz     r10, VCPU_GPR(r10)(r4)
+       lwz     r11, VCPU_GPR(r11)(r4)
+       lwz     r12, VCPU_GPR(r12)(r4)
+       lwz     r13, VCPU_GPR(r13)(r4)
+       lwz     r3, VCPU_LR(r4)
+       mtlr    r3
+       lwz     r3, VCPU_XER(r4)
+       mtxer   r3
+
+       /* Switch the IVPR. XXX If we take a TLB miss after this we're screwed,
+        * so how do we make sure vcpu won't fault? */
+       lis     r8, kvmppc_booke_handlers@ha
+       lwz     r8, kvmppc_booke_handlers@l(r8)
+       mtspr   SPRN_IVPR, r8
+
+       /* Save vcpu pointer for the exception handlers. */
+       mtspr   SPRN_SPRG1, r4
+
+       /* Can't switch the stack pointer until after IVPR is switched,
+        * because host interrupt handlers would get confused. */
+       lwz     r1, VCPU_GPR(r1)(r4)
+
+       /* XXX handle USPRG0 */
+       /* Host interrupt handlers may have clobbered these guest-readable
+        * SPRGs, so we need to reload them here with the guest's values. */
+       lwz     r3, VCPU_SPRG4(r4)
+       mtspr   SPRN_SPRG4, r3
+       lwz     r3, VCPU_SPRG5(r4)
+       mtspr   SPRN_SPRG5, r3
+       lwz     r3, VCPU_SPRG6(r4)
+       mtspr   SPRN_SPRG6, r3
+       lwz     r3, VCPU_SPRG7(r4)
+       mtspr   SPRN_SPRG7, r3
+
+       /* Finish loading guest volatiles and jump to guest. */
+       lwz     r3, VCPU_CTR(r4)
+       mtctr   r3
+       lwz     r3, VCPU_CR(r4)
+       mtcr    r3
+       lwz     r5, VCPU_GPR(r5)(r4)
+       lwz     r6, VCPU_GPR(r6)(r4)
+       lwz     r7, VCPU_GPR(r7)(r4)
+       lwz     r8, VCPU_GPR(r8)(r4)
+       lwz     r3, VCPU_PC(r4)
+       mtsrr0  r3
+       lwz     r3, VCPU_MSR(r4)
+       oris    r3, r3, KVMPPC_MSR_MASK@h
+       ori     r3, r3, KVMPPC_MSR_MASK@l
+       mtsrr1  r3
+       lwz     r3, VCPU_GPR(r3)(r4)
+       lwz     r4, VCPU_GPR(r4)(r4)
+       rfi
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
new file mode 100644 (file)
index 0000000..a03fe0c
--- /dev/null
@@ -0,0 +1,760 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kvm_host.h>
+
+#include <asm/dcr.h>
+#include <asm/dcr-regs.h>
+#include <asm/time.h>
+#include <asm/byteorder.h>
+#include <asm/kvm_ppc.h>
+
+#include "44x_tlb.h"
+
+/* Instruction decoding */
+static inline unsigned int get_op(u32 inst)
+{
+       return inst >> 26;
+}
+
+static inline unsigned int get_xop(u32 inst)
+{
+       return (inst >> 1) & 0x3ff;
+}
+
+static inline unsigned int get_sprn(u32 inst)
+{
+       return ((inst >> 16) & 0x1f) | ((inst >> 6) & 0x3e0);
+}
+
+static inline unsigned int get_dcrn(u32 inst)
+{
+       return ((inst >> 16) & 0x1f) | ((inst >> 6) & 0x3e0);
+}
+
+static inline unsigned int get_rt(u32 inst)
+{
+       return (inst >> 21) & 0x1f;
+}
+
+static inline unsigned int get_rs(u32 inst)
+{
+       return (inst >> 21) & 0x1f;
+}
+
+static inline unsigned int get_ra(u32 inst)
+{
+       return (inst >> 16) & 0x1f;
+}
+
+static inline unsigned int get_rb(u32 inst)
+{
+       return (inst >> 11) & 0x1f;
+}
+
+static inline unsigned int get_rc(u32 inst)
+{
+       return inst & 0x1;
+}
+
+static inline unsigned int get_ws(u32 inst)
+{
+       return (inst >> 11) & 0x1f;
+}
+
+static inline unsigned int get_d(u32 inst)
+{
+       return inst & 0xffff;
+}
+
+static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,
+                             const struct tlbe *tlbe)
+{
+       gpa_t gpa;
+
+       if (!get_tlb_v(tlbe))
+               return 0;
+
+       /* Does it match current guest AS? */
+       /* XXX what about IS != DS? */
+       if (get_tlb_ts(tlbe) != !!(vcpu->arch.msr & MSR_IS))
+               return 0;
+
+       gpa = get_tlb_raddr(tlbe);
+       if (!gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT))
+               /* Mapping is not for RAM. */
+               return 0;
+
+       return 1;
+}
+
+static int kvmppc_emul_tlbwe(struct kvm_vcpu *vcpu, u32 inst)
+{
+       u64 eaddr;
+       u64 raddr;
+       u64 asid;
+       u32 flags;
+       struct tlbe *tlbe;
+       unsigned int ra;
+       unsigned int rs;
+       unsigned int ws;
+       unsigned int index;
+
+       ra = get_ra(inst);
+       rs = get_rs(inst);
+       ws = get_ws(inst);
+
+       index = vcpu->arch.gpr[ra];
+       if (index > PPC44x_TLB_SIZE) {
+               printk("%s: index %d\n", __func__, index);
+               kvmppc_dump_vcpu(vcpu);
+               return EMULATE_FAIL;
+       }
+
+       tlbe = &vcpu->arch.guest_tlb[index];
+
+       /* Invalidate shadow mappings for the about-to-be-clobbered TLBE. */
+       if (tlbe->word0 & PPC44x_TLB_VALID) {
+               eaddr = get_tlb_eaddr(tlbe);
+               asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid;
+               kvmppc_mmu_invalidate(vcpu, eaddr, asid);
+       }
+
+       switch (ws) {
+       case PPC44x_TLB_PAGEID:
+               tlbe->tid = vcpu->arch.mmucr & 0xff;
+               tlbe->word0 = vcpu->arch.gpr[rs];
+               break;
+
+       case PPC44x_TLB_XLAT:
+               tlbe->word1 = vcpu->arch.gpr[rs];
+               break;
+
+       case PPC44x_TLB_ATTRIB:
+               tlbe->word2 = vcpu->arch.gpr[rs];
+               break;
+
+       default:
+               return EMULATE_FAIL;
+       }
+
+       if (tlbe_is_host_safe(vcpu, tlbe)) {
+               eaddr = get_tlb_eaddr(tlbe);
+               raddr = get_tlb_raddr(tlbe);
+               asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid;
+               flags = tlbe->word2 & 0xffff;
+
+               /* Create a 4KB mapping on the host. If the guest wanted a
+                * large page, only the first 4KB is mapped here and the rest
+                * are mapped on the fly. */
+               kvmppc_mmu_map(vcpu, eaddr, raddr >> PAGE_SHIFT, asid, flags);
+       }
+
+       return EMULATE_DONE;
+}
+
+static void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
+{
+       if (vcpu->arch.tcr & TCR_DIE) {
+               /* The decrementer ticks at the same rate as the timebase, so
+                * that's how we convert the guest DEC value to the number of
+                * host ticks. */
+               unsigned long nr_jiffies;
+
+               nr_jiffies = vcpu->arch.dec / tb_ticks_per_jiffy;
+               mod_timer(&vcpu->arch.dec_timer,
+                         get_jiffies_64() + nr_jiffies);
+       } else {
+               del_timer(&vcpu->arch.dec_timer);
+       }
+}
+
+static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.pc = vcpu->arch.srr0;
+       kvmppc_set_msr(vcpu, vcpu->arch.srr1);
+}
+
+/* XXX to do:
+ * lhax
+ * lhaux
+ * lswx
+ * lswi
+ * stswx
+ * stswi
+ * lha
+ * lhau
+ * lmw
+ * stmw
+ *
+ * XXX is_bigendian should depend on MMU mapping or MSR[LE]
+ */
+int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+       u32 inst = vcpu->arch.last_inst;
+       u32 ea;
+       int ra;
+       int rb;
+       int rc;
+       int rs;
+       int rt;
+       int sprn;
+       int dcrn;
+       enum emulation_result emulated = EMULATE_DONE;
+       int advance = 1;
+
+       switch (get_op(inst)) {
+       case 3:                                                 /* trap */
+               printk("trap!\n");
+               kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM);
+               advance = 0;
+               break;
+
+       case 19:
+               switch (get_xop(inst)) {
+               case 50:                                        /* rfi */
+                       kvmppc_emul_rfi(vcpu);
+                       advance = 0;
+                       break;
+
+               default:
+                       emulated = EMULATE_FAIL;
+                       break;
+               }
+               break;
+
+       case 31:
+               switch (get_xop(inst)) {
+
+               case 83:                                        /* mfmsr */
+                       rt = get_rt(inst);
+                       vcpu->arch.gpr[rt] = vcpu->arch.msr;
+                       break;
+
+               case 87:                                        /* lbzx */
+                       rt = get_rt(inst);
+                       emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
+                       break;
+
+               case 131:                                       /* wrtee */
+                       rs = get_rs(inst);
+                       vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
+                                        | (vcpu->arch.gpr[rs] & MSR_EE);
+                       break;
+
+               case 146:                                       /* mtmsr */
+                       rs = get_rs(inst);
+                       kvmppc_set_msr(vcpu, vcpu->arch.gpr[rs]);
+                       break;
+
+               case 163:                                       /* wrteei */
+                       vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
+                                        | (inst & MSR_EE);
+                       break;
+
+               case 215:                                       /* stbx */
+                       rs = get_rs(inst);
+                       emulated = kvmppc_handle_store(run, vcpu,
+                                                      vcpu->arch.gpr[rs],
+                                                      1, 1);
+                       break;
+
+               case 247:                                       /* stbux */
+                       rs = get_rs(inst);
+                       ra = get_ra(inst);
+                       rb = get_rb(inst);
+
+                       ea = vcpu->arch.gpr[rb];
+                       if (ra)
+                               ea += vcpu->arch.gpr[ra];
+
+                       emulated = kvmppc_handle_store(run, vcpu,
+                                                      vcpu->arch.gpr[rs],
+                                                      1, 1);
+                       vcpu->arch.gpr[rs] = ea;
+                       break;
+
+               case 279:                                       /* lhzx */
+                       rt = get_rt(inst);
+                       emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
+                       break;
+
+               case 311:                                       /* lhzux */
+                       rt = get_rt(inst);
+                       ra = get_ra(inst);
+                       rb = get_rb(inst);
+
+                       ea = vcpu->arch.gpr[rb];
+                       if (ra)
+                               ea += vcpu->arch.gpr[ra];
+
+                       emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
+                       vcpu->arch.gpr[ra] = ea;
+                       break;
+
+               case 323:                                       /* mfdcr */
+                       dcrn = get_dcrn(inst);
+                       rt = get_rt(inst);
+
+                       /* The guest may access CPR0 registers to determine the timebase
+                        * frequency, and it must know the real host frequency because it
+                        * can directly access the timebase registers.
+                        *
+                        * It would be possible to emulate those accesses in userspace,
+                        * but userspace can really only figure out the end frequency.
+                        * We could decompose that into the factors that compute it, but
+                        * that's tricky math, and it's easier to just report the real
+                        * CPR0 values.
+                        */
+                       switch (dcrn) {
+                       case DCRN_CPR0_CONFIG_ADDR:
+                               vcpu->arch.gpr[rt] = vcpu->arch.cpr0_cfgaddr;
+                               break;
+                       case DCRN_CPR0_CONFIG_DATA:
+                               local_irq_disable();
+                               mtdcr(DCRN_CPR0_CONFIG_ADDR,
+                                     vcpu->arch.cpr0_cfgaddr);
+                               vcpu->arch.gpr[rt] = mfdcr(DCRN_CPR0_CONFIG_DATA);
+                               local_irq_enable();
+                               break;
+                       default:
+                               run->dcr.dcrn = dcrn;
+                               run->dcr.data =  0;
+                               run->dcr.is_write = 0;
+                               vcpu->arch.io_gpr = rt;
+                               vcpu->arch.dcr_needed = 1;
+                               emulated = EMULATE_DO_DCR;
+                       }
+
+                       break;
+
+               case 339:                                       /* mfspr */
+                       sprn = get_sprn(inst);
+                       rt = get_rt(inst);
+
+                       switch (sprn) {
+                       case SPRN_SRR0:
+                               vcpu->arch.gpr[rt] = vcpu->arch.srr0; break;
+                       case SPRN_SRR1:
+                               vcpu->arch.gpr[rt] = vcpu->arch.srr1; break;
+                       case SPRN_MMUCR:
+                               vcpu->arch.gpr[rt] = vcpu->arch.mmucr; break;
+                       case SPRN_PID:
+                               vcpu->arch.gpr[rt] = vcpu->arch.pid; break;
+                       case SPRN_IVPR:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ivpr; break;
+                       case SPRN_CCR0:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ccr0; break;
+                       case SPRN_CCR1:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ccr1; break;
+                       case SPRN_PVR:
+                               vcpu->arch.gpr[rt] = vcpu->arch.pvr; break;
+                       case SPRN_DEAR:
+                               vcpu->arch.gpr[rt] = vcpu->arch.dear; break;
+                       case SPRN_ESR:
+                               vcpu->arch.gpr[rt] = vcpu->arch.esr; break;
+                       case SPRN_DBCR0:
+                               vcpu->arch.gpr[rt] = vcpu->arch.dbcr0; break;
+                       case SPRN_DBCR1:
+                               vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break;
+
+                       /* Note: mftb and TBRL/TBWL are user-accessible, so
+                        * the guest can always access the real TB anyways.
+                        * In fact, we probably will never see these traps. */
+                       case SPRN_TBWL:
+                               vcpu->arch.gpr[rt] = mftbl(); break;
+                       case SPRN_TBWU:
+                               vcpu->arch.gpr[rt] = mftbu(); break;
+
+                       case SPRN_SPRG0:
+                               vcpu->arch.gpr[rt] = vcpu->arch.sprg0; break;
+                       case SPRN_SPRG1:
+                               vcpu->arch.gpr[rt] = vcpu->arch.sprg1; break;
+                       case SPRN_SPRG2:
+                               vcpu->arch.gpr[rt] = vcpu->arch.sprg2; break;
+                       case SPRN_SPRG3:
+                               vcpu->arch.gpr[rt] = vcpu->arch.sprg3; break;
+                       /* Note: SPRG4-7 are user-readable, so we don't get
+                        * a trap. */
+
+                       case SPRN_IVOR0:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ivor[0]; break;
+                       case SPRN_IVOR1:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ivor[1]; break;
+                       case SPRN_IVOR2:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ivor[2]; break;
+                       case SPRN_IVOR3:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ivor[3]; break;
+                       case SPRN_IVOR4:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ivor[4]; break;
+                       case SPRN_IVOR5:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ivor[5]; break;
+                       case SPRN_IVOR6:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ivor[6]; break;
+                       case SPRN_IVOR7:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ivor[7]; break;
+                       case SPRN_IVOR8:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ivor[8]; break;
+                       case SPRN_IVOR9:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ivor[9]; break;
+                       case SPRN_IVOR10:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ivor[10]; break;
+                       case SPRN_IVOR11:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ivor[11]; break;
+                       case SPRN_IVOR12:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ivor[12]; break;
+                       case SPRN_IVOR13:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ivor[13]; break;
+                       case SPRN_IVOR14:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ivor[14]; break;
+                       case SPRN_IVOR15:
+                               vcpu->arch.gpr[rt] = vcpu->arch.ivor[15]; break;
+
+                       default:
+                               printk("mfspr: unknown spr %x\n", sprn);
+                               vcpu->arch.gpr[rt] = 0;
+                               break;
+                       }
+                       break;
+
+               case 407:                                       /* sthx */
+                       rs = get_rs(inst);
+                       ra = get_ra(inst);
+                       rb = get_rb(inst);
+
+                       emulated = kvmppc_handle_store(run, vcpu,
+                                                      vcpu->arch.gpr[rs],
+                                                      2, 1);
+                       break;
+
+               case 439:                                       /* sthux */
+                       rs = get_rs(inst);
+                       ra = get_ra(inst);
+                       rb = get_rb(inst);
+
+                       ea = vcpu->arch.gpr[rb];
+                       if (ra)
+                               ea += vcpu->arch.gpr[ra];
+
+                       emulated = kvmppc_handle_store(run, vcpu,
+                                                      vcpu->arch.gpr[rs],
+                                                      2, 1);
+                       vcpu->arch.gpr[ra] = ea;
+                       break;
+
+               case 451:                                       /* mtdcr */
+                       dcrn = get_dcrn(inst);
+                       rs = get_rs(inst);
+
+                       /* emulate some access in kernel */
+                       switch (dcrn) {
+                       case DCRN_CPR0_CONFIG_ADDR:
+                               vcpu->arch.cpr0_cfgaddr = vcpu->arch.gpr[rs];
+                               break;
+                       default:
+                               run->dcr.dcrn = dcrn;
+                               run->dcr.data = vcpu->arch.gpr[rs];
+                               run->dcr.is_write = 1;
+                               vcpu->arch.dcr_needed = 1;
+                               emulated = EMULATE_DO_DCR;
+                       }
+
+                       break;
+
+               case 467:                                       /* mtspr */
+                       sprn = get_sprn(inst);
+                       rs = get_rs(inst);
+                       switch (sprn) {
+                       case SPRN_SRR0:
+                               vcpu->arch.srr0 = vcpu->arch.gpr[rs]; break;
+                       case SPRN_SRR1:
+                               vcpu->arch.srr1 = vcpu->arch.gpr[rs]; break;
+                       case SPRN_MMUCR:
+                               vcpu->arch.mmucr = vcpu->arch.gpr[rs]; break;
+                       case SPRN_PID:
+                               vcpu->arch.pid = vcpu->arch.gpr[rs]; break;
+                       case SPRN_CCR0:
+                               vcpu->arch.ccr0 = vcpu->arch.gpr[rs]; break;
+                       case SPRN_CCR1:
+                               vcpu->arch.ccr1 = vcpu->arch.gpr[rs]; break;
+                       case SPRN_DEAR:
+                               vcpu->arch.dear = vcpu->arch.gpr[rs]; break;
+                       case SPRN_ESR:
+                               vcpu->arch.esr = vcpu->arch.gpr[rs]; break;
+                       case SPRN_DBCR0:
+                               vcpu->arch.dbcr0 = vcpu->arch.gpr[rs]; break;
+                       case SPRN_DBCR1:
+                               vcpu->arch.dbcr1 = vcpu->arch.gpr[rs]; break;
+
+                       /* XXX We need to context-switch the timebase for
+                        * watchdog and FIT. */
+                       case SPRN_TBWL: break;
+                       case SPRN_TBWU: break;
+
+                       case SPRN_DEC:
+                               vcpu->arch.dec = vcpu->arch.gpr[rs];
+                               kvmppc_emulate_dec(vcpu);
+                               break;
+
+                       case SPRN_TSR:
+                               vcpu->arch.tsr &= ~vcpu->arch.gpr[rs]; break;
+
+                       case SPRN_TCR:
+                               vcpu->arch.tcr = vcpu->arch.gpr[rs];
+                               kvmppc_emulate_dec(vcpu);
+                               break;
+
+                       case SPRN_SPRG0:
+                               vcpu->arch.sprg0 = vcpu->arch.gpr[rs]; break;
+                       case SPRN_SPRG1:
+                               vcpu->arch.sprg1 = vcpu->arch.gpr[rs]; break;
+                       case SPRN_SPRG2:
+                               vcpu->arch.sprg2 = vcpu->arch.gpr[rs]; break;
+                       case SPRN_SPRG3:
+                               vcpu->arch.sprg3 = vcpu->arch.gpr[rs]; break;
+
+                       /* Note: SPRG4-7 are user-readable. These values are
+                        * loaded into the real SPRGs when resuming the
+                        * guest. */
+                       case SPRN_SPRG4:
+                               vcpu->arch.sprg4 = vcpu->arch.gpr[rs]; break;
+                       case SPRN_SPRG5:
+                               vcpu->arch.sprg5 = vcpu->arch.gpr[rs]; break;
+                       case SPRN_SPRG6:
+                               vcpu->arch.sprg6 = vcpu->arch.gpr[rs]; break;
+                       case SPRN_SPRG7:
+                               vcpu->arch.sprg7 = vcpu->arch.gpr[rs]; break;
+
+                       case SPRN_IVPR:
+                               vcpu->arch.ivpr = vcpu->arch.gpr[rs]; break;
+                       case SPRN_IVOR0:
+                               vcpu->arch.ivor[0] = vcpu->arch.gpr[rs]; break;
+                       case SPRN_IVOR1:
+                               vcpu->arch.ivor[1] = vcpu->arch.gpr[rs]; break;
+                       case SPRN_IVOR2:
+                               vcpu->arch.ivor[2] = vcpu->arch.gpr[rs]; break;
+                       case SPRN_IVOR3:
+                               vcpu->arch.ivor[3] = vcpu->arch.gpr[rs]; break;
+                       case SPRN_IVOR4:
+                               vcpu->arch.ivor[4] = vcpu->arch.gpr[rs]; break;
+                       case SPRN_IVOR5:
+                               vcpu->arch.ivor[5] = vcpu->arch.gpr[rs]; break;
+                       case SPRN_IVOR6:
+                               vcpu->arch.ivor[6] = vcpu->arch.gpr[rs]; break;
+                       case SPRN_IVOR7:
+                               vcpu->arch.ivor[7] = vcpu->arch.gpr[rs]; break;
+                       case SPRN_IVOR8:
+                               vcpu->arch.ivor[8] = vcpu->arch.gpr[rs]; break;
+                       case SPRN_IVOR9:
+                               vcpu->arch.ivor[9] = vcpu->arch.gpr[rs]; break;
+                       case SPRN_IVOR10:
+                               vcpu->arch.ivor[10] = vcpu->arch.gpr[rs]; break;
+                       case SPRN_IVOR11:
+                               vcpu->arch.ivor[11] = vcpu->arch.gpr[rs]; break;
+                       case SPRN_IVOR12:
+                               vcpu->arch.ivor[12] = vcpu->arch.gpr[rs]; break;
+                       case SPRN_IVOR13:
+                               vcpu->arch.ivor[13] = vcpu->arch.gpr[rs]; break;
+                       case SPRN_IVOR14:
+                               vcpu->arch.ivor[14] = vcpu->arch.gpr[rs]; break;
+                       case SPRN_IVOR15:
+                               vcpu->arch.ivor[15] = vcpu->arch.gpr[rs]; break;
+
+                       default:
+                               printk("mtspr: unknown spr %x\n", sprn);
+                               emulated = EMULATE_FAIL;
+                               break;
+                       }
+                       break;
+
+               case 470:                                       /* dcbi */
+                       /* Do nothing. The guest is performing dcbi because
+                        * hardware DMA is not snooped by the dcache, but
+                        * emulated DMA either goes through the dcache as
+                        * normal writes, or the host kernel has handled dcache
+                        * coherence. */
+                       break;
+
+               case 534:                                       /* lwbrx */
+                       rt = get_rt(inst);
+                       emulated = kvmppc_handle_load(run, vcpu, rt, 4, 0);
+                       break;
+
+               case 566:                                       /* tlbsync */
+                       break;
+
+               case 662:                                       /* stwbrx */
+                       rs = get_rs(inst);
+                       ra = get_ra(inst);
+                       rb = get_rb(inst);
+
+                       emulated = kvmppc_handle_store(run, vcpu,
+                                                      vcpu->arch.gpr[rs],
+                                                      4, 0);
+                       break;
+
+               case 978:                                       /* tlbwe */
+                       emulated = kvmppc_emul_tlbwe(vcpu, inst);
+                       break;
+
+               case 914:       {                               /* tlbsx */
+                       int index;
+                       unsigned int as = get_mmucr_sts(vcpu);
+                       unsigned int pid = get_mmucr_stid(vcpu);
+
+                       rt = get_rt(inst);
+                       ra = get_ra(inst);
+                       rb = get_rb(inst);
+                       rc = get_rc(inst);
+
+                       ea = vcpu->arch.gpr[rb];
+                       if (ra)
+                               ea += vcpu->arch.gpr[ra];
+
+                       index = kvmppc_44x_tlb_index(vcpu, ea, pid, as);
+                       if (rc) {
+                               if (index < 0)
+                                       vcpu->arch.cr &= ~0x20000000;
+                               else
+                                       vcpu->arch.cr |= 0x20000000;
+                       }
+                       vcpu->arch.gpr[rt] = index;
+
+                       }
+                       break;
+
+               case 790:                                       /* lhbrx */
+                       rt = get_rt(inst);
+                       emulated = kvmppc_handle_load(run, vcpu, rt, 2, 0);
+                       break;
+
+               case 918:                                       /* sthbrx */
+                       rs = get_rs(inst);
+                       ra = get_ra(inst);
+                       rb = get_rb(inst);
+
+                       emulated = kvmppc_handle_store(run, vcpu,
+                                                      vcpu->arch.gpr[rs],
+                                                      2, 0);
+                       break;
+
+               case 966:                                       /* iccci */
+                       break;
+
+               default:
+                       printk("unknown: op %d xop %d\n", get_op(inst),
+                               get_xop(inst));
+                       emulated = EMULATE_FAIL;
+                       break;
+               }
+               break;
+
+       case 32:                                                /* lwz */
+               rt = get_rt(inst);
+               emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
+               break;
+
+       case 33:                                                /* lwzu */
+               ra = get_ra(inst);
+               rt = get_rt(inst);
+               emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
+               vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
+               break;
+
+       case 34:                                                /* lbz */
+               rt = get_rt(inst);
+               emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
+               break;
+
+       case 35:                                                /* lbzu */
+               ra = get_ra(inst);
+               rt = get_rt(inst);
+               emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
+               vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
+               break;
+
+       case 36:                                                /* stw */
+               rs = get_rs(inst);
+               emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
+                                              4, 1);
+               break;
+
+       case 37:                                                /* stwu */
+               ra = get_ra(inst);
+               rs = get_rs(inst);
+               emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
+                                              4, 1);
+               vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
+               break;
+
+       case 38:                                                /* stb */
+               rs = get_rs(inst);
+               emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
+                                              1, 1);
+               break;
+
+       case 39:                                                /* stbu */
+               ra = get_ra(inst);
+               rs = get_rs(inst);
+               emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
+                                              1, 1);
+               vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
+               break;
+
+       case 40:                                                /* lhz */
+               rt = get_rt(inst);
+               emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
+               break;
+
+       case 41:                                                /* lhzu */
+               ra = get_ra(inst);
+               rt = get_rt(inst);
+               emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
+               vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
+               break;
+
+       case 44:                                                /* sth */
+               rs = get_rs(inst);
+               emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
+                                              2, 1);
+               break;
+
+       case 45:                                                /* sthu */
+               ra = get_ra(inst);
+               rs = get_rs(inst);
+               emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
+                                              2, 1);
+               vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
+               break;
+
+       default:
+               printk("unknown op %d\n", get_op(inst));
+               emulated = EMULATE_FAIL;
+               break;
+       }
+
+       if (advance)
+               vcpu->arch.pc += 4; /* Advance past emulated instruction. */
+
+       return emulated;
+}
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
new file mode 100644 (file)
index 0000000..bad40bd
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ *          Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
+ */
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/kvm_host.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <asm/cputable.h>
+#include <asm/uaccess.h>
+#include <asm/kvm_ppc.h>
+
+
+gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
+{
+       return gfn;
+}
+
+int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
+{
+       /* XXX implement me */
+       return 0;
+}
+
+int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
+{
+       return 1;
+}
+
+
+int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+       enum emulation_result er;
+       int r;
+
+       er = kvmppc_emulate_instruction(run, vcpu);
+       switch (er) {
+       case EMULATE_DONE:
+               /* Future optimization: only reload non-volatiles if they were
+                * actually modified. */
+               r = RESUME_GUEST_NV;
+               break;
+       case EMULATE_DO_MMIO:
+               run->exit_reason = KVM_EXIT_MMIO;
+               /* We must reload nonvolatiles because "update" load/store
+                * instructions modify register state. */
+               /* Future optimization: only reload non-volatiles if they were
+                * actually modified. */
+               r = RESUME_HOST_NV;
+               break;
+       case EMULATE_FAIL:
+               /* XXX Deliver Program interrupt to guest. */
+               printk(KERN_EMERG "%s: emulation failed (%08x)\n", __func__,
+                      vcpu->arch.last_inst);
+               r = RESUME_HOST;
+               break;
+       default:
+               BUG();
+       }
+
+       return r;
+}
+
+void kvm_arch_hardware_enable(void *garbage)
+{
+}
+
+void kvm_arch_hardware_disable(void *garbage)
+{
+}
+
+int kvm_arch_hardware_setup(void)
+{
+       return 0;
+}
+
+void kvm_arch_hardware_unsetup(void)
+{
+}
+
+void kvm_arch_check_processor_compat(void *rtn)
+{
+       int r;
+
+       if (strcmp(cur_cpu_spec->platform, "ppc440") == 0)
+               r = 0;
+       else
+               r = -ENOTSUPP;
+
+       *(int *)rtn = r;
+}
+
+struct kvm *kvm_arch_create_vm(void)
+{
+       struct kvm *kvm;
+
+       kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL);
+       if (!kvm)
+               return ERR_PTR(-ENOMEM);
+
+       return kvm;
+}
+
+static void kvmppc_free_vcpus(struct kvm *kvm)
+{
+       unsigned int i;
+
+       for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+               if (kvm->vcpus[i]) {
+                       kvm_arch_vcpu_free(kvm->vcpus[i]);
+                       kvm->vcpus[i] = NULL;
+               }
+       }
+}
+
+void kvm_arch_destroy_vm(struct kvm *kvm)
+{
+       kvmppc_free_vcpus(kvm);
+       kvm_free_physmem(kvm);
+       kfree(kvm);
+}
+
+int kvm_dev_ioctl_check_extension(long ext)
+{
+       int r;
+
+       switch (ext) {
+       case KVM_CAP_USER_MEMORY:
+               r = 1;
+               break;
+       default:
+               r = 0;
+               break;
+       }
+       return r;
+
+}
+
+long kvm_arch_dev_ioctl(struct file *filp,
+                        unsigned int ioctl, unsigned long arg)
+{
+       return -EINVAL;
+}
+
+int kvm_arch_set_memory_region(struct kvm *kvm,
+                               struct kvm_userspace_memory_region *mem,
+                               struct kvm_memory_slot old,
+                               int user_alloc)
+{
+       return 0;
+}
+
+struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
+{
+       struct kvm_vcpu *vcpu;
+       int err;
+
+       vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
+       if (!vcpu) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       err = kvm_vcpu_init(vcpu, kvm, id);
+       if (err)
+               goto free_vcpu;
+
+       return vcpu;
+
+free_vcpu:
+       kmem_cache_free(kvm_vcpu_cache, vcpu);
+out:
+       return ERR_PTR(err);
+}
+
+void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
+{
+       kvm_vcpu_uninit(vcpu);
+       kmem_cache_free(kvm_vcpu_cache, vcpu);
+}
+
+void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+       kvm_arch_vcpu_free(vcpu);
+}
+
+int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
+{
+       unsigned int priority = exception_priority[BOOKE_INTERRUPT_DECREMENTER];
+
+       return test_bit(priority, &vcpu->arch.pending_exceptions);
+}
+
+static void kvmppc_decrementer_func(unsigned long data)
+{
+       struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
+
+       kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_DECREMENTER);
+}
+
+int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
+{
+       setup_timer(&vcpu->arch.dec_timer, kvmppc_decrementer_func,
+                   (unsigned long)vcpu);
+
+       return 0;
+}
+
+void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
+{
+}
+
+void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+}
+
+void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
+{
+}
+
+void decache_vcpus_on_cpu(int cpu)
+{
+}
+
+int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
+                                    struct kvm_debug_guest *dbg)
+{
+       return -ENOTSUPP;
+}
+
+static void kvmppc_complete_dcr_load(struct kvm_vcpu *vcpu,
+                                     struct kvm_run *run)
+{
+       u32 *gpr = &vcpu->arch.gpr[vcpu->arch.io_gpr];
+       *gpr = run->dcr.data;
+}
+
+static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,
+                                      struct kvm_run *run)
+{
+       u32 *gpr = &vcpu->arch.gpr[vcpu->arch.io_gpr];
+
+       if (run->mmio.len > sizeof(*gpr)) {
+               printk(KERN_ERR "bad MMIO length: %d\n", run->mmio.len);
+               return;
+       }
+
+       if (vcpu->arch.mmio_is_bigendian) {
+               switch (run->mmio.len) {
+               case 4: *gpr = *(u32 *)run->mmio.data; break;
+               case 2: *gpr = *(u16 *)run->mmio.data; break;
+               case 1: *gpr = *(u8 *)run->mmio.data; break;
+               }
+       } else {
+               /* Convert BE data from userland back to LE. */
+               switch (run->mmio.len) {
+               case 4: *gpr = ld_le32((u32 *)run->mmio.data); break;
+               case 2: *gpr = ld_le16((u16 *)run->mmio.data); break;
+               case 1: *gpr = *(u8 *)run->mmio.data; break;
+               }
+       }
+}
+
+int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
+                       unsigned int rt, unsigned int bytes, int is_bigendian)
+{
+       if (bytes > sizeof(run->mmio.data)) {
+               printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__,
+                      run->mmio.len);
+       }
+
+       run->mmio.phys_addr = vcpu->arch.paddr_accessed;
+       run->mmio.len = bytes;
+       run->mmio.is_write = 0;
+
+       vcpu->arch.io_gpr = rt;
+       vcpu->arch.mmio_is_bigendian = is_bigendian;
+       vcpu->mmio_needed = 1;
+       vcpu->mmio_is_write = 0;
+
+       return EMULATE_DO_MMIO;
+}
+
+int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
+                        u32 val, unsigned int bytes, int is_bigendian)
+{
+       void *data = run->mmio.data;
+
+       if (bytes > sizeof(run->mmio.data)) {
+               printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__,
+                      run->mmio.len);
+       }
+
+       run->mmio.phys_addr = vcpu->arch.paddr_accessed;
+       run->mmio.len = bytes;
+       run->mmio.is_write = 1;
+       vcpu->mmio_needed = 1;
+       vcpu->mmio_is_write = 1;
+
+       /* Store the value at the lowest bytes in 'data'. */
+       if (is_bigendian) {
+               switch (bytes) {
+               case 4: *(u32 *)data = val; break;
+               case 2: *(u16 *)data = val; break;
+               case 1: *(u8  *)data = val; break;
+               }
+       } else {
+               /* Store LE value into 'data'. */
+               switch (bytes) {
+               case 4: st_le32(data, val); break;
+               case 2: st_le16(data, val); break;
+               case 1: *(u8 *)data = val; break;
+               }
+       }
+
+       return EMULATE_DO_MMIO;
+}
+
+int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       int r;
+       sigset_t sigsaved;
+
+       if (vcpu->sigset_active)
+               sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
+
+       if (vcpu->mmio_needed) {
+               if (!vcpu->mmio_is_write)
+                       kvmppc_complete_mmio_load(vcpu, run);
+               vcpu->mmio_needed = 0;
+       } else if (vcpu->arch.dcr_needed) {
+               if (!vcpu->arch.dcr_is_write)
+                       kvmppc_complete_dcr_load(vcpu, run);
+               vcpu->arch.dcr_needed = 0;
+       }
+
+       kvmppc_check_and_deliver_interrupts(vcpu);
+
+       local_irq_disable();
+       kvm_guest_enter();
+       r = __kvmppc_vcpu_run(run, vcpu);
+       kvm_guest_exit();
+       local_irq_enable();
+
+       if (vcpu->sigset_active)
+               sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+       return r;
+}
+
+int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
+{
+       kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_EXTERNAL);
+       return 0;
+}
+
+int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
+                                    struct kvm_mp_state *mp_state)
+{
+       return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
+                                    struct kvm_mp_state *mp_state)
+{
+       return -EINVAL;
+}
+
+long kvm_arch_vcpu_ioctl(struct file *filp,
+                         unsigned int ioctl, unsigned long arg)
+{
+       struct kvm_vcpu *vcpu = filp->private_data;
+       void __user *argp = (void __user *)arg;
+       long r;
+
+       switch (ioctl) {
+       case KVM_INTERRUPT: {
+               struct kvm_interrupt irq;
+               r = -EFAULT;
+               if (copy_from_user(&irq, argp, sizeof(irq)))
+                       goto out;
+               r = kvm_vcpu_ioctl_interrupt(vcpu, &irq);
+               break;
+       }
+       default:
+               r = -EINVAL;
+       }
+
+out:
+       return r;
+}
+
+int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
+{
+       return -ENOTSUPP;
+}
+
+long kvm_arch_vm_ioctl(struct file *filp,
+                       unsigned int ioctl, unsigned long arg)
+{
+       long r;
+
+       switch (ioctl) {
+       default:
+               r = -EINVAL;
+       }
+
+       return r;
+}
+
+int kvm_arch_init(void *opaque)
+{
+       return 0;
+}
+
+void kvm_arch_exit(void)
+{
+}
index ada249bf97794b82584d1b27f1f8837f8757c49c..ce10e2b1b902e5ddba7abcd9f48489ef1f2f862e 100644 (file)
@@ -202,7 +202,7 @@ adjust_total_lowmem(void)
                cam_max_size = max_lowmem_size;
 
        /* adjust lowmem size to max_lowmem_size */
-       ram = min(max_lowmem_size, total_lowmem);
+       ram = min(max_lowmem_size, (phys_addr_t)total_lowmem);
 
        /* Calculate CAM values */
        __cam0 = 1UL << 2 * (__ilog2(ram) / 2);
index e10d76a860d3d77c46bae1a496d956bfd7ab2fc5..ddeaf9e38ad5dd159e257eca31fdddc0c8f4958c 100644 (file)
@@ -191,7 +191,7 @@ _GLOBAL(add_hash_page)
        add     r3,r3,r0                /* note create_hpte trims to 24 bits */
 
 #ifdef CONFIG_SMP
-       rlwinm  r8,r1,0,0,18            /* use cpu number to make tag */
+       rlwinm  r8,r1,0,0,(31-THREAD_SHIFT) /* use cpu number to make tag */
        lwz     r8,TI_CPU(r8)           /* to go in mmu_hash_lock */
        oris    r8,r8,12
 #endif /* CONFIG_SMP */
@@ -526,7 +526,7 @@ _GLOBAL(flush_hash_pages)
 #ifdef CONFIG_SMP
        addis   r9,r7,mmu_hash_lock@ha
        addi    r9,r9,mmu_hash_lock@l
-       rlwinm  r8,r1,0,0,18
+       rlwinm  r8,r1,0,0,(31-THREAD_SHIFT)
        add     r8,r8,r7
        lwz     r8,TI_CPU(r8)
        oris    r8,r8,9
index 47325f23c51f2b325ba30fd8cd89d972ed2a0318..1952b4d3fa7f562eeec7d272205e4393870ab4c5 100644 (file)
@@ -59,7 +59,10 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 unsigned long total_memory;
 unsigned long total_lowmem;
 
-phys_addr_t memstart_addr;
+phys_addr_t memstart_addr = (phys_addr_t)~0ull;
+EXPORT_SYMBOL(memstart_addr);
+phys_addr_t kernstart_addr;
+EXPORT_SYMBOL(kernstart_addr);
 phys_addr_t lowmem_end_addr;
 
 int boot_mapsize;
@@ -68,14 +71,6 @@ unsigned long agp_special_page;
 EXPORT_SYMBOL(agp_special_page);
 #endif
 
-#ifdef CONFIG_HIGHMEM
-pte_t *kmap_pte;
-pgprot_t kmap_prot;
-
-EXPORT_SYMBOL(kmap_prot);
-EXPORT_SYMBOL(kmap_pte);
-#endif
-
 void MMU_init(void);
 
 /* XXX should be in current.h  -- paulus */
index 698bd000f98bcba9a01da4ae7993c855877be057..c5ac532a0161b733757016d8fb28396d9a47193d 100644 (file)
@@ -72,7 +72,8 @@
 #warning TASK_SIZE is smaller than it needs to be.
 #endif
 
-phys_addr_t memstart_addr;
+phys_addr_t memstart_addr = ~0;
+phys_addr_t kernstart_addr;
 
 void free_initmem(void)
 {
index 16def4dcff6d33ccadcf2b2b53c65628519fa901..5ccb579b81e41bd52c8ac7474c7d36067e911859 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/tlb.h>
 #include <asm/sections.h>
 #include <asm/vdso.h>
+#include <asm/fixmap.h>
 
 #include "mmu_decl.h"
 
@@ -57,6 +58,20 @@ int init_bootmem_done;
 int mem_init_done;
 unsigned long memory_limit;
 
+#ifdef CONFIG_HIGHMEM
+pte_t *kmap_pte;
+pgprot_t kmap_prot;
+
+EXPORT_SYMBOL(kmap_prot);
+EXPORT_SYMBOL(kmap_pte);
+
+static inline pte_t *virt_to_kpte(unsigned long vaddr)
+{
+       return pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr),
+                       vaddr), vaddr), vaddr);
+}
+#endif
+
 int page_is_ram(unsigned long pfn)
 {
        unsigned long paddr = (pfn << PAGE_SHIFT);
@@ -216,7 +231,7 @@ void __init do_init_bootmem(void)
        unsigned long total_pages;
        int boot_mapsize;
 
-       max_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;
+       max_low_pfn = max_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;
        total_pages = (lmb_end_of_DRAM() - memstart_addr) >> PAGE_SHIFT;
 #ifdef CONFIG_HIGHMEM
        total_pages = total_lowmem >> PAGE_SHIFT;
@@ -232,7 +247,8 @@ void __init do_init_bootmem(void)
 
        start = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE);
 
-       boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages);
+       min_low_pfn = MEMORY_START >> PAGE_SHIFT;
+       boot_mapsize = init_bootmem_node(NODE_DATA(0), start >> PAGE_SHIFT, min_low_pfn, max_low_pfn);
 
        /* Add active regions with valid PFNs */
        for (i = 0; i < lmb.memory.cnt; i++) {
@@ -310,14 +326,19 @@ void __init paging_init(void)
        unsigned long top_of_ram = lmb_end_of_DRAM();
        unsigned long max_zone_pfns[MAX_NR_ZONES];
 
+#ifdef CONFIG_PPC32
+       unsigned long v = __fix_to_virt(__end_of_fixed_addresses - 1);
+       unsigned long end = __fix_to_virt(FIX_HOLE);
+
+       for (; v < end; v += PAGE_SIZE)
+               map_page(v, 0, 0); /* XXX gross */
+#endif
+
 #ifdef CONFIG_HIGHMEM
        map_page(PKMAP_BASE, 0, 0);     /* XXX gross */
-       pkmap_page_table = pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k
-                       (PKMAP_BASE), PKMAP_BASE), PKMAP_BASE), PKMAP_BASE);
-       map_page(KMAP_FIX_BEGIN, 0, 0); /* XXX gross */
-       kmap_pte = pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k
-                       (KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN),
-                        KMAP_FIX_BEGIN);
+       pkmap_page_table = virt_to_kpte(PKMAP_BASE);
+
+       kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN));
        kmap_prot = PAGE_KERNEL;
 #endif /* CONFIG_HIGHMEM */
 
index 1efd631211ef3772532430129176286bb182fbbc..dc704da363eb77897d392781591bf87ac337a8dd 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/cpu.h>
 #include <linux/notifier.h>
 #include <linux/lmb.h>
+#include <linux/of.h>
 #include <asm/sparsemem.h>
 #include <asm/prom.h>
 #include <asm/system.h>
index 64c44bcc68de03f926ca67c74cac4a8db80a5239..80d1babb230d5d2547c754613d3c5aeaba5220ab 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
+#include <asm/fixmap.h>
 #include <asm/io.h>
 
 #include "mmu_decl.h"
@@ -387,3 +388,25 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
        change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0));
 }
 #endif /* CONFIG_DEBUG_PAGEALLOC */
+
+static int fixmaps;
+unsigned long FIXADDR_TOP = 0xfffff000;
+EXPORT_SYMBOL(FIXADDR_TOP);
+
+void __set_fixmap (enum fixed_addresses idx, phys_addr_t phys, pgprot_t flags)
+{
+       unsigned long address = __fix_to_virt(idx);
+
+       if (idx >= __end_of_fixed_addresses) {
+               BUG();
+               return;
+       }
+
+       map_page(address, phys, flags);
+       fixmaps++;
+}
+
+void __this_fixmap_does_not_exist(void)
+{
+       WARN_ON(1);
+}
index f38c50b4ce56ab4d609488fcc0644800a3001313..87454c52697326e9173b4f695b46b9e705a77e97 100644 (file)
@@ -45,7 +45,6 @@ source "arch/powerpc/platforms/powermac/Kconfig"
 source "arch/powerpc/platforms/prep/Kconfig"
 source "arch/powerpc/platforms/maple/Kconfig"
 source "arch/powerpc/platforms/pasemi/Kconfig"
-source "arch/powerpc/platforms/celleb/Kconfig"
 source "arch/powerpc/platforms/ps3/Kconfig"
 source "arch/powerpc/platforms/cell/Kconfig"
 source "arch/powerpc/platforms/8xx/Kconfig"
index 5fc7fac10e938515c24c6cb157a6944b746ccf2b..f7efaa925a1350f8c9e157b1c8a31d45ea34047a 100644 (file)
@@ -220,8 +220,8 @@ config SMP
          If you don't know what to do here, say N.
 
 config NR_CPUS
-       int "Maximum number of CPUs (2-128)"
-       range 2 128
+       int "Maximum number of CPUs (2-1024)"
+       range 2 1024
        depends on SMP
        default "32" if PPC64
        default "4"
index a984894466d91c23dcafe92e97932e31c9d43bf3..423a0234dc31289d8b76cd69fb0828eb944349ce 100644 (file)
@@ -24,5 +24,4 @@ obj-$(CONFIG_PPC_MAPLE)               += maple/
 obj-$(CONFIG_PPC_PASEMI)       += pasemi/
 obj-$(CONFIG_PPC_CELL)         += cell/
 obj-$(CONFIG_PPC_PS3)          += ps3/
-obj-$(CONFIG_PPC_CELLEB)       += celleb/
 obj-$(CONFIG_EMBEDDED6xx)      += embedded6xx/
index 2f169991896d9a2d8e33524df82675e2d5e2278b..3959fcfe731c4a99e01ed7a124a067de85bf4e1a 100644 (file)
@@ -25,6 +25,19 @@ config PPC_IBM_CELL_BLADE
        select PPC_UDBG_16550
        select UDBG_RTAS_CONSOLE
 
+config PPC_CELLEB
+       bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
+       depends on PPC_MULTIPLATFORM && PPC64
+       select PPC_CELL
+       select PPC_CELL_NATIVE
+       select PPC_RTAS
+       select PPC_INDIRECT_IO
+       select PPC_OF_PLATFORM_PCI
+       select HAS_TXX9_SERIAL
+       select PPC_UDBG_BEAT
+       select USB_OHCI_BIG_ENDIAN_MMIO
+       select USB_EHCI_BIG_ENDIAN_MMIO
+
 menu "Cell Broadband Engine options"
        depends on PPC_CELL
 
index c89964c6fb1fc6c66166af182c6a9735e2cb857b..c2a7e4e5ddf983e5dacfbe45af4925a16d2dc122 100644 (file)
@@ -1,6 +1,7 @@
 obj-$(CONFIG_PPC_CELL_NATIVE)          += interrupt.o iommu.o setup.o \
                                           cbe_regs.o spider-pic.o \
-                                          pervasive.o pmu.o io-workarounds.o
+                                          pervasive.o pmu.o io-workarounds.o \
+                                          spider-pci.o
 obj-$(CONFIG_CBE_RAS)                  += ras.o
 
 obj-$(CONFIG_CBE_THERM)                        += cbe_thermal.o
@@ -26,3 +27,20 @@ obj-$(CONFIG_SPU_BASE)                       += spu_callbacks.o spu_base.o \
                                           spufs/
 
 obj-$(CONFIG_PCI_MSI)                  += axon_msi.o
+
+
+# celleb stuff
+ifeq ($(CONFIG_PPC_CELLEB),y)
+obj-y                                  += celleb_setup.o \
+                                          celleb_pci.o celleb_scc_epci.o \
+                                          celleb_scc_pciex.o \
+                                          celleb_scc_uhc.o \
+                                          io-workarounds.o spider-pci.o \
+                                          beat.o beat_htab.o beat_hvCall.o \
+                                          beat_interrupt.o beat_iommu.o
+
+obj-$(CONFIG_SMP)                      += beat_smp.o
+obj-$(CONFIG_PPC_UDBG_BEAT)            += beat_udbg.o
+obj-$(CONFIG_SERIAL_TXX9)              += celleb_scc_sio.o
+obj-$(CONFIG_SPU_BASE)                 += beat_spu_priv1.o
+endif
index d95e71dee91f85f000a1662c200f2075b6bec95f..c39f5c225f2e6420b45fc8afd1bbc2a0c379fa8b 100644 (file)
@@ -123,7 +123,7 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev)
                return NULL;
        }
 
-       for (; dn; tmp = of_get_parent(dn), of_node_put(dn), dn = tmp) {
+       for (; dn; dn = of_get_next_parent(dn)) {
                ph = of_get_property(dn, "msi-translator", NULL);
                if (ph)
                        break;
@@ -169,7 +169,7 @@ static int axon_msi_check_device(struct pci_dev *dev, int nvec, int type)
 
 static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
 {
-       struct device_node *dn, *tmp;
+       struct device_node *dn;
        struct msi_desc *entry;
        int len;
        const u32 *prop;
@@ -182,7 +182,7 @@ static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
 
        entry = list_first_entry(&dev->msi_list, struct msi_desc, list);
 
-       for (; dn; tmp = of_get_parent(dn), of_node_put(dn), dn = tmp) {
+       for (; dn; dn = of_get_next_parent(dn)) {
                if (entry->msi_attrib.is_64) {
                        prop = of_get_property(dn, "msi-address-64", &len);
                        if (prop)
similarity index 99%
rename from arch/powerpc/platforms/celleb/beat.c
rename to arch/powerpc/platforms/cell/beat.c
index b64b171f245b513e57ca5d7174c05384aecccf30..48c690ea65da36844de63f177e6d4982d4ec7fa4 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "beat_wrapper.h"
 #include "beat.h"
-#include "interrupt.h"
+#include "beat_interrupt.h"
 
 static int beat_pm_poweroff_flag;
 
similarity index 99%
rename from arch/powerpc/platforms/celleb/interrupt.c
rename to arch/powerpc/platforms/cell/beat_interrupt.c
index 69562a867876ebd54dbdd7e3f4ac85f2b34fd377..192a93509372ec8e949bcc91943c86127d3e3803 100644 (file)
@@ -26,7 +26,7 @@
 
 #include <asm/machdep.h>
 
-#include "interrupt.h"
+#include "beat_interrupt.h"
 #include "beat_wrapper.h"
 
 #define        MAX_IRQS        NR_IRQS
similarity index 99%
rename from arch/powerpc/platforms/celleb/smp.c
rename to arch/powerpc/platforms/cell/beat_smp.c
index a7631250aeb4658fcf176d9bee3029eac52675ba..26efc204c47f2271a4e4fe29622850a0ceea3d47 100644 (file)
@@ -37,7 +37,7 @@
 #include <asm/machdep.h>
 #include <asm/udbg.h>
 
-#include "interrupt.h"
+#include "beat_interrupt.h"
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
similarity index 93%
rename from arch/powerpc/platforms/celleb/pci.c
rename to arch/powerpc/platforms/cell/celleb_pci.c
index 51b390d34e4dc51dd085075b0b4289648ad26008..f39a3b2a1667838c80bf762af0cac1512f4fcde2 100644 (file)
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
-#include <asm/machdep.h>
 #include <asm/pci-bridge.h>
 #include <asm/ppc-pci.h>
 
-#include "pci.h"
-#include "interrupt.h"
+#include "io-workarounds.h"
+#include "celleb_pci.h"
 
 #define MAX_PCI_DEVICES    32
 #define MAX_PCI_FUNCTIONS   8
@@ -190,7 +189,7 @@ static int celleb_fake_pci_read_config(struct pci_bus *bus,
 
 
 static int celleb_fake_pci_write_config(struct pci_bus *bus,
-                unsigned int devfn, int where, int size, u32 val)
+               unsigned int devfn, int where, int size, u32 val)
 {
        char *config;
        struct device_node *node;
@@ -457,33 +456,42 @@ static int __init celleb_setup_fake_pci(struct device_node *dev,
        return 0;
 }
 
-void __init fake_pci_workaround_init(struct pci_controller *phb)
-{
-       /**
-        *  We will add fake pci bus to scc_pci_bus for the purpose to improve
-        *  I/O Macro performance. But device-tree and device drivers
-        *  are not ready to use address with a token.
-        */
-
-       /* celleb_pci_add_one(phb, NULL); */
-}
+static struct celleb_phb_spec celleb_fake_pci_spec __initdata = {
+       .setup = celleb_setup_fake_pci,
+};
 
 static struct of_device_id celleb_phb_match[] __initdata = {
        {
                .name = "pci-pseudo",
-               .data = celleb_setup_fake_pci,
+               .data = &celleb_fake_pci_spec,
        }, {
                .name = "epci",
-               .data = celleb_setup_epci,
+               .data = &celleb_epci_spec,
+       }, {
+               .name = "pcie",
+               .data = &celleb_pciex_spec,
        }, {
        },
 };
 
+static int __init celleb_io_workaround_init(struct pci_controller *phb,
+                                           struct celleb_phb_spec *phb_spec)
+{
+       if (phb_spec->ops) {
+               iowa_register_bus(phb, phb_spec->ops, phb_spec->iowa_init,
+                                 phb_spec->iowa_data);
+               io_workaround_init();
+       }
+
+       return 0;
+}
+
 int __init celleb_setup_phb(struct pci_controller *phb)
 {
        struct device_node *dev = phb->dn;
        const struct of_device_id *match;
-       int (*setup_func)(struct device_node *, struct pci_controller *);
+       struct celleb_phb_spec *phb_spec;
+       int rc;
 
        match = of_match_node(celleb_phb_match, dev);
        if (!match)
@@ -492,8 +500,12 @@ int __init celleb_setup_phb(struct pci_controller *phb)
        phb_set_bus_ranges(dev, phb);
        phb->buid = 1;
 
-       setup_func = match->data;
-       return (*setup_func)(dev, phb);
+       phb_spec = match->data;
+       rc = (*phb_spec->setup)(dev, phb);
+       if (rc)
+               return 1;
+
+       return celleb_io_workaround_init(phb, phb_spec);
 }
 
 int celleb_pci_probe_mode(struct pci_bus *bus)
similarity index 73%
rename from arch/powerpc/platforms/celleb/pci.h
rename to arch/powerpc/platforms/cell/celleb_pci.h
index 5d5544ffeddba2824638b07faadf3b7e75252bcb..4cba1523ec50463116108f6eb8fbe101d5fb4362 100644 (file)
 #include <asm/prom.h>
 #include <asm/ppc-pci.h>
 
+#include "io-workarounds.h"
+
+struct celleb_phb_spec {
+       int (*setup)(struct device_node *, struct pci_controller *);
+       struct ppc_pci_io *ops;
+       int (*iowa_init)(struct iowa_bus *, void *);
+       void *iowa_data;
+};
+
 extern int celleb_setup_phb(struct pci_controller *);
 extern int celleb_pci_probe_mode(struct pci_bus *);
 
-extern int celleb_setup_epci(struct device_node *, struct pci_controller *);
-
-extern void *celleb_dummy_page_va;
-extern int __init celleb_pci_workaround_init(void);
-extern void __init celleb_pci_add_one(struct pci_controller *,
-                                     void (*)(struct pci_controller *));
-extern void fake_pci_workaround_init(struct pci_controller *);
-extern void epci_workaround_init(struct pci_controller *);
+extern struct celleb_phb_spec celleb_epci_spec;
+extern struct celleb_phb_spec celleb_pciex_spec;
 
 #endif /* _CELLEB_PCI_H */
similarity index 68%
rename from arch/powerpc/platforms/celleb/scc.h
rename to arch/powerpc/platforms/cell/celleb_scc.h
index 6be1542a6e663daa93e759777e4b0aea057debf9..b596a711c348ca72bfc6310397ba2f6001ad793c 100644 (file)
 /* bits for SCC_EPCI_CNTOPT */
 #define SCC_EPCI_CNTOPT_O2PMB   0x00000002
 
+/* SCC PCIEXC SMMIO registers */
+#define PEXCADRS               0x000
+#define PEXCWDATA              0x004
+#define PEXCRDATA              0x008
+#define PEXDADRS               0x010
+#define PEXDCMND               0x014
+#define PEXDWDATA              0x018
+#define PEXDRDATA              0x01c
+#define PEXREQID               0x020
+#define PEXTIDMAP              0x024
+#define PEXINTMASK             0x028
+#define PEXINTSTS              0x02c
+#define PEXAERRMASK            0x030
+#define PEXAERRSTS             0x034
+#define PEXPRERRMASK           0x040
+#define PEXPRERRSTS            0x044
+#define PEXPRERRID01           0x048
+#define PEXPRERRID23           0x04c
+#define PEXVDMASK              0x050
+#define PEXVDSTS               0x054
+#define PEXRCVCPLIDA           0x060
+#define PEXLENERRIDA           0x068
+#define PEXPHYPLLST            0x070
+#define PEXDMRDEN0             0x100
+#define PEXDMRDADR0            0x104
+#define PEXDMRDENX             0x110
+#define PEXDMRDADRX            0x114
+#define PEXECMODE              0xf00
+#define PEXMAEA(n)             (0xf50 + (8 * n))
+#define PEXMAEC(n)             (0xf54 + (8 * n))
+#define PEXCCRCTRL             0xff0
+
+/* SCC PCIEXC bits and shifts for PEXCADRS */
+#define PEXCADRS_BYTE_EN_SHIFT         20
+#define PEXCADRS_CMD_SHIFT             16
+#define PEXCADRS_CMD_READ              (0xa << PEXCADRS_CMD_SHIFT)
+#define PEXCADRS_CMD_WRITE             (0xb << PEXCADRS_CMD_SHIFT)
+
+/* SCC PCIEXC shifts for PEXDADRS */
+#define PEXDADRS_BUSNO_SHIFT           20
+#define PEXDADRS_DEVNO_SHIFT           15
+#define PEXDADRS_FUNCNO_SHIFT          12
+
+/* SCC PCIEXC bits and shifts for PEXDCMND */
+#define PEXDCMND_BYTE_EN_SHIFT         4
+#define PEXDCMND_IO_READ               0x2
+#define PEXDCMND_IO_WRITE              0x3
+#define PEXDCMND_CONFIG_READ           0xa
+#define PEXDCMND_CONFIG_WRITE          0xb
+
+/* SCC PCIEXC bits for PEXPHYPLLST */
+#define PEXPHYPLLST_PEXPHYAPLLST       0x00000001
+
+/* SCC PCIEXC bits for PEXECMODE */
+#define PEXECMODE_ALL_THROUGH          0x00000000
+#define PEXECMODE_ALL_8BIT             0x00550155
+#define PEXECMODE_ALL_16BIT            0x00aa02aa
+
+/* SCC PCIEXC bits for PEXCCRCTRL */
+#define PEXCCRCTRL_PEXIPCOREEN         0x00040000
+#define PEXCCRCTRL_PEXIPCONTEN         0x00020000
+#define PEXCCRCTRL_PEXPHYPLLEN         0x00010000
+#define PEXCCRCTRL_PCIEXCAOCKEN                0x00000100
+
+/* SCC PCIEXC port configuration registers */
+#define PEXTCERRCHK            0x21c
+#define PEXTAMAPB0             0x220
+#define PEXTAMAPL0             0x224
+#define PEXTAMAPB(n)           (PEXTAMAPB0 + 8 * (n))
+#define PEXTAMAPL(n)           (PEXTAMAPL0 + 8 * (n))
+#define PEXCHVC0P              0x500
+#define PEXCHVC0NP             0x504
+#define PEXCHVC0C              0x508
+#define PEXCDVC0P              0x50c
+#define PEXCDVC0NP             0x510
+#define PEXCDVC0C              0x514
+#define PEXCHVCXP              0x518
+#define PEXCHVCXNP             0x51c
+#define PEXCHVCXC              0x520
+#define PEXCDVCXP              0x524
+#define PEXCDVCXNP             0x528
+#define PEXCDVCXC              0x52c
+#define PEXCTTRG               0x530
+#define PEXTSCTRL              0x700
+#define PEXTSSTS               0x704
+#define PEXSKPCTRL             0x708
+
 /* UHC registers */
 #define SCC_UHC_CKRCTRL         0xff0
 #define SCC_UHC_ECMODE          0xf00
similarity index 86%
rename from arch/powerpc/platforms/celleb/scc_epci.c
rename to arch/powerpc/platforms/cell/celleb_scc_epci.c
index a999b393f6f6e81a0f2e72a2e52cbad49aa7d4bb..08c285b10e30a81f89e4113773e357abd5742971 100644 (file)
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
-#include <asm/machdep.h>
 #include <asm/pci-bridge.h>
 #include <asm/ppc-pci.h>
 
-#include "scc.h"
-#include "pci.h"
-#include "interrupt.h"
+#include "celleb_scc.h"
+#include "celleb_pci.h"
 
 #define MAX_PCI_DEVICES   32
 #define MAX_PCI_FUNCTIONS  8
 
 #define iob()  __asm__ __volatile__("eieio; sync":::"memory")
 
-struct epci_private {
-       dma_addr_t      dummy_page_da;
-};
-
 static inline PCI_IO_ADDR celleb_epci_get_epci_base(
                                        struct pci_controller *hose)
 {
@@ -71,42 +65,6 @@ static inline PCI_IO_ADDR celleb_epci_get_epci_cfg(
        return hose->cfg_data;
 }
 
-static void scc_epci_dummy_read(struct pci_controller *hose)
-{
-       PCI_IO_ADDR epci_base;
-       u32 val;
-
-       epci_base = celleb_epci_get_epci_base(hose);
-
-       val = in_be32(epci_base + SCC_EPCI_WATRP);
-       iosync();
-
-       return;
-}
-
-void __init epci_workaround_init(struct pci_controller *hose)
-{
-       PCI_IO_ADDR epci_base;
-       PCI_IO_ADDR reg;
-       struct epci_private *private = hose->private_data;
-
-       BUG_ON(!private);
-
-       private->dummy_page_da = dma_map_single(hose->parent,
-               celleb_dummy_page_va, PAGE_SIZE, DMA_FROM_DEVICE);
-       if (private->dummy_page_da == DMA_ERROR_CODE) {
-               printk(KERN_ERR "EPCI: dummy read disabled. "
-                      "Map dummy page failed.\n");
-               return;
-       }
-
-       celleb_pci_add_one(hose, scc_epci_dummy_read);
-       epci_base = celleb_epci_get_epci_base(hose);
-
-       reg = epci_base + SCC_EPCI_DUMYRADR;
-       out_be32(reg, private->dummy_page_da);
-}
-
 static inline void clear_and_disable_master_abort_interrupt(
                                        struct pci_controller *hose)
 {
@@ -151,10 +109,8 @@ static int celleb_epci_check_abort(struct pci_controller *hose,
        return PCIBIOS_SUCCESSFUL;
 }
 
-static PCI_IO_ADDR celleb_epci_make_config_addr(
-                                       struct pci_bus *bus,
-                                       struct pci_controller *hose,
-                                       unsigned int devfn, int where)
+static PCI_IO_ADDR celleb_epci_make_config_addr(struct pci_bus *bus,
+               struct pci_controller *hose, unsigned int devfn, int where)
 {
        PCI_IO_ADDR addr;
 
@@ -425,8 +381,8 @@ static int __init celleb_epci_init(struct pci_controller *hose)
        return 0;
 }
 
-int __init celleb_setup_epci(struct device_node *node,
-                               struct pci_controller *hose)
+static int __init celleb_setup_epci(struct device_node *node,
+                                   struct pci_controller *hose)
 {
        struct resource r;
 
@@ -450,8 +406,7 @@ int __init celleb_setup_epci(struct device_node *node,
        if (!hose->cfg_addr)
                goto error;
        pr_debug("EPCI: cfg_addr map 0x%016lx->0x%016lx + 0x%016lx\n",
-                r.start, (unsigned long)hose->cfg_addr,
-               (r.end - r.start + 1));
+                r.start, (unsigned long)hose->cfg_addr, (r.end - r.start + 1));
 
        if (of_address_to_resource(node, 2, &r))
                goto error;
@@ -459,14 +414,7 @@ int __init celleb_setup_epci(struct device_node *node,
        if (!hose->cfg_data)
                goto error;
        pr_debug("EPCI: cfg_data map 0x%016lx->0x%016lx + 0x%016lx\n",
-                r.start, (unsigned long)hose->cfg_data,
-               (r.end - r.start + 1));
-
-       hose->private_data = kzalloc(sizeof(struct epci_private), GFP_KERNEL);
-       if (hose->private_data == NULL) {
-               printk(KERN_ERR "EPCI: no memory for private data.\n");
-               goto error;
-       }
+                r.start, (unsigned long)hose->cfg_data, (r.end - r.start + 1));
 
        hose->ops = &celleb_epci_ops;
        celleb_epci_init(hose);
@@ -474,8 +422,6 @@ int __init celleb_setup_epci(struct device_node *node,
        return 0;
 
 error:
-       kfree(hose->private_data);
-
        if (hose->cfg_addr)
                iounmap(hose->cfg_addr);
 
@@ -483,3 +429,10 @@ error:
                iounmap(hose->cfg_data);
        return 1;
 }
+
+struct celleb_phb_spec celleb_epci_spec __initdata = {
+       .setup = celleb_setup_epci,
+       .ops = &spiderpci_ops,
+       .iowa_init = &spiderpci_iowa_init,
+       .iowa_data = (void *)0,
+};
diff --git a/arch/powerpc/platforms/cell/celleb_scc_pciex.c b/arch/powerpc/platforms/cell/celleb_scc_pciex.c
new file mode 100644 (file)
index 0000000..ab24d94
--- /dev/null
@@ -0,0 +1,547 @@
+/*
+ * Support for Celleb PCI-Express.
+ *
+ * (C) Copyright 2007-2008 TOSHIBA 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/iommu.h>
+#include <asm/byteorder.h>
+
+#include "celleb_scc.h"
+#include "celleb_pci.h"
+
+#define PEX_IN(base, off)      in_be32((void *)(base) + (off))
+#define PEX_OUT(base, off, data) out_be32((void *)(base) + (off), (data))
+
+static void scc_pciex_io_flush(struct iowa_bus *bus)
+{
+       (void)PEX_IN(bus->phb->cfg_addr, PEXDMRDEN0);
+}
+
+/*
+ * Memory space access to device on PCIEX
+ */
+#define PCIEX_MMIO_READ(name, ret)                                     \
+static ret scc_pciex_##name(const PCI_IO_ADDR addr)                    \
+{                                                                      \
+       ret val = __do_##name(addr);                                    \
+       scc_pciex_io_flush(iowa_mem_find_bus(addr));                    \
+       return val;                                                     \
+}
+
+#define PCIEX_MMIO_READ_STR(name)                                      \
+static void scc_pciex_##name(const PCI_IO_ADDR addr, void *buf,                \
+                            unsigned long count)                       \
+{                                                                      \
+       __do_##name(addr, buf, count);                                  \
+       scc_pciex_io_flush(iowa_mem_find_bus(addr));                    \
+}
+
+PCIEX_MMIO_READ(readb, u8)
+PCIEX_MMIO_READ(readw, u16)
+PCIEX_MMIO_READ(readl, u32)
+PCIEX_MMIO_READ(readq, u64)
+PCIEX_MMIO_READ(readw_be, u16)
+PCIEX_MMIO_READ(readl_be, u32)
+PCIEX_MMIO_READ(readq_be, u64)
+PCIEX_MMIO_READ_STR(readsb)
+PCIEX_MMIO_READ_STR(readsw)
+PCIEX_MMIO_READ_STR(readsl)
+
+static void scc_pciex_memcpy_fromio(void *dest, const PCI_IO_ADDR src,
+                                   unsigned long n)
+{
+       __do_memcpy_fromio(dest, src, n);
+       scc_pciex_io_flush(iowa_mem_find_bus(src));
+}
+
+/*
+ * I/O port access to devices on PCIEX.
+ */
+
+static inline unsigned long get_bus_address(struct pci_controller *phb,
+                                           unsigned long port)
+{
+       return port - ((unsigned long)(phb->io_base_virt) - _IO_BASE);
+}
+
+static u32 scc_pciex_read_port(struct pci_controller *phb,
+                              unsigned long port, int size)
+{
+       unsigned int byte_enable;
+       unsigned int cmd, shift;
+       unsigned long addr;
+       u32 data, ret;
+
+       BUG_ON(((port & 0x3ul) + size) > 4);
+
+       addr = get_bus_address(phb, port);
+       shift = addr & 0x3ul;
+       byte_enable = ((1 << size) - 1) << shift;
+       cmd = PEXDCMND_IO_READ | (byte_enable << PEXDCMND_BYTE_EN_SHIFT);
+       PEX_OUT(phb->cfg_addr, PEXDADRS, (addr & ~0x3ul));
+       PEX_OUT(phb->cfg_addr, PEXDCMND, cmd);
+       data = PEX_IN(phb->cfg_addr, PEXDRDATA);
+       ret = (data >> (shift * 8)) & (0xFFFFFFFF >> ((4 - size) * 8));
+
+       pr_debug("PCIEX:PIO READ:port=0x%lx, addr=0x%lx, size=%d, be=%x,"
+                " cmd=%x, data=%x, ret=%x\n", port, addr, size, byte_enable,
+                cmd, data, ret);
+
+       return ret;
+}
+
+static void scc_pciex_write_port(struct pci_controller *phb,
+                                unsigned long port, int size, u32 val)
+{
+       unsigned int byte_enable;
+       unsigned int cmd, shift;
+       unsigned long addr;
+       u32 data;
+
+       BUG_ON(((port & 0x3ul) + size) > 4);
+
+       addr = get_bus_address(phb, port);
+       shift = addr & 0x3ul;
+       byte_enable = ((1 << size) - 1) << shift;
+       cmd = PEXDCMND_IO_WRITE | (byte_enable << PEXDCMND_BYTE_EN_SHIFT);
+       data = (val & (0xFFFFFFFF >> (4 - size) * 8)) << (shift * 8);
+       PEX_OUT(phb->cfg_addr, PEXDADRS, (addr & ~0x3ul));
+       PEX_OUT(phb->cfg_addr, PEXDCMND, cmd);
+       PEX_OUT(phb->cfg_addr, PEXDWDATA, data);
+
+       pr_debug("PCIEX:PIO WRITE:port=0x%lx, addr=%lx, size=%d, val=%x,"
+                " be=%x, cmd=%x, data=%x\n", port, addr, size, val,
+                byte_enable, cmd, data);
+}
+
+static u8 __scc_pciex_inb(struct pci_controller *phb, unsigned long port)
+{
+       return (u8)scc_pciex_read_port(phb, port, 1);
+}
+
+static u16 __scc_pciex_inw(struct pci_controller *phb, unsigned long port)
+{
+       u32 data;
+       if ((port & 0x3ul) < 3)
+               data = scc_pciex_read_port(phb, port, 2);
+       else {
+               u32 d1 = scc_pciex_read_port(phb, port, 1);
+               u32 d2 = scc_pciex_read_port(phb, port + 1, 1);
+               data = d1 | (d2 << 8);
+       }
+       return (u16)data;
+}
+
+static u32 __scc_pciex_inl(struct pci_controller *phb, unsigned long port)
+{
+       unsigned int mod = port & 0x3ul;
+       u32 data;
+       if (mod == 0)
+               data = scc_pciex_read_port(phb, port, 4);
+       else {
+               u32 d1 = scc_pciex_read_port(phb, port, 4 - mod);
+               u32 d2 = scc_pciex_read_port(phb, port + 1, mod);
+               data = d1 | (d2 << (mod * 8));
+       }
+       return data;
+}
+
+static void __scc_pciex_outb(struct pci_controller *phb,
+                            u8 val, unsigned long port)
+{
+       scc_pciex_write_port(phb, port, 1, (u32)val);
+}
+
+static void __scc_pciex_outw(struct pci_controller *phb,
+                            u16 val, unsigned long port)
+{
+       if ((port & 0x3ul) < 3)
+               scc_pciex_write_port(phb, port, 2, (u32)val);
+       else {
+               u32 d1 = val & 0x000000FF;
+               u32 d2 = (val & 0x0000FF00) >> 8;
+               scc_pciex_write_port(phb, port, 1, d1);
+               scc_pciex_write_port(phb, port + 1, 1, d2);
+       }
+}
+
+static void __scc_pciex_outl(struct pci_controller *phb,
+                            u32 val, unsigned long port)
+{
+       unsigned int mod = port & 0x3ul;
+       if (mod == 0)
+               scc_pciex_write_port(phb, port, 4, val);
+       else {
+               u32 d1 = val & (0xFFFFFFFFul >> (mod * 8));
+               u32 d2 = val >> ((4 - mod) * 8);
+               scc_pciex_write_port(phb, port, 4 - mod, d1);
+               scc_pciex_write_port(phb, port + 1, mod, d2);
+       }
+}
+
+#define PCIEX_PIO_FUNC(size, name)                                     \
+static u##size scc_pciex_in##name(unsigned long port)                  \
+{                                                                      \
+       struct iowa_bus *bus = iowa_pio_find_bus(port);                 \
+       u##size data = __scc_pciex_in##name(bus->phb, port);            \
+       scc_pciex_io_flush(bus);                                        \
+       return data;                                                    \
+}                                                                      \
+static void scc_pciex_ins##name(unsigned long p, void *b, unsigned long c) \
+{                                                                      \
+       struct iowa_bus *bus = iowa_pio_find_bus(p);                    \
+       u##size *dst = b;                                               \
+       for (; c != 0; c--, dst++)                                      \
+               *dst = cpu_to_le##size(__scc_pciex_in##name(bus->phb, p)); \
+       scc_pciex_io_flush(bus);                                        \
+}                                                                      \
+static void scc_pciex_out##name(u##size val, unsigned long port)       \
+{                                                                      \
+       struct iowa_bus *bus = iowa_pio_find_bus(port);                 \
+       __scc_pciex_out##name(bus->phb, val, port);                     \
+}                                                                      \
+static void scc_pciex_outs##name(unsigned long p, const void *b,       \
+                                unsigned long c)                       \
+{                                                                      \
+       struct iowa_bus *bus = iowa_pio_find_bus(p);                    \
+       const u##size *src = b;                                         \
+       for (; c != 0; c--, src++)                                      \
+               __scc_pciex_out##name(bus->phb, le##size##_to_cpu(*src), p); \
+}
+#define cpu_to_le8(x) (x)
+#define le8_to_cpu(x) (x)
+PCIEX_PIO_FUNC(8, b)
+PCIEX_PIO_FUNC(16, w)
+PCIEX_PIO_FUNC(32, l)
+
+static struct ppc_pci_io scc_pciex_ops = {
+       .readb = scc_pciex_readb,
+       .readw = scc_pciex_readw,
+       .readl = scc_pciex_readl,
+       .readq = scc_pciex_readq,
+       .readw_be = scc_pciex_readw_be,
+       .readl_be = scc_pciex_readl_be,
+       .readq_be = scc_pciex_readq_be,
+       .readsb = scc_pciex_readsb,
+       .readsw = scc_pciex_readsw,
+       .readsl = scc_pciex_readsl,
+       .memcpy_fromio = scc_pciex_memcpy_fromio,
+       .inb = scc_pciex_inb,
+       .inw = scc_pciex_inw,
+       .inl = scc_pciex_inl,
+       .outb = scc_pciex_outb,
+       .outw = scc_pciex_outw,
+       .outl = scc_pciex_outl,
+       .insb = scc_pciex_insb,
+       .insw = scc_pciex_insw,
+       .insl = scc_pciex_insl,
+       .outsb = scc_pciex_outsb,
+       .outsw = scc_pciex_outsw,
+       .outsl = scc_pciex_outsl,
+};
+
+static int __init scc_pciex_iowa_init(struct iowa_bus *bus, void *data)
+{
+       dma_addr_t dummy_page_da;
+       void *dummy_page_va;
+
+       dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!dummy_page_va) {
+               pr_err("PCIEX:Alloc dummy_page_va failed\n");
+               return -1;
+       }
+
+       dummy_page_da = dma_map_single(bus->phb->parent, dummy_page_va,
+                                      PAGE_SIZE, DMA_FROM_DEVICE);
+       if (dma_mapping_error(dummy_page_da)) {
+               pr_err("PCIEX:Map dummy page failed.\n");
+               kfree(dummy_page_va);
+               return -1;
+       }
+
+       PEX_OUT(bus->phb->cfg_addr, PEXDMRDADR0, dummy_page_da);
+
+       return 0;
+}
+
+/*
+ * config space access
+ */
+#define MK_PEXDADRS(bus_no, dev_no, func_no, addr) \
+       ((uint32_t)(((addr) & ~0x3UL) | \
+       ((bus_no) << PEXDADRS_BUSNO_SHIFT) | \
+       ((dev_no)  << PEXDADRS_DEVNO_SHIFT) | \
+       ((func_no) << PEXDADRS_FUNCNO_SHIFT)))
+
+#define MK_PEXDCMND_BYTE_EN(addr, size) \
+       ((((0x1 << (size))-1) << ((addr) & 0x3)) << PEXDCMND_BYTE_EN_SHIFT)
+#define MK_PEXDCMND(cmd, addr, size) ((cmd) | MK_PEXDCMND_BYTE_EN(addr, size))
+
+static uint32_t config_read_pciex_dev(unsigned int *base,
+               uint64_t bus_no, uint64_t dev_no, uint64_t func_no,
+               uint64_t off, uint64_t size)
+{
+       uint32_t ret;
+       uint32_t addr, cmd;
+
+       addr = MK_PEXDADRS(bus_no, dev_no, func_no, off);
+       cmd = MK_PEXDCMND(PEXDCMND_CONFIG_READ, off, size);
+       PEX_OUT(base, PEXDADRS, addr);
+       PEX_OUT(base, PEXDCMND, cmd);
+       ret = (PEX_IN(base, PEXDRDATA)
+               >> ((off & (4-size)) * 8)) & ((0x1 << (size * 8)) - 1);
+       return ret;
+}
+
+static void config_write_pciex_dev(unsigned int *base, uint64_t bus_no,
+       uint64_t dev_no, uint64_t func_no, uint64_t off, uint64_t size,
+       uint32_t data)
+{
+       uint32_t addr, cmd;
+
+       addr = MK_PEXDADRS(bus_no, dev_no, func_no, off);
+       cmd = MK_PEXDCMND(PEXDCMND_CONFIG_WRITE, off, size);
+       PEX_OUT(base, PEXDADRS, addr);
+       PEX_OUT(base, PEXDCMND, cmd);
+       PEX_OUT(base, PEXDWDATA,
+               (data & ((0x1 << (size * 8)) - 1)) << ((off & (4-size)) * 8));
+}
+
+#define MK_PEXCADRS_BYTE_EN(off, len) \
+       ((((0x1 << (len)) - 1) << ((off) & 0x3)) << PEXCADRS_BYTE_EN_SHIFT)
+#define MK_PEXCADRS(cmd, addr, size) \
+       ((cmd) | MK_PEXCADRS_BYTE_EN(addr, size) | ((addr) & ~0x3))
+static uint32_t config_read_pciex_rc(unsigned int *base,
+                                    uint32_t where, uint32_t size)
+{
+       PEX_OUT(base, PEXCADRS, MK_PEXCADRS(PEXCADRS_CMD_READ, where, size));
+       return (PEX_IN(base, PEXCRDATA)
+               >> ((where & (4 - size)) * 8)) & ((0x1 << (size * 8)) - 1);
+}
+
+static void config_write_pciex_rc(unsigned int *base, uint32_t where,
+                                 uint32_t size, uint32_t val)
+{
+       uint32_t data;
+
+       data = (val & ((0x1 << (size * 8)) - 1)) << ((where & (4 - size)) * 8);
+       PEX_OUT(base, PEXCADRS, MK_PEXCADRS(PEXCADRS_CMD_WRITE, where, size));
+       PEX_OUT(base, PEXCWDATA, data);
+}
+
+/* Interfaces */
+/* Note: Work-around
+ *  On SCC PCIEXC, one device is seen on all 32 dev_no.
+ *  As SCC PCIEXC can have only one device on the bus, we look only one dev_no.
+ * (dev_no = 1)
+ */
+static int scc_pciex_read_config(struct pci_bus *bus, unsigned int devfn,
+                                int where, int size, unsigned int *val)
+{
+       struct device_node *dn;
+       struct pci_controller *phb;
+
+       dn = bus->sysdata;
+       phb = pci_find_hose_for_OF_device(dn);
+
+       if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1) {
+               *val = ~0;
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+
+       if (bus->number == 0 && PCI_SLOT(devfn) == 0)
+               *val = config_read_pciex_rc(phb->cfg_addr, where, size);
+       else
+               *val = config_read_pciex_dev(phb->cfg_addr, bus->number,
+                               PCI_SLOT(devfn), PCI_FUNC(devfn), where, size);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int scc_pciex_write_config(struct pci_bus *bus, unsigned int devfn,
+                                 int where, int size, unsigned int val)
+{
+       struct device_node *dn;
+       struct pci_controller *phb;
+
+       dn = bus->sysdata;
+       phb = pci_find_hose_for_OF_device(dn);
+
+       if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       if (bus->number == 0 && PCI_SLOT(devfn) == 0)
+               config_write_pciex_rc(phb->cfg_addr, where, size, val);
+       else
+               config_write_pciex_dev(phb->cfg_addr, bus->number,
+                       PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val);
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops scc_pciex_pci_ops = {
+       scc_pciex_read_config,
+       scc_pciex_write_config,
+};
+
+static void pciex_clear_intr_all(unsigned int *base)
+{
+       PEX_OUT(base, PEXAERRSTS, 0xffffffff);
+       PEX_OUT(base, PEXPRERRSTS, 0xffffffff);
+       PEX_OUT(base, PEXINTSTS, 0xffffffff);
+}
+
+#if 0
+static void pciex_disable_intr_all(unsigned int *base)
+{
+       PEX_OUT(base, PEXINTMASK,   0x0);
+       PEX_OUT(base, PEXAERRMASK,  0x0);
+       PEX_OUT(base, PEXPRERRMASK, 0x0);
+       PEX_OUT(base, PEXVDMASK,    0x0);
+}
+#endif
+
+static void pciex_enable_intr_all(unsigned int *base)
+{
+       PEX_OUT(base, PEXINTMASK, 0x0000e7f1);
+       PEX_OUT(base, PEXAERRMASK, 0x03ff01ff);
+       PEX_OUT(base, PEXPRERRMASK, 0x0001010f);
+       PEX_OUT(base, PEXVDMASK, 0x00000001);
+}
+
+static void pciex_check_status(unsigned int *base)
+{
+       uint32_t err = 0;
+       uint32_t intsts, aerr, prerr, rcvcp, lenerr;
+       uint32_t maea, maec;
+
+       intsts = PEX_IN(base, PEXINTSTS);
+       aerr = PEX_IN(base, PEXAERRSTS);
+       prerr = PEX_IN(base, PEXPRERRSTS);
+       rcvcp = PEX_IN(base, PEXRCVCPLIDA);
+       lenerr = PEX_IN(base, PEXLENERRIDA);
+
+       if (intsts || aerr || prerr || rcvcp || lenerr)
+               err = 1;
+
+       pr_info("PCEXC interrupt!!\n");
+       pr_info("PEXINTSTS    :0x%08x\n", intsts);
+       pr_info("PEXAERRSTS   :0x%08x\n", aerr);
+       pr_info("PEXPRERRSTS  :0x%08x\n", prerr);
+       pr_info("PEXRCVCPLIDA :0x%08x\n", rcvcp);
+       pr_info("PEXLENERRIDA :0x%08x\n", lenerr);
+
+       /* print detail of Protection Error */
+       if (intsts & 0x00004000) {
+               uint32_t i, n;
+               for (i = 0; i < 4; i++) {
+                       n = 1 << i;
+                       if (prerr & n) {
+                               maea = PEX_IN(base, PEXMAEA(i));
+                               maec = PEX_IN(base, PEXMAEC(i));
+                               pr_info("PEXMAEC%d     :0x%08x\n", i, maec);
+                               pr_info("PEXMAEA%d     :0x%08x\n", i, maea);
+                       }
+               }
+       }
+
+       if (err)
+               pciex_clear_intr_all(base);
+}
+
+static irqreturn_t pciex_handle_internal_irq(int irq, void *dev_id)
+{
+       struct pci_controller *phb = dev_id;
+
+       pr_debug("PCIEX:pciex_handle_internal_irq(irq=%d)\n", irq);
+
+       BUG_ON(phb->cfg_addr == NULL);
+
+       pciex_check_status(phb->cfg_addr);
+
+       return IRQ_HANDLED;
+}
+
+static __init int celleb_setup_pciex(struct device_node *node,
+                                    struct pci_controller *phb)
+{
+       struct resource r;
+       struct of_irq oirq;
+       int virq;
+
+       /* SMMIO registers; used inside this file */
+       if (of_address_to_resource(node, 0, &r)) {
+               pr_err("PCIEXC:Failed to get config resource.\n");
+               return 1;
+       }
+       phb->cfg_addr = ioremap(r.start, r.end - r.start + 1);
+       if (!phb->cfg_addr) {
+               pr_err("PCIEXC:Failed to remap SMMIO region.\n");
+               return 1;
+       }
+
+       /* Not use cfg_data,  cmd and data regs are near address reg */
+       phb->cfg_data = NULL;
+
+       /* set pci_ops */
+       phb->ops = &scc_pciex_pci_ops;
+
+       /* internal interrupt handler */
+       if (of_irq_map_one(node, 1, &oirq)) {
+               pr_err("PCIEXC:Failed to map irq\n");
+               goto error;
+       }
+       virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+                                    oirq.size);
+       if (request_irq(virq, pciex_handle_internal_irq,
+                       IRQF_DISABLED, "pciex", (void *)phb)) {
+               pr_err("PCIEXC:Failed to request irq\n");
+               goto error;
+       }
+
+       /* enable all interrupts */
+       pciex_clear_intr_all(phb->cfg_addr);
+       pciex_enable_intr_all(phb->cfg_addr);
+       /* MSI: TBD */
+
+       return 0;
+
+error:
+       phb->cfg_data = NULL;
+       if (phb->cfg_addr)
+               iounmap(phb->cfg_addr);
+       phb->cfg_addr = NULL;
+       return 1;
+}
+
+struct celleb_phb_spec celleb_pciex_spec __initdata = {
+       .setup = celleb_setup_pciex,
+       .ops = &scc_pciex_ops,
+       .iowa_init = &scc_pciex_iowa_init,
+};
similarity index 99%
rename from arch/powerpc/platforms/celleb/scc_uhc.c
rename to arch/powerpc/platforms/cell/celleb_scc_uhc.c
index cb4307994087638916db9c126fc5addcfaaf3b75..d63b720bfe3a591aff611d6cc31854e282037dd7 100644 (file)
@@ -25,7 +25,7 @@
 #include <asm/io.h>
 #include <asm/machdep.h>
 
-#include "scc.h"
+#include "celleb_scc.h"
 
 #define UHC_RESET_WAIT_MAX 10000
 
similarity index 97%
rename from arch/powerpc/platforms/celleb/setup.c
rename to arch/powerpc/platforms/cell/celleb_setup.c
index f27ae1e3fb58d010f79735822cf9b297c6407e5f..b11cb30decb2ded24fa63160c7b84f31c683ac05 100644 (file)
 #include <asm/rtas.h>
 #include <asm/cell-regs.h>
 
-#include "interrupt.h"
+#include "beat_interrupt.h"
 #include "beat_wrapper.h"
 #include "beat.h"
-#include "pci.h"
-#include "../cell/interrupt.h"
-#include "../cell/pervasive.h"
-#include "../cell/ras.h"
+#include "celleb_pci.h"
+#include "interrupt.h"
+#include "pervasive.h"
+#include "ras.h"
 
 static char celleb_machine_type[128] = "Celleb";
 
@@ -114,8 +114,6 @@ static int __init celleb_publish_devices(void)
        /* Publish OF platform devices for southbridge IOs */
        of_platform_bus_probe(NULL, celleb_bus_ids, NULL);
 
-       celleb_pci_workaround_init();
-
        return 0;
 }
 machine_device_initcall(celleb_beat, celleb_publish_devices);
index 979d4b67efb45dcb6562133d2d977ebed6de14e4..3b84e8be314c4f5a09217f11d89426d86c93b19e 100644 (file)
@@ -1,6 +1,9 @@
 /*
+ * Support PCI IO workaround
+ *
  *  Copyright (C) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>
  *                    IBM, Corp.
+ *  (C) Copyright 2007-2008 TOSHIBA CORPORATION
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 #undef DEBUG
 
 #include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/pci.h>
+
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/pci-bridge.h>
+#include <asm/pgtable.h>
 #include <asm/ppc-pci.h>
 
+#include "io-workarounds.h"
 
-#define SPIDER_PCI_REG_BASE            0xd000
-#define SPIDER_PCI_VCI_CNTL_STAT       0x0110
-#define SPIDER_PCI_DUMMY_READ          0x0810
-#define SPIDER_PCI_DUMMY_READ_BASE     0x0814
+#define IOWA_MAX_BUS   8
 
-/* Undefine that to re-enable bogus prefetch
- *
- * Without that workaround, the chip will do bogus prefetch past
- * page boundary from system memory. This setting will disable that,
- * though the documentation is unclear as to the consequences of doing
- * so, either purely performances, or possible misbehaviour... It's not
- * clear wether the chip can handle unaligned accesses at all without
- * prefetching enabled.
- *
- * For now, things appear to be behaving properly with that prefetching
- * disabled and IDE, possibly because IDE isn't doing any unaligned
- * access.
- */
-#define SPIDER_DISABLE_PREFETCH
+static struct iowa_bus iowa_busses[IOWA_MAX_BUS];
+static unsigned int iowa_bus_count;
 
-#define MAX_SPIDERS    3
+static struct iowa_bus *iowa_pci_find(unsigned long vaddr, unsigned long paddr)
+{
+       int i, j;
+       struct resource *res;
+       unsigned long vstart, vend;
 
-static struct spider_pci_bus {
-       void __iomem    *regs;
-       unsigned long   mmio_start;
-       unsigned long   mmio_end;
-       unsigned long   pio_vstart;
-       unsigned long   pio_vend;
-} spider_pci_busses[MAX_SPIDERS];
-static int spider_pci_count;
+       for (i = 0; i < iowa_bus_count; i++) {
+               struct iowa_bus *bus = &iowa_busses[i];
+               struct pci_controller *phb = bus->phb;
 
-static struct spider_pci_bus *spider_pci_find(unsigned long vaddr,
-                                             unsigned long paddr)
-{
-       int i;
-
-       for (i = 0; i < spider_pci_count; i++) {
-               struct spider_pci_bus *bus = &spider_pci_busses[i];
-               if (paddr && paddr >= bus->mmio_start && paddr < bus->mmio_end)
-                       return bus;
-               if (vaddr && vaddr >= bus->pio_vstart && vaddr < bus->pio_vend)
-                       return bus;
+               if (vaddr) {
+                       vstart = (unsigned long)phb->io_base_virt;
+                       vend = vstart + phb->pci_io_size - 1;
+                       if ((vaddr >= vstart) && (vaddr <= vend))
+                               return bus;
+               }
+
+               if (paddr)
+                       for (j = 0; j < 3; j++) {
+                               res = &phb->mem_resources[j];
+                               if (paddr >= res->start && paddr <= res->end)
+                                       return bus;
+                       }
        }
+
        return NULL;
 }
 
-static void spider_io_flush(const volatile void __iomem *addr)
+struct iowa_bus *iowa_mem_find_bus(const PCI_IO_ADDR addr)
 {
-       struct spider_pci_bus *bus;
+       struct iowa_bus *bus;
        int token;
 
-       /* Get platform token (set by ioremap) from address */
        token = PCI_GET_ADDR_TOKEN(addr);
 
-       /* Fast path if we have a non-0 token, it indicates which bus we
-        * are on.
-        *
-        * If the token is 0, that means either that the ioremap was done
-        * before we initialized this layer, or it's a PIO operation. We
-        * fallback to a low path in this case. Hopefully, internal devices
-        * which are ioremap'ed early should use in_XX/out_XX functions
-        * instead of the PCI ones and thus not suffer from the slowdown.
-        *
-        * Also note that currently, the workaround will not work for areas
-        * that are not mapped with PTEs (bolted in the hash table). This
-        * is the case for ioremaps done very early at boot (before
-        * mem_init_done) and includes the mapping of the ISA IO space.
-        *
-        * Fortunately, none of the affected devices is expected to do DMA
-        * and thus there should be no problem in practice.
-        *
-        * In order to improve performances, we only do the PTE search for
-        * addresses falling in the PHB IO space area. That means it will
-        * not work for hotplug'ed PHBs but those don't exist with Spider.
-        */
-       if (token && token <= spider_pci_count)
-               bus = &spider_pci_busses[token - 1];
+       if (token && token <= iowa_bus_count)
+               bus = &iowa_busses[token - 1];
        else {
                unsigned long vaddr, paddr;
                pte_t *ptep;
 
-               /* Fixup physical address */
                vaddr = (unsigned long)PCI_FIX_ADDR(addr);
+               if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END)
+                       return NULL;
 
-               /* Check if it's in allowed range for  PIO */
-               if (vaddr < PHB_IO_BASE || vaddr > PHB_IO_END)
-                       return;
-
-               /* Try to find a PTE. If not, clear the paddr, we'll do
-                * a vaddr only lookup (PIO only)
-                */
                ptep = find_linux_pte(init_mm.pgd, vaddr);
                if (ptep == NULL)
                        paddr = 0;
                else
                        paddr = pte_pfn(*ptep) << PAGE_SHIFT;
+               bus = iowa_pci_find(vaddr, paddr);
 
-               bus = spider_pci_find(vaddr, paddr);
                if (bus == NULL)
-                       return;
+                       return NULL;
        }
 
-       /* Now do the workaround
-        */
-       (void)in_be32(bus->regs + SPIDER_PCI_DUMMY_READ);
+       return bus;
 }
 
-static u8 spider_readb(const volatile void __iomem *addr)
+struct iowa_bus *iowa_pio_find_bus(unsigned long port)
 {
-       u8 val = __do_readb(addr);
-       spider_io_flush(addr);
-       return val;
+       unsigned long vaddr = (unsigned long)pci_io_base + port;
+       return iowa_pci_find(vaddr, 0);
 }
 
-static u16 spider_readw(const volatile void __iomem *addr)
-{
-       u16 val = __do_readw(addr);
-       spider_io_flush(addr);
-       return val;
-}
 
-static u32 spider_readl(const volatile void __iomem *addr)
-{
-       u32 val = __do_readl(addr);
-       spider_io_flush(addr);
-       return val;
+#define DEF_PCI_AC_RET(name, ret, at, al, space, aa)           \
+static ret iowa_##name at                                      \
+{                                                              \
+       struct iowa_bus *bus;                                   \
+       bus = iowa_##space##_find_bus(aa);                      \
+       if (bus && bus->ops && bus->ops->name)                  \
+               return bus->ops->name al;                       \
+       return __do_##name al;                                  \
 }
 
-static u64 spider_readq(const volatile void __iomem *addr)
-{
-       u64 val = __do_readq(addr);
-       spider_io_flush(addr);
-       return val;
+#define DEF_PCI_AC_NORET(name, at, al, space, aa)              \
+static void iowa_##name at                                     \
+{                                                              \
+       struct iowa_bus *bus;                                   \
+       bus = iowa_##space##_find_bus(aa);                      \
+       if (bus && bus->ops && bus->ops->name) {                \
+               bus->ops->name al;                              \
+               return;                                         \
+       }                                                       \
+       __do_##name al;                                         \
 }
 
-static u16 spider_readw_be(const volatile void __iomem *addr)
-{
-       u16 val = __do_readw_be(addr);
-       spider_io_flush(addr);
-       return val;
-}
+#include <asm/io-defs.h>
 
-static u32 spider_readl_be(const volatile void __iomem *addr)
-{
-       u32 val = __do_readl_be(addr);
-       spider_io_flush(addr);
-       return val;
-}
+#undef DEF_PCI_AC_RET
+#undef DEF_PCI_AC_NORET
 
-static u64 spider_readq_be(const volatile void __iomem *addr)
-{
-       u64 val = __do_readq_be(addr);
-       spider_io_flush(addr);
-       return val;
-}
+static struct ppc_pci_io __initdata iowa_pci_io = {
 
-static void spider_readsb(const volatile void __iomem *addr, void *buf,
-                         unsigned long count)
-{
-       __do_readsb(addr, buf, count);
-       spider_io_flush(addr);
-}
+#define DEF_PCI_AC_RET(name, ret, at, al, space, aa)   .name = iowa_##name,
+#define DEF_PCI_AC_NORET(name, at, al, space, aa)      .name = iowa_##name,
 
-static void spider_readsw(const volatile void __iomem *addr, void *buf,
-                         unsigned long count)
-{
-       __do_readsw(addr, buf, count);
-       spider_io_flush(addr);
-}
+#include <asm/io-defs.h>
 
-static void spider_readsl(const volatile void __iomem *addr, void *buf,
-                         unsigned long count)
-{
-       __do_readsl(addr, buf, count);
-       spider_io_flush(addr);
-}
-
-static void spider_memcpy_fromio(void *dest, const volatile void __iomem *src,
-                                unsigned long n)
-{
-       __do_memcpy_fromio(dest, src, n);
-       spider_io_flush(src);
-}
+#undef DEF_PCI_AC_RET
+#undef DEF_PCI_AC_NORET
 
+};
 
-static void __iomem * spider_ioremap(unsigned long addr, unsigned long size,
-                                    unsigned long flags)
+static void __iomem *iowa_ioremap(unsigned long addr, unsigned long size,
+                                               unsigned long flags)
 {
-       struct spider_pci_bus *bus;
+       struct iowa_bus *bus;
        void __iomem *res = __ioremap(addr, size, flags);
        int busno;
 
-       pr_debug("spider_ioremap(0x%lx, 0x%lx, 0x%lx) -> 0x%p\n",
-                addr, size, flags, res);
-
-       bus = spider_pci_find(0, addr);
+       bus = iowa_pci_find(0, addr);
        if (bus != NULL) {
-               busno = bus - spider_pci_busses;
-               pr_debug(" found bus %d, setting token\n", busno);
+               busno = bus - iowa_busses;
                PCI_SET_ADDR_TOKEN(res, busno + 1);
        }
-       pr_debug(" result=0x%p\n", res);
-
        return res;
 }
 
-static void __init spider_pci_setup_chip(struct spider_pci_bus *bus)
-{
-#ifdef SPIDER_DISABLE_PREFETCH
-       u32 val = in_be32(bus->regs + SPIDER_PCI_VCI_CNTL_STAT);
-       pr_debug(" PVCI_Control_Status was 0x%08x\n", val);
-       out_be32(bus->regs + SPIDER_PCI_VCI_CNTL_STAT, val | 0x8);
-#endif
-
-       /* Configure the dummy address for the workaround */
-       out_be32(bus->regs + SPIDER_PCI_DUMMY_READ_BASE, 0x80000000);
-}
-
-static void __init spider_pci_add_one(struct pci_controller *phb)
+/* Regist new bus to support workaround */
+void __init iowa_register_bus(struct pci_controller *phb,
+                       struct ppc_pci_io *ops,
+                       int (*initfunc)(struct iowa_bus *, void *), void *data)
 {
-       struct spider_pci_bus *bus = &spider_pci_busses[spider_pci_count];
+       struct iowa_bus *bus;
        struct device_node *np = phb->dn;
-       struct resource rsrc;
-       void __iomem *regs;
 
-       if (spider_pci_count >= MAX_SPIDERS) {
-               printk(KERN_ERR "Too many spider bridges, workarounds"
-                      " disabled for %s\n", np->full_name);
+       if (iowa_bus_count >= IOWA_MAX_BUS) {
+               pr_err("IOWA:Too many pci bridges, "
+                      "workarounds disabled for %s\n", np->full_name);
                return;
        }
 
-       /* Get the registers for the beast */
-       if (of_address_to_resource(np, 0, &rsrc)) {
-               printk(KERN_ERR "Failed to get registers for spider %s"
-                      " workarounds disabled\n", np->full_name);
-               return;
-       }
+       bus = &iowa_busses[iowa_bus_count];
+       bus->phb = phb;
+       bus->ops = ops;
 
-       /* Mask out some useless bits in there to get to the base of the
-        * spider chip
-        */
-       rsrc.start &= ~0xfffffffful;
-
-       /* Map them */
-       regs = ioremap(rsrc.start + SPIDER_PCI_REG_BASE, 0x1000);
-       if (regs == NULL) {
-               printk(KERN_ERR "Failed to map registers for spider %s"
-                      " workarounds disabled\n", np->full_name);
-               return;
-       }
-
-       spider_pci_count++;
-
-       /* We assume spiders only have one MMIO resource */
-       bus->mmio_start = phb->mem_resources[0].start;
-       bus->mmio_end = phb->mem_resources[0].end + 1;
-
-       bus->pio_vstart = (unsigned long)phb->io_base_virt;
-       bus->pio_vend = bus->pio_vstart + phb->pci_io_size;
-
-       bus->regs = regs;
-
-       printk(KERN_INFO "PCI: Spider MMIO workaround for %s\n",np->full_name);
+       if (initfunc)
+               if ((*initfunc)(bus, data))
+                       return;
 
-       pr_debug(" mmio (P) = 0x%016lx..0x%016lx\n",
-                bus->mmio_start, bus->mmio_end);
-       pr_debug("  pio (V) = 0x%016lx..0x%016lx\n",
-                bus->pio_vstart, bus->pio_vend);
-       pr_debug(" regs (P) = 0x%016lx (V) = 0x%p\n",
-                rsrc.start + SPIDER_PCI_REG_BASE, bus->regs);
+       iowa_bus_count++;
 
-       spider_pci_setup_chip(bus);
+       pr_debug("IOWA:[%d]Add bus, %s.\n", iowa_bus_count-1, np->full_name);
 }
 
-static struct ppc_pci_io __initdata spider_pci_io = {
-       .readb = spider_readb,
-       .readw = spider_readw,
-       .readl = spider_readl,
-       .readq = spider_readq,
-       .readw_be = spider_readw_be,
-       .readl_be = spider_readl_be,
-       .readq_be = spider_readq_be,
-       .readsb = spider_readsb,
-       .readsw = spider_readsw,
-       .readsl = spider_readsl,
-       .memcpy_fromio = spider_memcpy_fromio,
-};
-
-static int __init spider_pci_workaround_init(void)
+/* enable IO workaround */
+void __init io_workaround_init(void)
 {
-       struct pci_controller *phb;
-
-       /* Find spider bridges. We assume they have been all probed
-        * in setup_arch(). If that was to change, we would need to
-        * update this code to cope with dynamically added busses
-        */
-       list_for_each_entry(phb, &hose_list, list_node) {
-               struct device_node *np = phb->dn;
-               const char *model = of_get_property(np, "model", NULL);
-
-               /* If no model property or name isn't exactly "pci", skip */
-               if (model == NULL || strcmp(np->name, "pci"))
-                       continue;
-               /* If model is not "Spider", skip */
-               if (strcmp(model, "Spider"))
-                       continue;
-               spider_pci_add_one(phb);
-       }
-
-       /* No Spider PCI found, exit */
-       if (spider_pci_count == 0)
-               return 0;
+       static int io_workaround_inited;
 
-       /* Setup IO callbacks. We only setup MMIO reads. PIO reads will
-        * fallback to MMIO reads (though without a token, thus slower)
-        */
-       ppc_pci_io = spider_pci_io;
-
-       /* Setup ioremap callback */
-       ppc_md.ioremap = spider_ioremap;
-
-       return 0;
+       if (io_workaround_inited)
+               return;
+       ppc_pci_io = iowa_pci_io;
+       ppc_md.ioremap = iowa_ioremap;
+       io_workaround_inited = 1;
 }
-machine_arch_initcall(cell, spider_pci_workaround_init);
diff --git a/arch/powerpc/platforms/cell/io-workarounds.h b/arch/powerpc/platforms/cell/io-workarounds.h
new file mode 100644 (file)
index 0000000..79d8ed3
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Support PCI IO workaround
+ *
+ * (C) Copyright 2007-2008 TOSHIBA 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _IO_WORKAROUNDS_H
+#define _IO_WORKAROUNDS_H
+
+#include <linux/io.h>
+#include <asm/pci-bridge.h>
+
+/* Bus info */
+struct iowa_bus {
+       struct pci_controller *phb;
+       struct ppc_pci_io *ops;
+       void   *private;
+};
+
+void __init io_workaround_init(void);
+void __init iowa_register_bus(struct pci_controller *, struct ppc_pci_io *,
+                             int (*)(struct iowa_bus *, void *), void *);
+struct iowa_bus *iowa_mem_find_bus(const PCI_IO_ADDR);
+struct iowa_bus *iowa_pio_find_bus(unsigned long);
+
+extern struct ppc_pci_io spiderpci_ops;
+extern int spiderpci_iowa_init(struct iowa_bus *, void *);
+
+#define SPIDER_PCI_REG_BASE            0xd000
+#define SPIDER_PCI_REG_SIZE            0x1000
+#define SPIDER_PCI_VCI_CNTL_STAT       0x0110
+#define SPIDER_PCI_DUMMY_READ          0x0810
+#define SPIDER_PCI_DUMMY_READ_BASE     0x0814
+
+#endif /* _IO_WORKAROUNDS_H */
index 5c531e8f9f6faed24276cc6405d4deebfd0e3509..ab721b50fbba15129e3037e10532e8ca47b6a2e8 100644 (file)
@@ -57,6 +57,7 @@
 #include "interrupt.h"
 #include "pervasive.h"
 #include "ras.h"
+#include "io-workarounds.h"
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -117,13 +118,50 @@ static void cell_fixup_pcie_rootcomplex(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, cell_fixup_pcie_rootcomplex);
 
+static int __devinit cell_setup_phb(struct pci_controller *phb)
+{
+       const char *model;
+       struct device_node *np;
+
+       int rc = rtas_setup_phb(phb);
+       if (rc)
+               return rc;
+
+       np = phb->dn;
+       model = of_get_property(np, "model", NULL);
+       if (model == NULL || strcmp(np->name, "pci"))
+               return 0;
+
+       /* Setup workarounds for spider */
+       if (strcmp(model, "Spider"))
+               return 0;
+
+       iowa_register_bus(phb, &spiderpci_ops, &spiderpci_iowa_init,
+                                 (void *)SPIDER_PCI_REG_BASE);
+       io_workaround_init();
+
+       return 0;
+}
+
 static int __init cell_publish_devices(void)
 {
+       struct device_node *root = of_find_node_by_path("/");
+       struct device_node *np;
        int node;
 
        /* Publish OF platform devices for southbridge IOs */
        of_platform_bus_probe(NULL, NULL, NULL);
 
+       /* On spider based blades, we need to manually create the OF
+        * platform devices for the PCI host bridges
+        */
+       for_each_child_of_node(root, np) {
+               if (np->type == NULL || (strcmp(np->type, "pci") != 0 &&
+                                        strcmp(np->type, "pciex") != 0))
+                       continue;
+               of_platform_device_create(np, NULL, NULL);
+       }
+
        /* There is no device for the MIC memory controller, thus we create
         * a platform device for it to attach the EDAC driver to.
         */
@@ -132,6 +170,7 @@ static int __init cell_publish_devices(void)
                        continue;
                platform_device_register_simple("cbe-mic", node, NULL, 0);
        }
+
        return 0;
 }
 machine_subsys_initcall(cell, cell_publish_devices);
@@ -213,7 +252,7 @@ static void __init cell_setup_arch(void)
 
        /* Find and initialize PCI host bridges */
        init_pci_config_tokens();
-       find_and_init_phbs();
+
        cbe_pervasive_init();
 #ifdef CONFIG_DUMMY_CONSOLE
        conswitchp = &dummy_con;
@@ -249,7 +288,7 @@ define_machine(cell) {
        .calibrate_decr         = generic_calibrate_decr,
        .progress               = cell_progress,
        .init_IRQ               = cell_init_irq,
-       .pci_setup_phb          = rtas_setup_phb,
+       .pci_setup_phb          = cell_setup_phb,
 #ifdef CONFIG_KEXEC
        .machine_kexec          = default_machine_kexec,
        .machine_kexec_prepare  = default_machine_kexec_prepare,
diff --git a/arch/powerpc/platforms/cell/spider-pci.c b/arch/powerpc/platforms/cell/spider-pci.c
new file mode 100644 (file)
index 0000000..418b605
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * IO workarounds for PCI on Celleb/Cell platform
+ *
+ * (C) Copyright 2006-2007 TOSHIBA 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+
+#include <asm/ppc-pci.h>
+#include <asm/pci-bridge.h>
+
+#include "io-workarounds.h"
+
+#define SPIDER_PCI_DISABLE_PREFETCH
+
+struct spiderpci_iowa_private {
+       void __iomem *regs;
+};
+
+static void spiderpci_io_flush(struct iowa_bus *bus)
+{
+       struct spiderpci_iowa_private *priv;
+       u32 val;
+
+       priv = bus->private;
+       val = in_be32(priv->regs + SPIDER_PCI_DUMMY_READ);
+       iosync();
+}
+
+#define SPIDER_PCI_MMIO_READ(name, ret)                                        \
+static ret spiderpci_##name(const PCI_IO_ADDR addr)                    \
+{                                                                      \
+       ret val = __do_##name(addr);                                    \
+       spiderpci_io_flush(iowa_mem_find_bus(addr));                    \
+       return val;                                                     \
+}
+
+#define SPIDER_PCI_MMIO_READ_STR(name)                                 \
+static void spiderpci_##name(const PCI_IO_ADDR addr, void *buf,        \
+                            unsigned long count)                       \
+{                                                                      \
+       __do_##name(addr, buf, count);                                  \
+       spiderpci_io_flush(iowa_mem_find_bus(addr));                    \
+}
+
+SPIDER_PCI_MMIO_READ(readb, u8)
+SPIDER_PCI_MMIO_READ(readw, u16)
+SPIDER_PCI_MMIO_READ(readl, u32)
+SPIDER_PCI_MMIO_READ(readq, u64)
+SPIDER_PCI_MMIO_READ(readw_be, u16)
+SPIDER_PCI_MMIO_READ(readl_be, u32)
+SPIDER_PCI_MMIO_READ(readq_be, u64)
+SPIDER_PCI_MMIO_READ_STR(readsb)
+SPIDER_PCI_MMIO_READ_STR(readsw)
+SPIDER_PCI_MMIO_READ_STR(readsl)
+
+static void spiderpci_memcpy_fromio(void *dest, const PCI_IO_ADDR src,
+                                   unsigned long n)
+{
+       __do_memcpy_fromio(dest, src, n);
+       spiderpci_io_flush(iowa_mem_find_bus(src));
+}
+
+static int __init spiderpci_pci_setup_chip(struct pci_controller *phb,
+                                          void __iomem *regs)
+{
+       void *dummy_page_va;
+       dma_addr_t dummy_page_da;
+
+#ifdef SPIDER_PCI_DISABLE_PREFETCH
+       u32 val = in_be32(regs + SPIDER_PCI_VCI_CNTL_STAT);
+       pr_debug("SPIDER_IOWA:PVCI_Control_Status was 0x%08x\n", val);
+       out_be32(regs + SPIDER_PCI_VCI_CNTL_STAT, val | 0x8);
+#endif /* SPIDER_PCI_DISABLE_PREFETCH */
+
+       /* setup dummy read */
+       /*
+        * On CellBlade, we can't know that which XDR memory is used by
+        * kmalloc() to allocate dummy_page_va.
+        * In order to imporve the performance, the XDR which is used to
+        * allocate dummy_page_va is the nearest the spider-pci.
+        * We have to select the CBE which is the nearest the spider-pci
+        * to allocate memory from the best XDR, but I don't know that
+        * how to do.
+        *
+        * Celleb does not have this problem, because it has only one XDR.
+        */
+       dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!dummy_page_va) {
+               pr_err("SPIDERPCI-IOWA:Alloc dummy_page_va failed.\n");
+               return -1;
+       }
+
+       dummy_page_da = dma_map_single(phb->parent, dummy_page_va,
+                                      PAGE_SIZE, DMA_FROM_DEVICE);
+       if (dma_mapping_error(dummy_page_da)) {
+               pr_err("SPIDER-IOWA:Map dummy page filed.\n");
+               kfree(dummy_page_va);
+               return -1;
+       }
+
+       out_be32(regs + SPIDER_PCI_DUMMY_READ_BASE, dummy_page_da);
+
+       return 0;
+}
+
+int __init spiderpci_iowa_init(struct iowa_bus *bus, void *data)
+{
+       void __iomem *regs = NULL;
+       struct spiderpci_iowa_private *priv;
+       struct device_node *np = bus->phb->dn;
+       struct resource r;
+       unsigned long offset = (unsigned long)data;
+
+       pr_debug("SPIDERPCI-IOWA:Bus initialize for spider(%s)\n",
+                np->full_name);
+
+       priv = kzalloc(sizeof(struct spiderpci_iowa_private), GFP_KERNEL);
+       if (!priv) {
+               pr_err("SPIDERPCI-IOWA:"
+                      "Can't allocate struct spiderpci_iowa_private");
+               return -1;
+       }
+
+       if (of_address_to_resource(np, 0, &r)) {
+               pr_err("SPIDERPCI-IOWA:Can't get resource.\n");
+               goto error;
+       }
+
+       regs = ioremap(r.start + offset, SPIDER_PCI_REG_SIZE);
+       if (!regs) {
+               pr_err("SPIDERPCI-IOWA:ioremap failed.\n");
+               goto error;
+       }
+       priv->regs = regs;
+       bus->private = priv;
+
+       if (spiderpci_pci_setup_chip(bus->phb, regs))
+               goto error;
+
+       return 0;
+
+error:
+       kfree(priv);
+       bus->private = NULL;
+
+       if (regs)
+               iounmap(regs);
+
+       return -1;
+}
+
+struct ppc_pci_io spiderpci_ops = {
+       .readb = spiderpci_readb,
+       .readw = spiderpci_readw,
+       .readl = spiderpci_readl,
+       .readq = spiderpci_readq,
+       .readw_be = spiderpci_readw_be,
+       .readl_be = spiderpci_readl_be,
+       .readq_be = spiderpci_readq_be,
+       .readsb = spiderpci_readsb,
+       .readsw = spiderpci_readsw,
+       .readsl = spiderpci_readsl,
+       .memcpy_fromio = spiderpci_memcpy_fromio,
+};
+
diff --git a/arch/powerpc/platforms/celleb/Kconfig b/arch/powerpc/platforms/celleb/Kconfig
deleted file mode 100644 (file)
index 372891e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-config PPC_CELLEB
-       bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
-       depends on PPC_MULTIPLATFORM && PPC64
-       select PPC_CELL
-       select PPC_CELL_NATIVE
-       select PPC_RTAS
-       select PPC_INDIRECT_IO
-       select PPC_OF_PLATFORM_PCI
-       select HAS_TXX9_SERIAL
-       select PPC_UDBG_BEAT
-       select USB_OHCI_BIG_ENDIAN_MMIO
-       select USB_EHCI_BIG_ENDIAN_MMIO
diff --git a/arch/powerpc/platforms/celleb/Makefile b/arch/powerpc/platforms/celleb/Makefile
deleted file mode 100644 (file)
index 889d43f..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-obj-y                          += interrupt.o iommu.o setup.o \
-                                  htab.o beat.o hvCall.o pci.o \
-                                  scc_epci.o scc_uhc.o \
-                                  io-workarounds.o
-
-obj-$(CONFIG_SMP)              += smp.o
-obj-$(CONFIG_PPC_UDBG_BEAT)    += udbg_beat.o
-obj-$(CONFIG_SERIAL_TXX9)      += scc_sio.o
-obj-$(CONFIG_SPU_BASE)         += spu_priv1.o
diff --git a/arch/powerpc/platforms/celleb/io-workarounds.c b/arch/powerpc/platforms/celleb/io-workarounds.c
deleted file mode 100644 (file)
index 423339b..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Support for Celleb io workarounds
- *
- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
- *
- * This file is based to arch/powerpc/platform/cell/io-workarounds.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; 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.
- */
-
-#undef DEBUG
-
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/irq.h>
-
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <asm/ppc-pci.h>
-
-#include "pci.h"
-
-#define MAX_CELLEB_PCI_BUS     4
-
-void *celleb_dummy_page_va;
-
-static struct celleb_pci_bus {
-       struct pci_controller *phb;
-       void (*dummy_read)(struct pci_controller *);
-} celleb_pci_busses[MAX_CELLEB_PCI_BUS];
-
-static int celleb_pci_count = 0;
-
-static struct celleb_pci_bus *celleb_pci_find(unsigned long vaddr,
-                                             unsigned long paddr)
-{
-       int i, j;
-       struct resource *res;
-
-       for (i = 0; i < celleb_pci_count; i++) {
-               struct celleb_pci_bus *bus = &celleb_pci_busses[i];
-               struct pci_controller *phb = bus->phb;
-               if (paddr)
-                       for (j = 0; j < 3; j++) {
-                               res = &phb->mem_resources[j];
-                               if (paddr >= res->start && paddr <= res->end)
-                                       return bus;
-                       }
-               res = &phb->io_resource;
-               if (vaddr && vaddr >= res->start && vaddr <= res->end)
-                       return bus;
-       }
-       return NULL;
-}
-
-static void celleb_io_flush(const PCI_IO_ADDR addr)
-{
-       struct celleb_pci_bus *bus;
-       int token;
-
-       token = PCI_GET_ADDR_TOKEN(addr);
-
-       if (token && token <= celleb_pci_count)
-               bus = &celleb_pci_busses[token - 1];
-       else {
-               unsigned long vaddr, paddr;
-               pte_t *ptep;
-
-               vaddr = (unsigned long)PCI_FIX_ADDR(addr);
-               if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END)
-                       return;
-
-               ptep = find_linux_pte(init_mm.pgd, vaddr);
-               if (ptep == NULL)
-                       paddr = 0;
-               else
-                       paddr = pte_pfn(*ptep) << PAGE_SHIFT;
-               bus = celleb_pci_find(vaddr, paddr);
-
-               if (bus == NULL)
-                       return;
-       }
-
-       if (bus->dummy_read)
-               bus->dummy_read(bus->phb);
-}
-
-static u8 celleb_readb(const PCI_IO_ADDR addr)
-{
-       u8 val;
-       val = __do_readb(addr);
-       celleb_io_flush(addr);
-       return val;
-}
-
-static u16 celleb_readw(const PCI_IO_ADDR addr)
-{
-       u16 val;
-       val = __do_readw(addr);
-       celleb_io_flush(addr);
-       return val;
-}
-
-static u32 celleb_readl(const PCI_IO_ADDR addr)
-{
-       u32 val;
-       val = __do_readl(addr);
-       celleb_io_flush(addr);
-       return val;
-}
-
-static u64 celleb_readq(const PCI_IO_ADDR addr)
-{
-       u64 val;
-       val = __do_readq(addr);
-       celleb_io_flush(addr);
-       return val;
-}
-
-static u16 celleb_readw_be(const PCI_IO_ADDR addr)
-{
-       u16 val;
-       val = __do_readw_be(addr);
-       celleb_io_flush(addr);
-       return val;
-}
-
-static u32 celleb_readl_be(const PCI_IO_ADDR addr)
-{
-       u32 val;
-       val = __do_readl_be(addr);
-       celleb_io_flush(addr);
-       return val;
-}
-
-static u64 celleb_readq_be(const PCI_IO_ADDR addr)
-{
-       u64 val;
-       val = __do_readq_be(addr);
-       celleb_io_flush(addr);
-       return val;
-}
-
-static void celleb_readsb(const PCI_IO_ADDR addr,
-                         void *buf, unsigned long count)
-{
-       __do_readsb(addr, buf, count);
-       celleb_io_flush(addr);
-}
-
-static void celleb_readsw(const PCI_IO_ADDR addr,
-                         void *buf, unsigned long count)
-{
-       __do_readsw(addr, buf, count);
-       celleb_io_flush(addr);
-}
-
-static void celleb_readsl(const PCI_IO_ADDR addr,
-                         void *buf, unsigned long count)
-{
-       __do_readsl(addr, buf, count);
-       celleb_io_flush(addr);
-}
-
-static void celleb_memcpy_fromio(void *dest,
-                                const PCI_IO_ADDR src,
-                                unsigned long n)
-{
-       __do_memcpy_fromio(dest, src, n);
-       celleb_io_flush(src);
-}
-
-static void __iomem *celleb_ioremap(unsigned long addr,
-                                    unsigned long size,
-                                    unsigned long flags)
-{
-       struct celleb_pci_bus *bus;
-       void __iomem *res = __ioremap(addr, size, flags);
-       int busno;
-
-       bus = celleb_pci_find(0, addr);
-       if (bus != NULL) {
-               busno = bus - celleb_pci_busses;
-               PCI_SET_ADDR_TOKEN(res, busno + 1);
-       }
-       return res;
-}
-
-static void celleb_iounmap(volatile void __iomem *addr)
-{
-       return __iounmap(PCI_FIX_ADDR(addr));
-}
-
-static struct ppc_pci_io celleb_pci_io __initdata = {
-       .readb = celleb_readb,
-       .readw = celleb_readw,
-       .readl = celleb_readl,
-       .readq = celleb_readq,
-       .readw_be = celleb_readw_be,
-       .readl_be = celleb_readl_be,
-       .readq_be = celleb_readq_be,
-       .readsb = celleb_readsb,
-       .readsw = celleb_readsw,
-       .readsl = celleb_readsl,
-       .memcpy_fromio = celleb_memcpy_fromio,
-};
-
-void __init celleb_pci_add_one(struct pci_controller *phb,
-                              void (*dummy_read)(struct pci_controller *))
-{
-       struct celleb_pci_bus *bus = &celleb_pci_busses[celleb_pci_count];
-       struct device_node *np = phb->dn;
-
-       if (celleb_pci_count >= MAX_CELLEB_PCI_BUS) {
-               printk(KERN_ERR "Too many pci bridges, workarounds"
-                      " disabled for %s\n", np->full_name);
-               return;
-       }
-
-       celleb_pci_count++;
-
-       bus->phb = phb;
-       bus->dummy_read = dummy_read;
-}
-
-static struct of_device_id celleb_pci_workaround_match[] __initdata = {
-       {
-               .name = "pci-pseudo",
-               .data = fake_pci_workaround_init,
-       }, {
-               .name = "epci",
-               .data = epci_workaround_init,
-       }, {
-       },
-};
-
-int __init celleb_pci_workaround_init(void)
-{
-       struct pci_controller *phb;
-       struct device_node *node;
-       const struct  of_device_id *match;
-       void (*init_func)(struct pci_controller *);
-
-       celleb_dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL);
-       if (!celleb_dummy_page_va) {
-               printk(KERN_ERR "Celleb: dummy read disabled. "
-                       "Alloc celleb_dummy_page_va failed\n");
-               return 1;
-       }
-
-       list_for_each_entry(phb, &hose_list, list_node) {
-               node = phb->dn;
-               match = of_match_node(celleb_pci_workaround_match, node);
-
-               if (match) {
-                       init_func = match->data;
-                       (*init_func)(phb);
-               }
-       }
-
-       ppc_pci_io = celleb_pci_io;
-       ppc_md.ioremap = celleb_ioremap;
-       ppc_md.iounmap = celleb_iounmap;
-
-       return 0;
-}
index c775cd4b3d6eee44f9b5dc44ed80a309e80ed5f7..8ff330d026ca686c462b30e8085ae7d7fd701340 100644 (file)
@@ -59,8 +59,33 @@ system_reset_iSeries:
        andc    r4,r4,r5
        mtspr   SPRN_CTRLT,r4
 
+/* Spin on __secondary_hold_spinloop until it is updated by the boot cpu. */
+/* In the UP case we'll yeild() later, and we will not access the paca anyway */
+#ifdef CONFIG_SMP
 1:
        HMT_LOW
+       LOAD_REG_IMMEDIATE(r23, __secondary_hold_spinloop)
+       ld      r23,0(r23)
+       sync
+       LOAD_REG_IMMEDIATE(r3,current_set)
+       sldi    r28,r24,3               /* get current_set[cpu#] */
+       ldx     r3,r3,r28
+       addi    r1,r3,THREAD_SIZE
+       subi    r1,r1,STACK_FRAME_OVERHEAD
+
+       cmpwi   0,r23,0                 /* Keep poking the Hypervisor until */
+       bne     2f                      /* we're released */
+       /* Let the Hypervisor know we are alive */
+       /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
+       lis     r3,0x8002
+       rldicr  r3,r3,32,15             /* r0 = (r3 << 32) & 0xffff000000000000 */
+       li      r0,-1                   /* r0=-1 indicates a Hypervisor call */
+       sc                              /* Invoke the hypervisor via a system call */
+       b       1b
+#endif
+
+2:
+       HMT_LOW
 #ifdef CONFIG_SMP
        lbz     r23,PACAPROCSTART(r13)  /* Test if this processor
                                         * should start */
@@ -91,7 +116,7 @@ iSeries_secondary_smp_loop:
        li      r0,-1                   /* r0=-1 indicates a Hypervisor call */
        sc                              /* Invoke the hypervisor via a system call */
        mfspr   r13,SPRN_SPRG3          /* Put r13 back ???? */
-       b       1b                      /* If SMP not configured, secondaries
+       b       2b                      /* If SMP not configured, secondaries
                                         * loop forever */
 
 /***  ISeries-LPAR interrupt handlers ***/
index c73379ec9141038c5a68e14f0233a64c9fb2601f..1d201782d4e5809190fcf4bb9ff64df5e9074195 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/syscalls.h>
 #include <linux/ctype.h>
 #include <linux/lmb.h>
+#include <linux/of.h>
 
 #include <asm/prom.h>
 
index 306a9d07491de3ea786695ba205472c1155589d0..07fe5b69b9e25f8c1c930c18a28a29920e525c89 100644 (file)
@@ -34,3 +34,8 @@ config LPARCFG
        help
        Provide system capacity information via human readable
        <key word>=<value> pairs through a /proc/ppc64/lparcfg interface.
+
+config PPC_PSERIES_DEBUG
+       depends on PPC_PSERIES && PPC_EARLY_DEBUG
+       bool "Enable extra debug logging in platforms/pseries"
+       default y
index bdae04bb7a0157048b24f64ff3f1f05a883976e6..bd2593ed28dd2f3c002a617b363707295cd2f2b6 100644 (file)
@@ -2,6 +2,10 @@ ifeq ($(CONFIG_PPC64),y)
 EXTRA_CFLAGS           += -mno-minimal-toc
 endif
 
+ifeq ($(CONFIG_PPC_PSERIES_DEBUG),y)
+EXTRA_CFLAGS           += -DDEBUG
+endif
+
 obj-y                  := lpar.o hvCall.o nvram.o reconfig.o \
                           setup.o iommu.o ras.o rtasd.o \
                           firmware.o power.o
index 550b2f7d2cc1ee8ed59b5a91f0a334f3402be80e..a3fd56b186e6063284306e37339a9a7cc7f8349d 100644 (file)
@@ -39,7 +39,6 @@
 #include <asm/ppc-pci.h>
 #include <asm/rtas.h>
 
-#undef DEBUG
 
 /** Overview:
  *  EEH, or "Extended Error Handling" is a PCI bridge technology for
index 1e83fcd0df312a3a9e41d146566ade3143eafdea..ce37040af870856271deecd0de2c0c42af32457e 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/pci-bridge.h>
 #include <asm/ppc-pci.h>
 
-#undef DEBUG
 
 /**
  * The pci address cache subsystem.  This subsystem places
index b765b7c77b65ddacdeb806ce10904d6e5697ea42..9d3a40f459747c2ab8077a21a23cb794893f9652 100644 (file)
  * 2 of the License, or (at your option) any later version.
  */
 
-#undef DEBUG
 
 #include <asm/firmware.h>
 #include <asm/prom.h>
 #include <asm/udbg.h>
 
-#ifdef DEBUG
-#define DBG(fmt...) udbg_printf(fmt)
-#else
-#define DBG(fmt...)
-#endif
 
 typedef struct {
     unsigned long val;
@@ -72,7 +66,7 @@ void __init fw_feature_init(const char *hypertas, unsigned long len)
        const char *s;
        int i;
 
-       DBG(" -> fw_feature_init()\n");
+       pr_debug(" -> fw_feature_init()\n");
 
        for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) {
                for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) {
@@ -88,5 +82,5 @@ void __init fw_feature_init(const char *hypertas, unsigned long len)
                }
        }
 
-       DBG(" <- fw_feature_init()\n");
+       pr_debug(" <- fw_feature_init()\n");
 }
index a65c763082010c8c1ff7d6fd0a8b458974fef085..176f1f39d2d5c2f25416a651c58f2d82e267d19a 100644 (file)
@@ -47,7 +47,6 @@
 
 #include "plpar_wrappers.h"
 
-#define DBG(fmt...)
 
 static void tce_build_pSeries(struct iommu_table *tbl, long index,
                              long npages, unsigned long uaddr,
@@ -322,7 +321,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
 
        dn = pci_bus_to_OF_node(bus);
 
-       DBG("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name);
+       pr_debug("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name);
 
        if (bus->self) {
                /* This is not a root bus, any setup will be done for the
@@ -347,7 +346,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
        for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling)
                children++;
 
-       DBG("Children: %d\n", children);
+       pr_debug("Children: %d\n", children);
 
        /* Calculate amount of DMA window per slot. Each window must be
         * a power of two (due to pci_alloc_consistent requirements).
@@ -361,8 +360,8 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
 
                while (pci->phb->dma_window_size * children > 0x80000000ul)
                        pci->phb->dma_window_size >>= 1;
-               DBG("No ISA/IDE, window size is 0x%lx\n",
-                       pci->phb->dma_window_size);
+               pr_debug("No ISA/IDE, window size is 0x%lx\n",
+                        pci->phb->dma_window_size);
                pci->phb->dma_window_base_cur = 0;
 
                return;
@@ -387,8 +386,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
        while (pci->phb->dma_window_size * children > 0x70000000ul)
                pci->phb->dma_window_size >>= 1;
 
-       DBG("ISA/IDE, window size is 0x%lx\n", pci->phb->dma_window_size);
-
+       pr_debug("ISA/IDE, window size is 0x%lx\n", pci->phb->dma_window_size);
 }
 
 
@@ -401,7 +399,8 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
 
        dn = pci_bus_to_OF_node(bus);
 
-       DBG("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n", dn->full_name);
+       pr_debug("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n",
+                dn->full_name);
 
        /* Find nearest ibm,dma-window, walking up the device tree */
        for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
@@ -411,14 +410,14 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
        }
 
        if (dma_window == NULL) {
-               DBG("  no ibm,dma-window property !\n");
+               pr_debug("  no ibm,dma-window property !\n");
                return;
        }
 
        ppci = PCI_DN(pdn);
 
-       DBG("  parent is %s, iommu_table: 0x%p\n",
-           pdn->full_name, ppci->iommu_table);
+       pr_debug("  parent is %s, iommu_table: 0x%p\n",
+                pdn->full_name, ppci->iommu_table);
 
        if (!ppci->iommu_table) {
                tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
@@ -426,7 +425,7 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
                iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window,
                        bus->number);
                ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node);
-               DBG("  created table: %p\n", ppci->iommu_table);
+               pr_debug("  created table: %p\n", ppci->iommu_table);
        }
 
        if (pdn != dn)
@@ -439,7 +438,7 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
        struct device_node *dn;
        struct iommu_table *tbl;
 
-       DBG("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev));
+       pr_debug("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev));
 
        dn = dev->dev.archdata.of_node;
 
@@ -450,7 +449,7 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
        if (!dev->bus->self) {
                struct pci_controller *phb = PCI_DN(dn)->phb;
 
-               DBG(" --> first child, no bridge. Allocating iommu table.\n");
+               pr_debug(" --> first child, no bridge. Allocating iommu table.\n");
                tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
                                   phb->node);
                iommu_table_setparms(phb, dn, tbl);
@@ -480,7 +479,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
        const void *dma_window = NULL;
        struct pci_dn *pci;
 
-       DBG("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev));
+       pr_debug("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev));
 
        /* dev setup for LPAR is a little tricky, since the device tree might
         * contain the dma-window properties per-device and not neccesarily
@@ -489,7 +488,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
         * already allocated.
         */
        dn = pci_device_to_OF_node(dev);
-       DBG("  node is %s\n", dn->full_name);
+       pr_debug("  node is %s\n", dn->full_name);
 
        for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
             pdn = pdn->parent) {
@@ -504,13 +503,13 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
                                 pci_name(dev), dn? dn->full_name : "<null>");
                return;
        }
-       DBG("  parent is %s\n", pdn->full_name);
+       pr_debug("  parent is %s\n", pdn->full_name);
 
        /* Check for parent == NULL so we don't try to setup the empty EADS
         * slots on POWER4 machines.
         */
        if (dma_window == NULL || pdn->parent == NULL) {
-               DBG("  no dma window for device, linking to parent\n");
+               pr_debug("  no dma window for device, linking to parent\n");
                dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table;
                return;
        }
@@ -522,9 +521,9 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
                iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window,
                        pci->phb->bus->number);
                pci->iommu_table = iommu_init_table(tbl, pci->phb->node);
-               DBG("  created table: %p\n", pci->iommu_table);
+               pr_debug("  created table: %p\n", pci->iommu_table);
        } else {
-               DBG("  found DMA window, table: %p\n", pci->iommu_table);
+               pr_debug("  found DMA window, table: %p\n", pci->iommu_table);
        }
 
        dev->dev.archdata.dma_data = pci->iommu_table;
index 9235c469449e06890e474c52af8fe11b21c96e2d..2cbaedb17f3ebc2396c23154153d4abf8c8badc1 100644 (file)
@@ -19,7 +19,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-#undef DEBUG_LOW
+/* Enables debugging of low-level hash table routines - careful! */
+#undef DEBUG
 
 #include <linux/kernel.h>
 #include <linux/dma-mapping.h>
 #include "plpar_wrappers.h"
 #include "pseries.h"
 
-#ifdef DEBUG_LOW
-#define DBG_LOW(fmt...) do { udbg_printf(fmt); } while(0)
-#else
-#define DBG_LOW(fmt...) do { } while(0)
-#endif
 
 /* in hvCall.S */
 EXPORT_SYMBOL(plpar_hcall);
@@ -196,6 +192,8 @@ void __init udbg_init_debug_lpar(void)
        udbg_putc = udbg_putcLP;
        udbg_getc = udbg_getcLP;
        udbg_getc_poll = udbg_getc_pollLP;
+
+       register_early_udbg_console();
 }
 
 /* returns 0 if couldn't find or use /chosen/stdout as console */
@@ -288,15 +286,15 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
        unsigned long hpte_v, hpte_r;
 
        if (!(vflags & HPTE_V_BOLTED))
-               DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
-                       "rflags=%lx, vflags=%lx, psize=%d)\n",
-               hpte_group, va, pa, rflags, vflags, psize);
+               pr_debug("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
+                        "rflags=%lx, vflags=%lx, psize=%d)\n",
+                        hpte_group, va, pa, rflags, vflags, psize);
 
        hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID;
        hpte_r = hpte_encode_r(pa, psize) | rflags;
 
        if (!(vflags & HPTE_V_BOLTED))
-               DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
+               pr_debug(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
 
        /* Now fill in the actual HPTE */
        /* Set CEC cookie to 0         */
@@ -313,7 +311,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
        lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot);
        if (unlikely(lpar_rc == H_PTEG_FULL)) {
                if (!(vflags & HPTE_V_BOLTED))
-                       DBG_LOW(" full\n");
+                       pr_debug(" full\n");
                return -1;
        }
 
@@ -324,11 +322,11 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
         */
        if (unlikely(lpar_rc != H_SUCCESS)) {
                if (!(vflags & HPTE_V_BOLTED))
-                       DBG_LOW(" lpar err %d\n", lpar_rc);
+                       pr_debug(" lpar err %lu\n", lpar_rc);
                return -2;
        }
        if (!(vflags & HPTE_V_BOLTED))
-               DBG_LOW(" -> slot: %d\n", slot & 7);
+               pr_debug(" -> slot: %lu\n", slot & 7);
 
        /* Because of iSeries, we have to pass down the secondary
         * bucket bit here as well
@@ -420,17 +418,17 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot,
 
        want_v = hpte_encode_avpn(va, psize, ssize);
 
-       DBG_LOW("    update: avpnv=%016lx, hash=%016lx, f=%x, psize: %d ... ",
-               want_v, slot, flags, psize);
+       pr_debug("    update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...",
+                want_v, slot, flags, psize);
 
        lpar_rc = plpar_pte_protect(flags, slot, want_v);
 
        if (lpar_rc == H_NOT_FOUND) {
-               DBG_LOW("not found !\n");
+               pr_debug("not found !\n");
                return -1;
        }
 
-       DBG_LOW("ok\n");
+       pr_debug("ok\n");
 
        BUG_ON(lpar_rc != H_SUCCESS);
 
@@ -505,8 +503,8 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
        unsigned long lpar_rc;
        unsigned long dummy1, dummy2;
 
-       DBG_LOW("    inval : slot=%lx, va=%016lx, psize: %d, local: %d",
-               slot, va, psize, local);
+       pr_debug("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
+                slot, va, psize, local);
 
        want_v = hpte_encode_avpn(va, psize, ssize);
        lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v, &dummy1, &dummy2);
index a1ab25c7082f1031343d492445c37ce3845580dd..2b548afd10031166166d77f58ae9939be0a6ae1a 100644 (file)
@@ -67,8 +67,6 @@ static int ras_check_exception_token;
 static irqreturn_t ras_epow_interrupt(int irq, void *dev_id);
 static irqreturn_t ras_error_interrupt(int irq, void *dev_id);
 
-/* #define DEBUG */
-
 
 static void request_ras_irqs(struct device_node *np,
                        irq_handler_t handler,
@@ -237,7 +235,7 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
                printk(KERN_EMERG "Error: Fatal hardware error <0x%lx 0x%x>\n",
                       *((unsigned long *)&ras_log_buf), status);
 
-#ifndef DEBUG
+#ifndef DEBUG_RTAS_POWER_OFF
                /* Don't actually power off when debugging so we can test
                 * without actually failing while injecting errors.
                 * Error data will not be logged to syslog.
index e3078ce41518aec0abb0579a5c2f9cb21315dd44..befadd4f9524880d197240836557369a5386a487 100644 (file)
 #include <asm/atomic.h>
 #include <asm/machdep.h>
 
-#if 0
-#define DEBUG(A...)    printk(KERN_ERR A)
-#else
-#define DEBUG(A...)
-#endif
 
 static DEFINE_SPINLOCK(rtasd_log_lock);
 
@@ -198,7 +193,7 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
        unsigned long s;
        int len = 0;
 
-       DEBUG("logging event\n");
+       pr_debug("rtasd: logging event\n");
        if (buf == NULL)
                return;
 
@@ -409,7 +404,8 @@ static int rtasd(void *unused)
        daemonize("rtasd");
 
        printk(KERN_DEBUG "RTAS daemon started\n");
-       DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate));
+       pr_debug("rtasd: will sleep for %d milliseconds\n",
+                (30000 / rtas_event_scan_rate));
 
        /* See if we have any error stored in NVRAM */
        memset(logdata, 0, rtas_error_log_max);
@@ -428,9 +424,9 @@ static int rtasd(void *unused)
        do_event_scan_all_cpus(1000);
 
        if (surveillance_timeout != -1) {
-               DEBUG("enabling surveillance\n");
+               pr_debug("rtasd: enabling surveillance\n");
                enable_surveillance(surveillance_timeout);
-               DEBUG("surveillance enabled\n");
+               pr_debug("rtasd: surveillance enabled\n");
        }
 
        /* Delay should be at least one second since some
index e5b0ea87016495743f6dac0856da16d277a8fc03..bec3803f0618ec9486a98668b39e7145f0c21b6f 100644 (file)
@@ -38,9 +38,7 @@
 #define SCANLOG_HWERROR -1
 #define SCANLOG_CONTINUE 1
 
-#define DEBUG(A...) do { if (scanlog_debug) printk(KERN_ERR "scanlog: " A); } while (0)
 
-static int scanlog_debug;
 static unsigned int ibm_scan_log_dump;                 /* RTAS token */
 static struct proc_dir_entry *proc_ppc64_scan_log_dump;        /* The proc file */
 
@@ -86,14 +84,14 @@ static ssize_t scanlog_read(struct file *file, char __user *buf,
                memcpy(data, rtas_data_buf, RTAS_DATA_BUF_SIZE);
                spin_unlock(&rtas_data_buf_lock);
 
-               DEBUG("status=%d, data[0]=%x, data[1]=%x, data[2]=%x\n",
-                     status, data[0], data[1], data[2]);
+               pr_debug("scanlog: status=%d, data[0]=%x, data[1]=%x, " \
+                        "data[2]=%x\n", status, data[0], data[1], data[2]);
                switch (status) {
                    case SCANLOG_COMPLETE:
-                       DEBUG("hit eof\n");
+                       pr_debug("scanlog: hit eof\n");
                        return 0;
                    case SCANLOG_HWERROR:
-                       DEBUG("hardware error reading scan log data\n");
+                       pr_debug("scanlog: hardware error reading data\n");
                        return -EIO;
                    case SCANLOG_CONTINUE:
                        /* We may or may not have data yet */
@@ -110,7 +108,8 @@ static ssize_t scanlog_read(struct file *file, char __user *buf,
                        /* Assume extended busy */
                        wait_time = rtas_busy_delay_time(status);
                        if (!wait_time) {
-                               printk(KERN_ERR "scanlog: unknown error from rtas: %d\n", status);
+                               printk(KERN_ERR "scanlog: unknown error " \
+                                      "from rtas: %d\n", status);
                                return -EIO;
                        }
                }
@@ -134,15 +133,9 @@ static ssize_t scanlog_write(struct file * file, const char __user * buf,
 
        if (buf) {
                if (strncmp(stkbuf, "reset", 5) == 0) {
-                       DEBUG("reset scanlog\n");
+                       pr_debug("scanlog: reset scanlog\n");
                        status = rtas_call(ibm_scan_log_dump, 2, 1, NULL, 0, 0);
-                       DEBUG("rtas returns %d\n", status);
-               } else if (strncmp(stkbuf, "debugon", 7) == 0) {
-                       printk(KERN_ERR "scanlog: debug on\n");
-                       scanlog_debug = 1;
-               } else if (strncmp(stkbuf, "debugoff", 8) == 0) {
-                       printk(KERN_ERR "scanlog: debug off\n");
-                       scanlog_debug = 0;
+                       pr_debug("scanlog: rtas returns %d\n", status);
                }
        }
        return count;
index f66aa9c3b13563dff365a0ae60c53c58011145eb..f5d29f5b13c1b0afb1ec3f67e3fb9eabd6c4a2f2 100644 (file)
@@ -16,8 +16,6 @@
  * bootup setup stuff..
  */
 
-#undef DEBUG
-
 #include <linux/cpu.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include "plpar_wrappers.h"
 #include "pseries.h"
 
-#ifdef DEBUG
-#define DBG(fmt...) udbg_printf(fmt)
-#else
-#define DBG(fmt...)
-#endif
 
 int fwnmi_active;  /* TRUE if an FWNMI handler is present */
 
@@ -326,7 +319,7 @@ static int pseries_set_xdabr(unsigned long dabr)
  */
 static void __init pSeries_init_early(void)
 {
-       DBG(" -> pSeries_init_early()\n");
+       pr_debug(" -> pSeries_init_early()\n");
 
        if (firmware_has_feature(FW_FEATURE_LPAR))
                find_udbg_vterm();
@@ -338,7 +331,7 @@ static void __init pSeries_init_early(void)
 
        iommu_init_early_pSeries();
 
-       DBG(" <- pSeries_init_early()\n");
+       pr_debug(" <- pSeries_init_early()\n");
 }
 
 /*
@@ -383,7 +376,7 @@ static int __init pSeries_probe(void)
            of_flat_dt_is_compatible(root, "IBM,CBEA"))
                return 0;
 
-       DBG("pSeries detected, looking for LPAR capability...\n");
+       pr_debug("pSeries detected, looking for LPAR capability...\n");
 
        /* Now try to figure out if we are running on LPAR */
        of_scan_flat_dt(pSeries_probe_hypertas, NULL);
@@ -393,8 +386,8 @@ static int __init pSeries_probe(void)
        else
                hpte_init_native();
 
-       DBG("Machine is%s LPAR !\n",
-           (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
+       pr_debug("Machine is%s LPAR !\n",
+                (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
 
        return 1;
 }
index ea4c65917a648c5e4795a99a23ba87c4efaf3351..9d8f8c84ab8900e0d661118addbc551bb2c3714d 100644 (file)
@@ -12,7 +12,6 @@
  *      2 of the License, or (at your option) any later version.
  */
 
-#undef DEBUG
 
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include "plpar_wrappers.h"
 #include "pseries.h"
 
-#ifdef DEBUG
-#include <asm/udbg.h>
-#define DBG(fmt...) udbg_printf(fmt)
-#else
-#define DBG(fmt...)
-#endif
 
 /*
  * The primary thread of each non-boot processor is recorded here before
@@ -231,7 +224,7 @@ static void __init smp_init_pseries(void)
 {
        int i;
 
-       DBG(" -> smp_init_pSeries()\n");
+       pr_debug(" -> smp_init_pSeries()\n");
 
        /* Mark threads which are still spinning in hold loops. */
        if (cpu_has_feature(CPU_FTR_SMT)) {
@@ -255,7 +248,7 @@ static void __init smp_init_pseries(void)
                smp_ops->take_timebase = pSeries_take_timebase;
        }
 
-       DBG(" <- smp_init_pSeries()\n");
+       pr_debug(" <- smp_init_pSeries()\n");
 }
 
 #ifdef CONFIG_MPIC
index 43df53c30aa079cd390f6dd06ac9ccd47d9f0a10..ebebc28fe89545c8658c6410bb70203fe51bcda3 100644 (file)
@@ -9,7 +9,6 @@
  *  2 of the License, or (at your option) any later version.
  */
 
-#undef DEBUG
 
 #include <linux/types.h>
 #include <linux/threads.h>
index 047b31027fa6500ec03ba55727da52d6b1fc58ad..41af1223e2a0f058036d7c4a11af9cf8d5a21937 100644 (file)
@@ -338,15 +338,13 @@ static int __init mv64x60_i2c_device_setup(struct device_node *np, int id)
 
        pdata.freq_m = 8;       /* default */
        prop = of_get_property(np, "freq_m", NULL);
-       if (!prop)
-               return -ENODEV;
-       pdata.freq_m = *prop;
+       if (prop)
+               pdata.freq_m = *prop;
 
        pdata.freq_m = 3;       /* default */
        prop = of_get_property(np, "freq_n", NULL);
-       if (!prop)
-               return -ENODEV;
-       pdata.freq_n = *prop;
+       if (prop)
+               pdata.freq_n = *prop;
 
        pdata.timeout = 1000;                           /* default: 1 second */
 
@@ -433,9 +431,13 @@ static int __init mv64x60_device_setup(void)
        int err;
 
        id = 0;
-       for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc")
-               if ((err = mv64x60_mpsc_device_setup(np, id++)))
-                       goto error;
+       for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc") {
+               err = mv64x60_mpsc_device_setup(np, id++);
+               if (err)
+                       printk(KERN_ERR "Failed to initialize MV64x60 "
+                                       "serial device %s: error %d.\n",
+                                       np->full_name, err);
+       }
 
        id = 0;
        id2 = 0;
@@ -443,38 +445,44 @@ static int __init mv64x60_device_setup(void)
                pdev = mv64x60_eth_register_shared_pdev(np, id++);
                if (IS_ERR(pdev)) {
                        err = PTR_ERR(pdev);
-                       goto error;
+                       printk(KERN_ERR "Failed to initialize MV64x60 "
+                                       "network block %s: error %d.\n",
+                                       np->full_name, err);
+                       continue;
                }
                for_each_child_of_node(np, np2) {
                        if (!of_device_is_compatible(np2,
                                        "marvell,mv64360-eth"))
                                continue;
                        err = mv64x60_eth_device_setup(np2, id2++, pdev);
-                       if (err) {
-                               of_node_put(np2);
-                               goto error;
-                       }
+                       if (err)
+                               printk(KERN_ERR "Failed to initialize "
+                                               "MV64x60 network device %s: "
+                                               "error %d.\n",
+                                               np2->full_name, err);
                }
        }
 
        id = 0;
-       for_each_compatible_node(np, "i2c", "marvell,mv64360-i2c")
-               if ((err = mv64x60_i2c_device_setup(np, id++)))
-                       goto error;
+       for_each_compatible_node(np, "i2c", "marvell,mv64360-i2c") {
+               err = mv64x60_i2c_device_setup(np, id++);
+               if (err)
+                       printk(KERN_ERR "Failed to initialize MV64x60 I2C "
+                                       "bus %s: error %d.\n",
+                                       np->full_name, err);
+       }
 
        /* support up to one watchdog timer */
        np = of_find_compatible_node(np, NULL, "marvell,mv64360-wdt");
        if (np) {
                if ((err = mv64x60_wdt_device_setup(np, id)))
-                       goto error;
+                       printk(KERN_ERR "Failed to initialize MV64x60 "
+                                       "Watchdog %s: error %d.\n",
+                                       np->full_name, err);
                of_node_put(np);
        }
 
        return 0;
-
-error:
-       of_node_put(np);
-       return err;
 }
 arch_initcall(mv64x60_device_setup);
 
index ccdb3b0418fce024d86df3e8fb372e36da4249f0..2792dc8b038c6efe52f626ffadd4edde64d29777 100644 (file)
@@ -94,7 +94,7 @@ static void mv64x60_udbg_init(void)
        if (!np)
                return;
 
-       block_index = of_get_property(np, "block-index", NULL);
+       block_index = of_get_property(np, "cell-index", NULL);
        if (!block_index)
                goto error;
 
index bcc3aa9d04f397fa62f7ef83fef80262c2eba942..d38b57e24ceefc94b29d9a82cde473dac6dd86f2 100644 (file)
@@ -165,9 +165,6 @@ static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
 #ifdef CONFIG_SBC82xx
 #define F1_RXCLK       9
 #define F1_TXCLK       10
-#elif defined(CONFIG_ADS8272)
-#define F1_RXCLK       11
-#define F1_TXCLK       10
 #else
 #define F1_RXCLK       12
 #define F1_TXCLK       11
@@ -175,13 +172,8 @@ static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
 
 /* FCC2 Clock Source Configuration.  There are board specific.
    Can only choose from CLK13-16 */
-#ifdef CONFIG_ADS8272
-#define F2_RXCLK       15
-#define F2_TXCLK       16
-#else
 #define F2_RXCLK       13
 #define F2_TXCLK       14
-#endif
 
 /* FCC3 Clock Source Configuration.  There are board specific.
    Can only choose from CLK13-16 */
@@ -289,10 +281,7 @@ static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
 /* TQM8260 has MDIO and MDCK on PC30 and PC31 respectively */
 #define PC_MDIO                ((uint)0x00000002)
 #define PC_MDCK                ((uint)0x00000001)
-#elif defined(CONFIG_ADS8272)
-#define PC_MDIO                ((uint)0x00002000)
-#define PC_MDCK                ((uint)0x00001000)
-#elif defined(CONFIG_EST8260) || defined(CONFIG_ADS8260) || defined(CONFIG_PQ2FADS)
+#elif defined(CONFIG_EST8260) || defined(CONFIG_ADS8260)
 #define PC_MDIO                ((uint)0x00400000)
 #define PC_MDCK                ((uint)0x00200000)
 #else
@@ -2118,11 +2107,6 @@ init_fcc_startup(fcc_info_t *fip, struct net_device *dev)
                printk("Can't get FCC IRQ %d\n", fip->fc_interrupt);
 
 #ifdef PHY_INTERRUPT
-#ifdef CONFIG_ADS8272
-       if (request_irq(PHY_INTERRUPT, mii_link_interrupt, IRQF_SHARED,
-                               "mii", dev) < 0)
-               printk(KERN_CRIT "Can't get MII IRQ %d\n", PHY_INTERRUPT);
-#else
        /* Make IRQn edge triggered.  This does not work if PHY_INTERRUPT is
         * on Port C.
         */
@@ -2132,7 +2116,6 @@ init_fcc_startup(fcc_info_t *fip, struct net_device *dev)
        if (request_irq(PHY_INTERRUPT, mii_link_interrupt, 0,
                                                        "mii", dev) < 0)
                printk(KERN_CRIT "Can't get MII IRQ %d\n", PHY_INTERRUPT);
-#endif
 #endif /* PHY_INTERRUPT */
 
        /* Set GFMR to enable Ethernet operating mode.
index c6d047ae77ac5d9f93b4f86be0c9ce716e476362..5899aea1644b332460f0a5c9b410ee03d3e68c44 100644 (file)
@@ -946,29 +946,6 @@ static int __init scc_enet_init(void)
        *((volatile uint *)BCSR1) &= ~BCSR1_ETHEN;
 #endif
 
-#ifdef CONFIG_MPC885ADS
-
-       /* Deassert PHY reset and enable the PHY.
-        */
-       {
-               volatile uint __iomem *bcsr = ioremap(BCSR_ADDR, BCSR_SIZE);
-               uint tmp;
-
-               tmp = in_be32(bcsr + 1 /* BCSR1 */);
-               tmp |= BCSR1_ETHEN;
-               out_be32(bcsr + 1, tmp);
-               tmp = in_be32(bcsr + 4 /* BCSR4 */);
-               tmp |= BCSR4_ETH10_RST;
-               out_be32(bcsr + 4, tmp);
-               iounmap(bcsr);
-       }
-
-       /* On MPC885ADS SCC ethernet PHY defaults to the full duplex mode
-        * upon reset. SCC is set to half duplex by default. So this
-        * inconsistency should be better fixed by the software.
-        */
-#endif
-
        dev->base_addr = (unsigned long)ep;
 #if 0
        dev->name = "CPM_ENET";
index abc877faf1232eb73cc284d6737e8ef356bef308..0f1863ed9c1c814abf1509566489b02ab651d664 100644 (file)
@@ -372,22 +372,6 @@ config MPC8XXFADS
        bool "FADS"
        select FADS
 
-config MPC86XADS
-       bool "MPC86XADS"
-       help
-         MPC86x Application Development System by Freescale Semiconductor.
-         The MPC86xADS is meant to serve as a platform for s/w and h/w
-         development around the MPC86X processor families.
-       select FADS
-
-config MPC885ADS
-       bool "MPC885ADS"
-       help
-         Freescale Semiconductor MPC885 Application Development System (ADS).
-         Also known as DUET.
-         The MPC885ADS is meant to serve as a platform for s/w and h/w
-         development around the MPC885 processor family.
-
 config TQM823L
        bool "TQM823L"
        help
@@ -479,53 +463,6 @@ config WINCEPT
 
 endchoice
 
-menu "Freescale Ethernet driver platform-specific options"
-       depends on FS_ENET
-
-       config MPC8xx_SECOND_ETH
-       bool "Second Ethernet channel"
-       depends on (MPC885ADS || MPC86XADS)
-       default y
-       help
-         This enables support for second Ethernet on MPC885ADS and MPC86xADS boards.
-         The latter will use SCC1, for 885ADS you can select it below.
-
-       choice
-               prompt "Second Ethernet channel"
-               depends on MPC8xx_SECOND_ETH
-               default MPC8xx_SECOND_ETH_FEC2
-
-               config MPC8xx_SECOND_ETH_FEC2
-               bool "FEC2"
-               depends on MPC885ADS
-               help
-                 Enable FEC2 to serve as 2-nd Ethernet channel. Note that SMC2
-                 (often 2-nd UART) will not work if this is enabled.
-
-               config MPC8xx_SECOND_ETH_SCC1
-               bool "SCC1"
-               depends on MPC86XADS
-               select MPC8xx_SCC_ENET_FIXED
-               help
-                 Enable SCC1 to serve as 2-nd Ethernet channel. Note that SMC1
-                 (often 1-nd UART) will not work if this is enabled.
-
-               config MPC8xx_SECOND_ETH_SCC3
-               bool "SCC3"
-               depends on MPC885ADS
-               help
-                 Enable SCC3 to serve as 2-nd Ethernet channel. Note that SMC1
-                 (often 1-nd UART) will not work if this is enabled.
-
-       endchoice
-
-       config MPC8xx_SCC_ENET_FIXED
-       depends on MPC8xx_SECOND_ETH_SCC
-       default n
-       bool "Use fixed MII-less mode for SCC Ethernet"
-
-endmenu
-
 choice
        prompt "Machine Type"
        depends on 6xx
@@ -666,9 +603,6 @@ config TQM8260
          End of Life: not yet :-)
          URL: <http://www.denx.de/PDF/TQM82xx_SPEC_Rev005.pdf>
 
-config ADS8272
-       bool "ADS8272"
-
 config PQ2FADS
        bool "Freescale-PQ2FADS"
        help
@@ -698,11 +632,6 @@ config EV64360
          platform.
 endchoice
 
-config PQ2ADS
-       bool
-       depends on ADS8272
-       default y
-
 config TQM8xxL
        bool
        depends on 8xx && (TQM823L || TQM850L || FPS850L || TQM855L || TQM860L)
@@ -725,15 +654,6 @@ config 8260
          this option means that you wish to build a kernel for a machine with
          an 8260 class CPU.
 
-config 8272
-       bool
-       depends on 6xx
-       default y if ADS8272
-       select 8260
-       help
-         The MPC8272 CPM has a different internal dpram setup than other CPM2
-         devices
-
 config CPM1
        bool
        depends on 8xx
@@ -1069,7 +989,7 @@ config PCI_8260
 
 config 8260_PCI9
        bool "Enable workaround for MPC826x erratum PCI 9"
-       depends on PCI_8260 && !ADS8272
+       depends on PCI_8260
        default y
 
 choice
diff --git a/arch/ppc/configs/ads8272_defconfig b/arch/ppc/configs/ads8272_defconfig
deleted file mode 100644 (file)
index 6619f91..0000000
+++ /dev/null
@@ -1,930 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc5
-# Wed Apr  4 20:55:16 2007
-#
-CONFIG_MMU=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_ARCH_HAS_ILOG2_U32=y
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_PPC=y
-CONFIG_PPC32=y
-CONFIG_GENERIC_NVRAM=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-CONFIG_GENERIC_BUG=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-# CONFIG_RELAY is not set
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-# CONFIG_KALLSYMS is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-# CONFIG_EPOLL is not set
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
-# CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
-
-#
-# Processor
-#
-CONFIG_6xx=y
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-# CONFIG_8xx is not set
-# CONFIG_E200 is not set
-# CONFIG_E500 is not set
-CONFIG_PPC_FPU=y
-# CONFIG_PPC_DCR_NATIVE is not set
-# CONFIG_KEXEC is not set
-# CONFIG_CPU_FREQ is not set
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_EMBEDDEDBOOT=y
-CONFIG_PPC_STD_MMU=y
-
-#
-# Platform options
-#
-
-#
-# Freescale Ethernet driver platform-specific options
-#
-# CONFIG_PPC_PREP is not set
-# CONFIG_APUS is not set
-# CONFIG_KATANA is not set
-# CONFIG_WILLOW is not set
-# CONFIG_CPCI690 is not set
-# CONFIG_POWERPMC250 is not set
-# CONFIG_CHESTNUT is not set
-# CONFIG_SPRUCE is not set
-# CONFIG_HDPU is not set
-# CONFIG_EV64260 is not set
-# CONFIG_LOPEC is not set
-# CONFIG_MVME5100 is not set
-# CONFIG_PPLUS is not set
-# CONFIG_PRPMC750 is not set
-# CONFIG_PRPMC800 is not set
-# CONFIG_SANDPOINT is not set
-# CONFIG_RADSTONE_PPC7D is not set
-# CONFIG_PAL4 is not set
-# CONFIG_EST8260 is not set
-# CONFIG_SBC82xx is not set
-# CONFIG_SBS8260 is not set
-# CONFIG_RPX8260 is not set
-# CONFIG_TQM8260 is not set
-CONFIG_ADS8272=y
-# CONFIG_PQ2FADS is not set
-# CONFIG_LITE5200 is not set
-# CONFIG_MPC834x_SYS is not set
-# CONFIG_EV64360 is not set
-CONFIG_PQ2ADS=y
-CONFIG_8260=y
-CONFIG_8272=y
-CONFIG_CPM2=y
-# CONFIG_PC_KEYBOARD is not set
-# CONFIG_SMP is not set
-# CONFIG_HIGHMEM is not set
-CONFIG_ARCH_POPULATES_NODE_MAP=y
-# CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_300 is not set
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-CONFIG_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_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_CMDLINE_BOOL is not set
-# CONFIG_PM is not set
-CONFIG_SECCOMP=y
-CONFIG_ISA_DMA_API=y
-
-#
-# Bus options
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_PPC_I8259 is not set
-CONFIG_PPC_INDIRECT_PCI=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_8260=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-
-#
-# Advanced setup
-#
-# CONFIG_ADVANCED_OPTIONS is not set
-
-#
-# Default settings for advanced configuration options are used
-#
-CONFIG_HIGHMEM_START=0xfe000000
-CONFIG_LOWMEM_SIZE=0x30000000
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE=0x80000000
-CONFIG_BOOT_LOAD=0x00400000
-
-#
-# 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=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-# CONFIG_NETWORK_SECMARK is not set
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-# CONFIG_IEEE80211 is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=32768
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-# CONFIG_CDROM_PKTCDVD is not set
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# Misc devices
-#
-# CONFIG_SGI_IOC4 is not set
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-# CONFIG_MARVELL_PHY is not set
-CONFIG_DAVICOM_PHY=y
-# CONFIG_QSEMI_PHY is not set
-# CONFIG_LXT_PHY is not set
-# CONFIG_CICADA_PHY is not set
-# CONFIG_VITESSE_PHY is not set
-# CONFIG_SMSC_PHY is not set
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-CONFIG_FS_ENET=y
-# CONFIG_FS_ENET_HAS_SCC is not set
-CONFIG_FS_ENET_HAS_FCC=y
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-# CONFIG_QLA3XXX is not set
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-# CONFIG_CHELSIO_T3 is not set
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_SERIAL_UARTLITE is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_SERIAL_CPM=y
-CONFIG_SERIAL_CPM_CONSOLE=y
-CONFIG_SERIAL_CPM_SCC1=y
-# CONFIG_SERIAL_CPM_SCC2 is not set
-# CONFIG_SERIAL_CPM_SCC3 is not set
-CONFIG_SERIAL_CPM_SCC4=y
-# CONFIG_SERIAL_CPM_SMC1 is not set
-# CONFIG_SERIAL_CPM_SMC2 is not set
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-CONFIG_HW_RANDOM=y
-# CONFIG_NVRAM is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
-
-#
-# Multifunction device drivers
-#
-# CONFIG_MFD_SM501 is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-# CONFIG_FB is not set
-# CONFIG_FB_IBM_GXT4500 is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_FUSE_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_POSIX_ACL is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_ACL_SUPPORT=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=y
-CONFIG_RPCSEC_GSS_KRB5=y
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-# CONFIG_MSDOS_PARTITION is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_KARMA_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
-# CONFIG_DLM is not set
-# CONFIG_SCC_ENET is not set
-# CONFIG_FEC_ENET is not set
-
-#
-# CPM2 Options
-#
-
-#
-# Library routines
-#
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_KGDB_CONSOLE is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_MANAGER=y
-# CONFIG_CRYPTO_HMAC is not set
-# CONFIG_CRYPTO_XCBC is not set
-# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_MD4 is not set
-CONFIG_CRYPTO_MD5=y
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_WP512 is not set
-# CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_GF128MUL is not set
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_PCBC=y
-# CONFIG_CRYPTO_LRW is not set
-CONFIG_CRYPTO_DES=y
-# CONFIG_CRYPTO_FCRYPT is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_AES is not set
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_ARC4 is not set
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_CAMELLIA is not set
-
-#
-# Hardware crypto devices
-#
diff --git a/arch/ppc/configs/mpc86x_ads_defconfig b/arch/ppc/configs/mpc86x_ads_defconfig
deleted file mode 100644 (file)
index f63c6f5..0000000
+++ /dev/null
@@ -1,633 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Tue Jun 14 13:36:35 2005
-#
-CONFIG_MMU=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
-CONFIG_PPC=y
-CONFIG_PPC32=y
-CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
-# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
-# CONFIG_KALLSYMS is not set
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-# CONFIG_BASE_FULL is not set
-CONFIG_FUTEX=y
-# CONFIG_EPOLL is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SHMEM is not set
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-CONFIG_TINY_SHMEM=y
-CONFIG_BASE_SMALL=1
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-# CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-# CONFIG_KMOD is not set
-
-#
-# Processor
-#
-# CONFIG_6xx is not set
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-# CONFIG_POWER3 is not set
-# CONFIG_POWER4 is not set
-CONFIG_8xx=y
-# CONFIG_E500 is not set
-# CONFIG_MATH_EMULATION is not set
-# CONFIG_CPU_FREQ is not set
-CONFIG_EMBEDDEDBOOT=y
-# CONFIG_PM is not set
-CONFIG_NOT_COHERENT_CACHE=y
-
-#
-# Platform options
-#
-CONFIG_FADS=y
-# CONFIG_RPXLITE is not set
-# CONFIG_RPXCLASSIC is not set
-# CONFIG_BSEIP is not set
-# CONFIG_MPC8XXFADS is not set
-CONFIG_MPC86XADS=y
-# CONFIG_TQM823L is not set
-# CONFIG_TQM850L is not set
-# CONFIG_TQM855L is not set
-# CONFIG_TQM860L is not set
-# CONFIG_FPS850L is not set
-# CONFIG_SPD823TS is not set
-# CONFIG_IVMS8 is not set
-# CONFIG_IVML24 is not set
-# CONFIG_SM850 is not set
-# CONFIG_HERMES_PRO is not set
-# CONFIG_IP860 is not set
-# CONFIG_LWMON is not set
-# CONFIG_PCU_E is not set
-# CONFIG_CCM is not set
-# CONFIG_LANTEC is not set
-# CONFIG_MBX is not set
-# CONFIG_WINCEPT is not set
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_HIGHMEM is not set
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_CMDLINE_BOOL is not set
-CONFIG_ISA_DMA_API=y
-
-#
-# Bus options
-#
-# CONFIG_PCI is not set
-# CONFIG_PCI_DOMAINS is not set
-# CONFIG_PCI_QSPAN is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# Advanced setup
-#
-# CONFIG_ADVANCED_OPTIONS is not set
-
-#
-# Default settings for advanced configuration options are used
-#
-CONFIG_HIGHMEM_START=0xfe000000
-CONFIG_LOWMEM_SIZE=0x30000000
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE=0x80000000
-CONFIG_CONSISTENT_START=0xff100000
-CONFIG_CONSISTENT_SIZE=0x00200000
-CONFIG_BOOT_LOAD=0x00400000
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-# CONFIG_STANDALONE is not set
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_LBD is not set
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
-# Macintosh device drivers
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-CONFIG_IPV6=m
-# CONFIG_IPV6_PRIVACY is not set
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-# CONFIG_INET6_TUNNEL is not set
-# CONFIG_IPV6_TUNNEL is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_OAKNET 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
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-# CONFIG_INPUT is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_SERIAL_CPM=y
-CONFIG_SERIAL_CPM_CONSOLE=y
-# CONFIG_SERIAL_CPM_SCC1 is not set
-# CONFIG_SERIAL_CPM_SCC2 is not set
-# CONFIG_SERIAL_CPM_SCC3 is not set
-# CONFIG_SERIAL_CPM_SCC4 is not set
-CONFIG_SERIAL_CPM_SMC1=y
-# CONFIG_SERIAL_CPM_SMC2 is not set
-CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_ARCH_HAS_HCD is not set
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-# CONFIG_TMPFS is not set
-# CONFIG_HUGETLBFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=y
-CONFIG_RPCSEC_GSS_KRB5=y
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# MPC8xx CPM Options
-#
-CONFIG_SCC_ENET=y
-CONFIG_SCC1_ENET=y
-# CONFIG_SCC2_ENET is not set
-# CONFIG_SCC3_ENET is not set
-# CONFIG_FEC_ENET is not set
-# CONFIG_ENET_BIG_BUFFERS is not set
-
-#
-# Generic MPC8xx Options
-#
-# CONFIG_8xx_COPYBACK is not set
-# CONFIG_8xx_CPU6 is not set
-CONFIG_NO_UCODE_PATCH=y
-# CONFIG_USB_SOF_UCODE_PATCH is not set
-# CONFIG_I2C_SPI_UCODE_PATCH is not set
-# CONFIG_I2C_SPI_SMC1_UCODE_PATCH is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-# CONFIG_CRYPTO_HMAC is not set
-# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_MD4 is not set
-CONFIG_CRYPTO_MD5=y
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_WP512 is not set
-# CONFIG_CRYPTO_TGR192 is not set
-CONFIG_CRYPTO_DES=y
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_AES is not set
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_ARC4 is not set
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
diff --git a/arch/ppc/configs/mpc885ads_defconfig b/arch/ppc/configs/mpc885ads_defconfig
deleted file mode 100644 (file)
index 016f94d..0000000
+++ /dev/null
@@ -1,622 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc6
-# Thu Jun  9 21:17:29 2005
-#
-CONFIG_MMU=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
-CONFIG_PPC=y
-CONFIG_PPC32=y
-CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
-# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
-# CONFIG_KALLSYMS is not set
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-# CONFIG_EPOLL is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Processor
-#
-# CONFIG_6xx is not set
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-# CONFIG_POWER3 is not set
-# CONFIG_POWER4 is not set
-CONFIG_8xx=y
-# CONFIG_E500 is not set
-# CONFIG_MATH_EMULATION is not set
-# CONFIG_CPU_FREQ is not set
-CONFIG_EMBEDDEDBOOT=y
-# CONFIG_PM is not set
-CONFIG_NOT_COHERENT_CACHE=y
-
-#
-# Platform options
-#
-# CONFIG_RPXLITE is not set
-# CONFIG_RPXCLASSIC is not set
-# CONFIG_BSEIP is not set
-# CONFIG_FADS is not set
-CONFIG_MPC885ADS=y
-# CONFIG_TQM823L is not set
-# CONFIG_TQM850L is not set
-# CONFIG_TQM855L is not set
-# CONFIG_TQM860L is not set
-# CONFIG_FPS850L is not set
-# CONFIG_SPD823TS is not set
-# CONFIG_IVMS8 is not set
-# CONFIG_IVML24 is not set
-# CONFIG_SM850 is not set
-# CONFIG_HERMES_PRO is not set
-# CONFIG_IP860 is not set
-# CONFIG_LWMON is not set
-# CONFIG_PCU_E is not set
-# CONFIG_CCM is not set
-# CONFIG_LANTEC is not set
-# CONFIG_MBX is not set
-# CONFIG_WINCEPT is not set
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_HIGHMEM is not set
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_CMDLINE_BOOL is not set
-CONFIG_ISA_DMA_API=y
-
-#
-# Bus options
-#
-# CONFIG_PCI is not set
-# CONFIG_PCI_DOMAINS is not set
-# CONFIG_PCI_QSPAN is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# Advanced setup
-#
-# CONFIG_ADVANCED_OPTIONS is not set
-
-#
-# Default settings for advanced configuration options are used
-#
-CONFIG_HIGHMEM_START=0xfe000000
-CONFIG_LOWMEM_SIZE=0x30000000
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE=0x80000000
-CONFIG_CONSISTENT_START=0xff100000
-CONFIG_CONSISTENT_SIZE=0x00200000
-CONFIG_BOOT_LOAD=0x00400000
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_LBD is not set
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
-# Macintosh device drivers
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_OAKNET 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=y
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_SYNC_TTY=y
-CONFIG_PPP_DEFLATE=y
-# CONFIG_PPP_BSDCOMP is not set
-# CONFIG_PPPOE is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-# CONFIG_INPUT is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_SERIAL_CPM=y
-CONFIG_SERIAL_CPM_CONSOLE=y
-# CONFIG_SERIAL_CPM_SCC1 is not set
-# CONFIG_SERIAL_CPM_SCC2 is not set
-# CONFIG_SERIAL_CPM_SCC3 is not set
-# CONFIG_SERIAL_CPM_SCC4 is not set
-CONFIG_SERIAL_CPM_SMC1=y
-CONFIG_SERIAL_CPM_SMC2=y
-CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_ARCH_HAS_HCD is not set
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND 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=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_PROC_KCORE is not set
-CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-# CONFIG_TMPFS is not set
-# CONFIG_HUGETLBFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# MPC8xx CPM Options
-#
-CONFIG_SCC_ENET=y
-# CONFIG_SCC1_ENET is not set
-# CONFIG_SCC2_ENET is not set
-CONFIG_SCC3_ENET=y
-# CONFIG_FEC_ENET is not set
-# CONFIG_ENET_BIG_BUFFERS is not set
-
-#
-# Generic MPC8xx Options
-#
-CONFIG_8xx_COPYBACK=y
-CONFIG_8xx_CPU6=y
-CONFIG_NO_UCODE_PATCH=y
-# CONFIG_USB_SOF_UCODE_PATCH is not set
-# CONFIG_I2C_SPI_UCODE_PATCH is not set
-# CONFIG_I2C_SPI_SMC1_UCODE_PATCH is not set
-
-#
-# Library routines
-#
-CONFIG_CRC_CCITT=y
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
index 2ba659f401bea31dcd9095eff9f97a4519592486..d9036ef0b6581215211397cd806f10eae4acfe38 100644 (file)
@@ -88,6 +88,7 @@ EXPORT_SYMBOL(strncpy);
 EXPORT_SYMBOL(strcat);
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strncmp);
 
 EXPORT_SYMBOL(csum_partial);
 EXPORT_SYMBOL(csum_partial_copy_generic);
index 84ed33ab4c2de8038a0891eb06ddda06e2484a31..927253bfc8262fab2ea233437bf7b918b5dabd67 100644 (file)
@@ -121,6 +121,20 @@ _GLOBAL(strcmp)
        beq     1b
        blr
 
+_GLOBAL(strncmp)
+       PPC_LCMPI r5,0
+       beqlr
+       mtctr   r5
+       addi    r5,r3,-1
+       addi    r4,r4,-1
+1:     lbzu    r3,1(r5)
+       cmpwi   1,r3,0
+       lbzu    r0,1(r4)
+       subf.   r3,r0,r3
+       beqlr   1
+       bdnzt   eq,1b
+       blr
+
 _GLOBAL(strlen)
        addi    r4,r3,-1
 1:     lbzu    r0,1(r4)
index 40f53fbe6d35c5d87978e2a40cf47a416e026e91..6260231987cbef58c31e2e28baf16cc17f8b5755 100644 (file)
@@ -4,7 +4,6 @@
 
 obj-$(CONFIG_PPC_PREP)         += prep_pci.o prep_setup.o
 obj-$(CONFIG_PREP_RESIDUAL)    += residual.o
-obj-$(CONFIG_PQ2ADS)           += pq2ads.o
 obj-$(CONFIG_TQM8260)          += tqm8260_setup.o
 obj-$(CONFIG_CPCI690)          += cpci690.o
 obj-$(CONFIG_EV64260)          += ev64260.o
@@ -24,6 +23,3 @@ obj-$(CONFIG_SBC82xx)         += sbc82xx.o
 obj-$(CONFIG_SPRUCE)           += spruce.o
 obj-$(CONFIG_LITE5200)         += lite5200.o
 obj-$(CONFIG_EV64360)          += ev64360.o
-obj-$(CONFIG_MPC86XADS)                += mpc866ads_setup.o
-obj-$(CONFIG_MPC885ADS)                += mpc885ads_setup.o
-obj-$(CONFIG_ADS8272)          += mpc8272ads_setup.o
index 2f9f0f60e3f76139f80a5ca43246679e091a3db8..5219366667b377961a88dd1010697dd9c849bb1a 100644 (file)
 
 #include <asm/ppcboot.h>
 
-#if defined(CONFIG_MPC86XADS)
-
-#define BOARD_CHIP_NAME "MPC86X"
-
-/* U-Boot maps BCSR to 0xff080000 */
-#define BCSR_ADDR              ((uint)0xff080000)
-
-/* MPC86XADS has one more CPLD and an additional BCSR.
- */
-#define CFG_PHYDEV_ADDR                ((uint)0xff0a0000)
-#define BCSR5                  ((uint)(CFG_PHYDEV_ADDR + 0x300))
-
-#define BCSR5_T1_RST           0x10
-#define BCSR5_ATM155_RST       0x08
-#define BCSR5_ATM25_RST                0x04
-#define BCSR5_MII1_EN          0x02
-#define BCSR5_MII1_RST         0x01
-
-/* There is no PHY link change interrupt */
-#define PHY_INTERRUPT  (-1)
-
-#else /* FADS */
-
 /* Memory map is configured by the PROM startup.
  * I tried to follow the FADS manual, although the startup PROM
  * dictates this and we simply have to move some of the physical
@@ -55,8 +32,6 @@
 /* PHY link change interrupt */
 #define PHY_INTERRUPT  SIU_IRQ2
 
-#endif /* CONFIG_MPC86XADS */
-
 #define BCSR_SIZE              ((uint)(64 * 1024))
 #define BCSR0                  ((uint)(BCSR_ADDR + 0x00))
 #define BCSR1                  ((uint)(BCSR_ADDR + 0x04))
diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c
deleted file mode 100644 (file)
index 47f4b38..0000000
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * arch/ppc/platforms/mpc8272ads_setup.c
- *
- * MPC82xx Board-specific PlatformDevice descriptions
- *
- * 2005 (c) MontaVista Software, Inc.
- * Vitaly Bordug <vbordug@ru.mvista.com>
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/ioport.h>
-#include <linux/fs_enet_pd.h>
-#include <linux/platform_device.h>
-#include <linux/phy.h>
-
-#include <asm/io.h>
-#include <asm/mpc8260.h>
-#include <asm/cpm2.h>
-#include <asm/immap_cpm2.h>
-#include <asm/irq.h>
-#include <asm/ppc_sys.h>
-#include <asm/ppcboot.h>
-#include <linux/fs_uart_pd.h>
-
-#include "pq2ads_pd.h"
-
-static void init_fcc1_ioports(struct fs_platform_info*);
-static void init_fcc2_ioports(struct fs_platform_info*);
-static void init_scc1_uart_ioports(struct fs_uart_platform_info*);
-static void init_scc4_uart_ioports(struct fs_uart_platform_info*);
-
-static struct fs_uart_platform_info mpc8272_uart_pdata[] = {
-       [fsid_scc1_uart] = {
-               .init_ioports   = init_scc1_uart_ioports,
-               .fs_no          = fsid_scc1_uart,
-               .brg            = 1,
-               .tx_num_fifo    = 4,
-               .tx_buf_size    = 32,
-               .rx_num_fifo    = 4,
-               .rx_buf_size    = 32,
-       },
-       [fsid_scc4_uart] = {
-               .init_ioports   = init_scc4_uart_ioports,
-               .fs_no          = fsid_scc4_uart,
-               .brg            = 4,
-               .tx_num_fifo    = 4,
-               .tx_buf_size    = 32,
-               .rx_num_fifo    = 4,
-               .rx_buf_size    = 32,
-       },
-};
-
-static struct fs_mii_bb_platform_info m82xx_mii_bb_pdata = {
-       .mdio_dat.bit   = 18,
-       .mdio_dir.bit   = 18,
-       .mdc_dat.bit    = 19,
-       .delay          = 1,
-};
-
-static struct fs_platform_info mpc82xx_enet_pdata[] = {
-       [fsid_fcc1] = {
-               .fs_no          = fsid_fcc1,
-               .cp_page        = CPM_CR_FCC1_PAGE,
-               .cp_block       = CPM_CR_FCC1_SBLOCK,
-
-               .clk_trx        = (PC_F1RXCLK | PC_F1TXCLK),
-               .clk_route      = CMX1_CLK_ROUTE,
-               .clk_mask       = CMX1_CLK_MASK,
-               .init_ioports   = init_fcc1_ioports,
-
-               .mem_offset     = FCC1_MEM_OFFSET,
-
-               .rx_ring        = 32,
-               .tx_ring        = 32,
-               .rx_copybreak   = 240,
-               .use_napi       = 0,
-               .napi_weight    = 17,
-               .bus_id         = "0:00",
-       },
-       [fsid_fcc2] = {
-               .fs_no          = fsid_fcc2,
-               .cp_page        = CPM_CR_FCC2_PAGE,
-               .cp_block       = CPM_CR_FCC2_SBLOCK,
-               .clk_trx        = (PC_F2RXCLK | PC_F2TXCLK),
-               .clk_route      = CMX2_CLK_ROUTE,
-               .clk_mask       = CMX2_CLK_MASK,
-               .init_ioports   = init_fcc2_ioports,
-
-               .mem_offset     = FCC2_MEM_OFFSET,
-
-               .rx_ring        = 32,
-               .tx_ring        = 32,
-               .rx_copybreak   = 240,
-               .use_napi       = 0,
-               .napi_weight    = 17,
-               .bus_id         = "0:03",
-       },
-};
-
-static void init_fcc1_ioports(struct fs_platform_info* pdata)
-{
-       struct io_port *io;
-       u32 tempval;
-       cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
-       u32 *bcsr = ioremap(BCSR_ADDR+4, sizeof(u32));
-
-       io = &immap->im_ioport;
-
-       /* Enable the PHY */
-       clrbits32(bcsr, BCSR1_FETHIEN);
-       setbits32(bcsr, BCSR1_FETH_RST);
-
-       /* FCC1 pins are on port A/C. */
-       /* Configure port A and C pins for FCC1 Ethernet. */
-
-       tempval = in_be32(&io->iop_pdira);
-       tempval &= ~PA1_DIRA0;
-       tempval |= PA1_DIRA1;
-       out_be32(&io->iop_pdira, tempval);
-
-       tempval = in_be32(&io->iop_psora);
-       tempval &= ~PA1_PSORA0;
-       tempval |= PA1_PSORA1;
-       out_be32(&io->iop_psora, tempval);
-
-       setbits32(&io->iop_ppara,PA1_DIRA0 | PA1_DIRA1);
-
-       /* Alter clocks */
-       tempval = PC_F1TXCLK|PC_F1RXCLK;
-
-       clrbits32(&io->iop_psorc, tempval);
-       clrbits32(&io->iop_pdirc, tempval);
-       setbits32(&io->iop_pparc, tempval);
-
-       clrbits32(&immap->im_cpmux.cmx_fcr, CMX1_CLK_MASK);
-       setbits32(&immap->im_cpmux.cmx_fcr, CMX1_CLK_ROUTE);
-       iounmap(bcsr);
-       iounmap(immap);
-}
-
-static void init_fcc2_ioports(struct fs_platform_info* pdata)
-{
-       cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
-       u32 *bcsr = ioremap(BCSR_ADDR+12, sizeof(u32));
-
-       struct io_port *io;
-       u32 tempval;
-
-       immap = cpm2_immr;
-
-       io = &immap->im_ioport;
-
-       /* Enable the PHY */
-       clrbits32(bcsr, BCSR3_FETHIEN2);
-       setbits32(bcsr, BCSR3_FETH2_RST);
-
-       /* FCC2 are port B/C. */
-       /* Configure port A and C pins for FCC2 Ethernet. */
-
-       tempval = in_be32(&io->iop_pdirb);
-       tempval &= ~PB2_DIRB0;
-       tempval |= PB2_DIRB1;
-       out_be32(&io->iop_pdirb, tempval);
-
-       tempval = in_be32(&io->iop_psorb);
-       tempval &= ~PB2_PSORB0;
-       tempval |= PB2_PSORB1;
-       out_be32(&io->iop_psorb, tempval);
-
-       setbits32(&io->iop_pparb,PB2_DIRB0 | PB2_DIRB1);
-
-       tempval = PC_F2RXCLK|PC_F2TXCLK;
-
-       /* Alter clocks */
-       clrbits32(&io->iop_psorc,tempval);
-       clrbits32(&io->iop_pdirc,tempval);
-       setbits32(&io->iop_pparc,tempval);
-
-       clrbits32(&immap->im_cpmux.cmx_fcr, CMX2_CLK_MASK);
-       setbits32(&immap->im_cpmux.cmx_fcr, CMX2_CLK_ROUTE);
-
-       iounmap(bcsr);
-       iounmap(immap);
-}
-
-
-static void __init mpc8272ads_fixup_enet_pdata(struct platform_device *pdev,
-                                             int idx)
-{
-       bd_t* bi = (void*)__res;
-       int fs_no = fsid_fcc1+pdev->id-1;
-
-       if(fs_no >= ARRAY_SIZE(mpc82xx_enet_pdata)) {
-               return;
-       }
-
-       mpc82xx_enet_pdata[fs_no].dpram_offset=
-                       (u32)cpm2_immr->im_dprambase;
-       mpc82xx_enet_pdata[fs_no].fcc_regs_c =
-                       (u32)cpm2_immr->im_fcc_c;
-       memcpy(&mpc82xx_enet_pdata[fs_no].macaddr,bi->bi_enetaddr,6);
-
-       /* prevent dup mac */
-       if(fs_no == fsid_fcc2)
-               mpc82xx_enet_pdata[fs_no].macaddr[5] ^= 1;
-
-       pdev->dev.platform_data = &mpc82xx_enet_pdata[fs_no];
-}
-
-static void mpc8272ads_fixup_uart_pdata(struct platform_device *pdev,
-                                             int idx)
-{
-       bd_t *bd = (bd_t *) __res;
-       struct fs_uart_platform_info *pinfo;
-       int num = ARRAY_SIZE(mpc8272_uart_pdata);
-       int id = fs_uart_id_scc2fsid(idx);
-
-       /* no need to alter anything if console */
-       if ((id < num) && (!pdev->dev.platform_data)) {
-               pinfo = &mpc8272_uart_pdata[id];
-               pinfo->uart_clk = bd->bi_intfreq;
-               pdev->dev.platform_data = pinfo;
-       }
-}
-
-static void init_scc1_uart_ioports(struct fs_uart_platform_info* pdata)
-{
-       cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
-
-        /* SCC1 is only on port D */
-       setbits32(&immap->im_ioport.iop_ppard,0x00000003);
-       clrbits32(&immap->im_ioport.iop_psord,0x00000001);
-       setbits32(&immap->im_ioport.iop_psord,0x00000002);
-       clrbits32(&immap->im_ioport.iop_pdird,0x00000001);
-       setbits32(&immap->im_ioport.iop_pdird,0x00000002);
-
-        /* Wire BRG1 to SCC1 */
-       clrbits32(&immap->im_cpmux.cmx_scr,0x00ffffff);
-
-       iounmap(immap);
-}
-
-static void init_scc4_uart_ioports(struct fs_uart_platform_info* pdata)
-{
-       cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
-
-       setbits32(&immap->im_ioport.iop_ppard,0x00000600);
-       clrbits32(&immap->im_ioport.iop_psord,0x00000600);
-       clrbits32(&immap->im_ioport.iop_pdird,0x00000200);
-       setbits32(&immap->im_ioport.iop_pdird,0x00000400);
-
-        /* Wire BRG4 to SCC4 */
-       clrbits32(&immap->im_cpmux.cmx_scr,0x000000ff);
-       setbits32(&immap->im_cpmux.cmx_scr,0x0000001b);
-
-       iounmap(immap);
-}
-
-static void __init mpc8272ads_fixup_mdio_pdata(struct platform_device *pdev,
-                                             int idx)
-{
-       m82xx_mii_bb_pdata.irq[0] = PHY_INTERRUPT;
-       m82xx_mii_bb_pdata.irq[1] = PHY_POLL;
-       m82xx_mii_bb_pdata.irq[2] = PHY_POLL;
-       m82xx_mii_bb_pdata.irq[3] = PHY_INTERRUPT;
-       m82xx_mii_bb_pdata.irq[31] = PHY_POLL;
-
-
-       m82xx_mii_bb_pdata.mdio_dat.offset =
-                               (u32)&cpm2_immr->im_ioport.iop_pdatc;
-
-       m82xx_mii_bb_pdata.mdio_dir.offset =
-                               (u32)&cpm2_immr->im_ioport.iop_pdirc;
-
-       m82xx_mii_bb_pdata.mdc_dat.offset =
-                               (u32)&cpm2_immr->im_ioport.iop_pdatc;
-
-
-       pdev->dev.platform_data = &m82xx_mii_bb_pdata;
-}
-
-static int mpc8272ads_platform_notify(struct device *dev)
-{
-       static const struct platform_notify_dev_map dev_map[] = {
-               {
-                       .bus_id = "fsl-cpm-fcc",
-                       .rtn = mpc8272ads_fixup_enet_pdata,
-               },
-               {
-                       .bus_id = "fsl-cpm-scc:uart",
-                       .rtn = mpc8272ads_fixup_uart_pdata,
-               },
-               {
-                       .bus_id = "fsl-bb-mdio",
-                       .rtn = mpc8272ads_fixup_mdio_pdata,
-               },
-               {
-                       .bus_id = NULL
-               }
-       };
-       platform_notify_map(dev_map,dev);
-
-       return 0;
-
-}
-
-int __init mpc8272ads_init(void)
-{
-       printk(KERN_NOTICE "mpc8272ads: Init\n");
-
-       platform_notify = mpc8272ads_platform_notify;
-
-       ppc_sys_device_initfunc();
-
-       ppc_sys_device_disable_all();
-       ppc_sys_device_enable(MPC82xx_CPM_FCC1);
-       ppc_sys_device_enable(MPC82xx_CPM_FCC2);
-
-       /* to be ready for console, let's attach pdata here */
-#ifdef CONFIG_SERIAL_CPM_SCC1
-       ppc_sys_device_setfunc(MPC82xx_CPM_SCC1, PPC_SYS_FUNC_UART);
-       ppc_sys_device_enable(MPC82xx_CPM_SCC1);
-
-#endif
-
-#ifdef CONFIG_SERIAL_CPM_SCC4
-       ppc_sys_device_setfunc(MPC82xx_CPM_SCC4, PPC_SYS_FUNC_UART);
-       ppc_sys_device_enable(MPC82xx_CPM_SCC4);
-#endif
-
-       ppc_sys_device_enable(MPC82xx_MDIO_BB);
-
-       return 0;
-}
-
-/*
-   To prevent confusion, console selection is gross:
-   by 0 assumed SCC1 and by 1 assumed SCC4
- */
-struct platform_device* early_uart_get_pdev(int index)
-{
-       bd_t *bd = (bd_t *) __res;
-       struct fs_uart_platform_info *pinfo;
-
-       struct platform_device* pdev = NULL;
-       if(index) { /*assume SCC4 here*/
-               pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC4];
-               pinfo = &mpc8272_uart_pdata[fsid_scc4_uart];
-       } else { /*over SCC1*/
-               pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC1];
-               pinfo = &mpc8272_uart_pdata[fsid_scc1_uart];
-       }
-
-       pinfo->uart_clk = bd->bi_intfreq;
-       pdev->dev.platform_data = pinfo;
-       ppc_sys_fixup_mem_resource(pdev, CPM_MAP_ADDR);
-       return NULL;
-}
-
-arch_initcall(mpc8272ads_init);
diff --git a/arch/ppc/platforms/mpc885ads.h b/arch/ppc/platforms/mpc885ads.h
deleted file mode 100644 (file)
index d3bbbb3..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * A collection of structures, addresses, and values associated with
- * the Freescale MPC885ADS board.
- * Copied from the FADS stuff.
- *
- * Author: MontaVista Software, Inc.
- *         source@mvista.com
- *
- * 2005 (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.
- */
-
-#ifdef __KERNEL__
-#ifndef __ASM_MPC885ADS_H__
-#define __ASM_MPC885ADS_H__
-
-
-#include <asm/ppcboot.h>
-
-/* U-Boot maps BCSR to 0xff080000 */
-#define BCSR_ADDR              ((uint)0xff080000)
-#define BCSR_SIZE              ((uint)32)
-#define BCSR0                  ((uint)(BCSR_ADDR + 0x00))
-#define BCSR1                  ((uint)(BCSR_ADDR + 0x04))
-#define BCSR2                  ((uint)(BCSR_ADDR + 0x08))
-#define BCSR3                  ((uint)(BCSR_ADDR + 0x0c))
-#define BCSR4                  ((uint)(BCSR_ADDR + 0x10))
-
-#define CFG_PHYDEV_ADDR                ((uint)0xff0a0000)
-#define BCSR5                  ((uint)(CFG_PHYDEV_ADDR + 0x300))
-
-#define IMAP_ADDR              ((uint)0xff000000)
-#define IMAP_SIZE              ((uint)(64 * 1024))
-
-#define PCMCIA_MEM_ADDR                ((uint)0xff020000)
-#define PCMCIA_MEM_SIZE                ((uint)(64 * 1024))
-
-/* Bits of interest in the BCSRs.
- */
-#define BCSR1_ETHEN            ((uint)0x20000000)
-#define BCSR1_IRDAEN           ((uint)0x10000000)
-#define BCSR1_RS232EN_1                ((uint)0x01000000)
-#define BCSR1_PCCEN            ((uint)0x00800000)
-#define BCSR1_PCCVCC0          ((uint)0x00400000)
-#define BCSR1_PCCVPP0          ((uint)0x00200000)
-#define BCSR1_PCCVPP1          ((uint)0x00100000)
-#define BCSR1_PCCVPP_MASK      (BCSR1_PCCVPP0 | BCSR1_PCCVPP1)
-#define BCSR1_RS232EN_2                ((uint)0x00040000)
-#define BCSR1_PCCVCC1          ((uint)0x00010000)
-#define BCSR1_PCCVCC_MASK      (BCSR1_PCCVCC0 | BCSR1_PCCVCC1)
-
-#define BCSR4_ETH10_RST                ((uint)0x80000000)      /* 10Base-T PHY reset*/
-#define BCSR4_USB_LO_SPD       ((uint)0x04000000)
-#define BCSR4_USB_VCC          ((uint)0x02000000)
-#define BCSR4_USB_FULL_SPD     ((uint)0x00040000)
-#define BCSR4_USB_EN           ((uint)0x00020000)
-
-#define BCSR5_MII2_EN          0x40
-#define BCSR5_MII2_RST         0x20
-#define BCSR5_T1_RST           0x10
-#define BCSR5_ATM155_RST       0x08
-#define BCSR5_ATM25_RST                0x04
-#define BCSR5_MII1_EN          0x02
-#define BCSR5_MII1_RST         0x01
-
-/* Interrupt level assignments */
-#define PHY_INTERRUPT  SIU_IRQ7        /* PHY link change interrupt */
-#define SIU_INT_FEC1   SIU_LEVEL1      /* FEC1 interrupt */
-#define SIU_INT_FEC2   SIU_LEVEL3      /* FEC2 interrupt */
-#define FEC_INTERRUPT  SIU_INT_FEC1    /* FEC interrupt */
-
-/* We don't use the 8259 */
-#define NR_8259_INTS   0
-
-/* CPM Ethernet through SCC3 */
-#define PA_ENET_RXD    ((ushort)0x0040)
-#define PA_ENET_TXD    ((ushort)0x0080)
-#define PE_ENET_TCLK   ((uint)0x00004000)
-#define PE_ENET_RCLK   ((uint)0x00008000)
-#define PE_ENET_TENA   ((uint)0x00000010)
-#define PC_ENET_CLSN   ((ushort)0x0400)
-#define PC_ENET_RENA   ((ushort)0x0800)
-
-/* Control bits in the SICR to route TCLK (CLK5) and RCLK (CLK6) to
- * SCC3.  Also, make sure GR3 (bit 8) and SC3 (bit 9) are zero */
-#define SICR_ENET_MASK ((uint)0x00ff0000)
-#define SICR_ENET_CLKRT        ((uint)0x002c0000)
-
-#define BOARD_CHIP_NAME "MPC885"
-
-#endif /* __ASM_MPC885ADS_H__ */
-#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/mpc885ads_setup.c b/arch/ppc/platforms/mpc885ads_setup.c
deleted file mode 100644 (file)
index ba06cc0..0000000
+++ /dev/null
@@ -1,476 +0,0 @@
-/*arch/ppc/platforms/mpc885ads_setup.c
- *
- * Platform setup for the Freescale mpc885ads board
- *
- * Vitaly Bordug <vbordug@ru.mvista.com>
- *
- * Copyright 2005 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/init.h>
-#include <linux/module.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-
-#include <linux/fs_enet_pd.h>
-#include <linux/fs_uart_pd.h>
-#include <linux/mii.h>
-
-#include <asm/delay.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/page.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/time.h>
-#include <asm/ppcboot.h>
-#include <asm/8xx_immap.h>
-#include <asm/cpm1.h>
-#include <asm/ppc_sys.h>
-
-extern unsigned char __res[];
-static void setup_smc1_ioports(struct fs_uart_platform_info*);
-static void setup_smc2_ioports(struct fs_uart_platform_info*);
-
-static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata;
-static void setup_fec1_ioports(struct fs_platform_info*);
-static void setup_fec2_ioports(struct fs_platform_info*);
-static void setup_scc3_ioports(struct fs_platform_info*);
-
-static struct fs_uart_platform_info mpc885_uart_pdata[] = {
-       [fsid_smc1_uart] = {
-               .brg            = 1,
-               .fs_no          = fsid_smc1_uart,
-               .init_ioports   = setup_smc1_ioports,
-               .tx_num_fifo    = 4,
-               .tx_buf_size    = 32,
-               .rx_num_fifo    = 4,
-               .rx_buf_size    = 32,
-       },
-       [fsid_smc2_uart] = {
-               .brg            = 2,
-               .fs_no          = fsid_smc2_uart,
-               .init_ioports   = setup_smc2_ioports,
-               .tx_num_fifo    = 4,
-               .tx_buf_size    = 32,
-               .rx_num_fifo    = 4,
-               .rx_buf_size    = 32,
-       },
-};
-
-static struct fs_platform_info mpc8xx_enet_pdata[] = {
-       [fsid_fec1] = {
-        .rx_ring = 128,
-        .tx_ring = 16,
-        .rx_copybreak = 240,
-
-        .use_napi = 1,
-        .napi_weight = 17,
-
-        .init_ioports = setup_fec1_ioports,
-
-          .bus_id = "0:00",
-          .has_phy = 1,
-        },
-       [fsid_fec2] = {
-            .rx_ring = 128,
-            .tx_ring = 16,
-            .rx_copybreak = 240,
-
-            .use_napi = 1,
-            .napi_weight = 17,
-
-            .init_ioports = setup_fec2_ioports,
-
-            .bus_id = "0:01",
-            .has_phy = 1,
-            },
-       [fsid_scc3] = {
-               .rx_ring = 64,
-               .tx_ring = 8,
-               .rx_copybreak = 240,
-
-               .use_napi = 1,
-               .napi_weight = 17,
-
-               .init_ioports = setup_scc3_ioports,
-#ifdef CONFIG_FIXED_MII_10_FDX
-               .bus_id = "fixed@100:1",
-#else
-               .bus_id = "0:02",
- #endif
-       },
-};
-
-void __init board_init(void)
-{
-       cpm8xx_t *cp = cpmp;
-       unsigned int *bcsr_io;
-
-#ifdef CONFIG_FS_ENET
-       immap_t *immap = (immap_t *) IMAP_ADDR;
-#endif
-       bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-
-       if (bcsr_io == NULL) {
-               printk(KERN_CRIT "Could not remap BCSR\n");
-               return;
-       }
-#ifdef CONFIG_SERIAL_CPM_SMC1
-       cp->cp_simode &= ~(0xe0000000 >> 17);   /* brg1 */
-       clrbits32(bcsr_io, BCSR1_RS232EN_1);
-        cp->cp_smc[0].smc_smcm |= (SMCM_RX | SMCM_TX);
-        cp->cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
-#else
-       setbits32(bcsr_io,BCSR1_RS232EN_1);
-       cp->cp_smc[0].smc_smcmr = 0;
-       cp->cp_smc[0].smc_smce = 0;
-#endif
-
-#ifdef CONFIG_SERIAL_CPM_SMC2
-       cp->cp_simode &= ~(0xe0000000 >> 1);
-       cp->cp_simode |= (0x20000000 >> 1);     /* brg2 */
-       clrbits32(bcsr_io,BCSR1_RS232EN_2);
-        cp->cp_smc[1].smc_smcm |= (SMCM_RX | SMCM_TX);
-        cp->cp_smc[1].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
-#else
-       setbits32(bcsr_io,BCSR1_RS232EN_2);
-       cp->cp_smc[1].smc_smcmr = 0;
-       cp->cp_smc[1].smc_smce = 0;
-#endif
-       iounmap(bcsr_io);
-
-#ifdef CONFIG_FS_ENET
-       /* use MDC for MII (common) */
-       setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
-       clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
-       bcsr_io = ioremap(BCSR5, sizeof(unsigned long));
-       clrbits32(bcsr_io,BCSR5_MII1_EN);
-       clrbits32(bcsr_io,BCSR5_MII1_RST);
-#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
-       clrbits32(bcsr_io,BCSR5_MII2_EN);
-       clrbits32(bcsr_io,BCSR5_MII2_RST);
-#endif
-       iounmap(bcsr_io);
-#endif
-}
-
-static void setup_fec1_ioports(struct fs_platform_info* pdata)
-{
-       immap_t *immap = (immap_t *) IMAP_ADDR;
-
-       /* configure FEC1 pins  */
-       setbits16(&immap->im_ioport.iop_papar, 0xf830);
-       setbits16(&immap->im_ioport.iop_padir, 0x0830);
-       clrbits16(&immap->im_ioport.iop_padir, 0xf000);
-       setbits32(&immap->im_cpm.cp_pbpar, 0x00001001);
-
-       clrbits32(&immap->im_cpm.cp_pbdir, 0x00001001);
-       setbits16(&immap->im_ioport.iop_pcpar, 0x000c);
-       clrbits16(&immap->im_ioport.iop_pcdir, 0x000c);
-       setbits32(&immap->im_cpm.cp_pepar, 0x00000003);
-
-       setbits32(&immap->im_cpm.cp_pedir, 0x00000003);
-       clrbits32(&immap->im_cpm.cp_peso, 0x00000003);
-       clrbits32(&immap->im_cpm.cp_cptr, 0x00000100);
-}
-
-static void setup_fec2_ioports(struct fs_platform_info* pdata)
-{
-       immap_t *immap = (immap_t *) IMAP_ADDR;
-
-       /* configure FEC2 pins */
-       setbits32(&immap->im_cpm.cp_pepar, 0x0003fffc);
-       setbits32(&immap->im_cpm.cp_pedir, 0x0003fffc);
-       clrbits32(&immap->im_cpm.cp_peso, 0x000087fc);
-       setbits32(&immap->im_cpm.cp_peso, 0x00037800);
-       clrbits32(&immap->im_cpm.cp_cptr, 0x00000080);
-}
-
-static void setup_scc3_ioports(struct fs_platform_info* pdata)
-{
-       immap_t *immap = (immap_t *) IMAP_ADDR;
-       unsigned *bcsr_io;
-
-       bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE);
-
-       if (bcsr_io == NULL) {
-               printk(KERN_CRIT "Could not remap BCSR\n");
-               return;
-       }
-
-       /* Enable the PHY.
-        */
-       clrbits32(bcsr_io+4, BCSR4_ETH10_RST);
-       udelay(1000);
-       setbits32(bcsr_io+4, BCSR4_ETH10_RST);
-       /* Configure port A pins for Txd and Rxd.
-        */
-       setbits16(&immap->im_ioport.iop_papar, PA_ENET_RXD | PA_ENET_TXD);
-       clrbits16(&immap->im_ioport.iop_padir, PA_ENET_RXD | PA_ENET_TXD);
-
-       /* Configure port C pins to enable CLSN and RENA.
-        */
-       clrbits16(&immap->im_ioport.iop_pcpar, PC_ENET_CLSN | PC_ENET_RENA);
-       clrbits16(&immap->im_ioport.iop_pcdir, PC_ENET_CLSN | PC_ENET_RENA);
-       setbits16(&immap->im_ioport.iop_pcso, PC_ENET_CLSN | PC_ENET_RENA);
-
-       /* Configure port E for TCLK and RCLK.
-        */
-       setbits32(&immap->im_cpm.cp_pepar, PE_ENET_TCLK | PE_ENET_RCLK);
-       clrbits32(&immap->im_cpm.cp_pepar, PE_ENET_TENA);
-       clrbits32(&immap->im_cpm.cp_pedir,
-                 PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA);
-       clrbits32(&immap->im_cpm.cp_peso, PE_ENET_TCLK | PE_ENET_RCLK);
-       setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA);
-
-       /* Configure Serial Interface clock routing.
-        * First, clear all SCC bits to zero, then set the ones we want.
-        */
-       clrbits32(&immap->im_cpm.cp_sicr, SICR_ENET_MASK);
-       setbits32(&immap->im_cpm.cp_sicr, SICR_ENET_CLKRT);
-
-       /* Disable Rx and Tx. SMC1 sshould be stopped if SCC3 eternet are used.
-        */
-       immap->im_cpm.cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
-       /* On the MPC885ADS SCC ethernet PHY is initialized in the full duplex mode
-        * by H/W setting after reset. SCC ethernet controller support only half duplex.
-        * This discrepancy of modes causes a lot of carrier lost errors.
-        */
-
-       /* In the original SCC enet driver the following code is placed at
-          the end of the initialization */
-       setbits32(&immap->im_cpm.cp_pepar, PE_ENET_TENA);
-       clrbits32(&immap->im_cpm.cp_pedir, PE_ENET_TENA);
-       setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA);
-
-       setbits32(bcsr_io+4, BCSR1_ETHEN);
-       iounmap(bcsr_io);
-}
-
-static int mac_count = 0;
-
-static void mpc885ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
-{
-       struct fs_platform_info *fpi;
-       bd_t *bd = (bd_t *) __res;
-       char *e;
-       int i;
-
-       if(fs_no >= ARRAY_SIZE(mpc8xx_enet_pdata)) {
-               printk(KERN_ERR"No network-suitable #%d device on bus", fs_no);
-               return;
-       }
-
-       fpi = &mpc8xx_enet_pdata[fs_no];
-
-       switch (fs_no) {
-       case fsid_fec1:
-               fpi->init_ioports = &setup_fec1_ioports;
-               break;
-       case fsid_fec2:
-               fpi->init_ioports = &setup_fec2_ioports;
-               break;
-       case fsid_scc3:
-               fpi->init_ioports = &setup_scc3_ioports;
-               break;
-       default:
-               printk(KERN_WARNING "Device %s is not supported!\n", pdev->name);
-               return;
-       }
-
-       pdev->dev.platform_data = fpi;
-       fpi->fs_no = fs_no;
-
-       e = (unsigned char *)&bd->bi_enetaddr;
-       for (i = 0; i < 6; i++)
-               fpi->macaddr[i] = *e++;
-
-       fpi->macaddr[5] += mac_count++;
-
-}
-
-static void mpc885ads_fixup_fec_enet_pdata(struct platform_device *pdev,
-                                          int idx)
-{
-       /* This is for FEC devices only */
-       if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
-               return;
-       mpc885ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
-}
-
-static void __init mpc885ads_fixup_scc_enet_pdata(struct platform_device *pdev,
-                                                 int idx)
-{
-       /* This is for SCC devices only */
-       if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
-               return;
-
-       mpc885ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
-}
-
-static void setup_smc1_ioports(struct fs_uart_platform_info* pdata)
-{
-        immap_t *immap = (immap_t *) IMAP_ADDR;
-        unsigned *bcsr_io;
-        unsigned int iobits = 0x000000c0;
-
-        bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-
-        if (bcsr_io == NULL) {
-                printk(KERN_CRIT "Could not remap BCSR1\n");
-                return;
-        }
-        clrbits32(bcsr_io,BCSR1_RS232EN_1);
-        iounmap(bcsr_io);
-
-        setbits32(&immap->im_cpm.cp_pbpar, iobits);
-        clrbits32(&immap->im_cpm.cp_pbdir, iobits);
-        clrbits16(&immap->im_cpm.cp_pbodr, iobits);
-}
-
-static void setup_smc2_ioports(struct fs_uart_platform_info* pdata)
-{
-        immap_t *immap = (immap_t *) IMAP_ADDR;
-        unsigned *bcsr_io;
-        unsigned int iobits = 0x00000c00;
-
-        bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-
-        if (bcsr_io == NULL) {
-                printk(KERN_CRIT "Could not remap BCSR1\n");
-                return;
-        }
-        clrbits32(bcsr_io,BCSR1_RS232EN_2);
-        iounmap(bcsr_io);
-
-#ifndef CONFIG_SERIAL_CPM_ALT_SMC2
-        setbits32(&immap->im_cpm.cp_pbpar, iobits);
-        clrbits32(&immap->im_cpm.cp_pbdir, iobits);
-        clrbits16(&immap->im_cpm.cp_pbodr, iobits);
-#else
-        setbits16(&immap->im_ioport.iop_papar, iobits);
-        clrbits16(&immap->im_ioport.iop_padir, iobits);
-        clrbits16(&immap->im_ioport.iop_paodr, iobits);
-#endif
-}
-
-static void __init mpc885ads_fixup_uart_pdata(struct platform_device *pdev,
-                                              int idx)
-{
-       bd_t *bd = (bd_t *) __res;
-       struct fs_uart_platform_info *pinfo;
-       int num = ARRAY_SIZE(mpc885_uart_pdata);
-
-       int id = fs_uart_id_smc2fsid(idx);
-
-       /* no need to alter anything if console */
-       if ((id < num) && (!pdev->dev.platform_data)) {
-               pinfo = &mpc885_uart_pdata[id];
-               pinfo->uart_clk = bd->bi_intfreq;
-               pdev->dev.platform_data = pinfo;
-       }
-}
-
-
-static int mpc885ads_platform_notify(struct device *dev)
-{
-
-       static const struct platform_notify_dev_map dev_map[] = {
-               {
-                       .bus_id = "fsl-cpm-fec",
-                       .rtn = mpc885ads_fixup_fec_enet_pdata,
-               },
-               {
-                       .bus_id = "fsl-cpm-scc",
-                       .rtn = mpc885ads_fixup_scc_enet_pdata,
-               },
-               {
-                       .bus_id = "fsl-cpm-smc:uart",
-                       .rtn = mpc885ads_fixup_uart_pdata
-               },
-               {
-                       .bus_id = NULL
-               }
-       };
-
-       platform_notify_map(dev_map,dev);
-
-       return 0;
-}
-
-int __init mpc885ads_init(void)
-{
-       struct fs_mii_fec_platform_info* fmpi;
-       bd_t *bd = (bd_t *) __res;
-
-       printk(KERN_NOTICE "mpc885ads: Init\n");
-
-       platform_notify = mpc885ads_platform_notify;
-
-       ppc_sys_device_initfunc();
-       ppc_sys_device_disable_all();
-
-       ppc_sys_device_enable(MPC8xx_CPM_FEC1);
-
-       ppc_sys_device_enable(MPC8xx_MDIO_FEC);
-       fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
-               &mpc8xx_mdio_fec_pdata;
-
-       fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
-
-       /* No PHY interrupt line here */
-       fmpi->irq[0xf] = SIU_IRQ7;
-
-#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3
-       ppc_sys_device_enable(MPC8xx_CPM_SCC3);
-
-#endif
-#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
-       ppc_sys_device_enable(MPC8xx_CPM_FEC2);
-#endif
-
-#ifdef CONFIG_SERIAL_CPM_SMC1
-       ppc_sys_device_enable(MPC8xx_CPM_SMC1);
-       ppc_sys_device_setfunc(MPC8xx_CPM_SMC1, PPC_SYS_FUNC_UART);
-#endif
-
-#ifdef CONFIG_SERIAL_CPM_SMC2
-       ppc_sys_device_enable(MPC8xx_CPM_SMC2);
-       ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
-#endif
-       return 0;
-}
-
-arch_initcall(mpc885ads_init);
-
-/*
-   To prevent confusion, console selection is gross:
-   by 0 assumed SMC1 and by 1 assumed SMC2
- */
-struct platform_device* early_uart_get_pdev(int index)
-{
-       bd_t *bd = (bd_t *) __res;
-       struct fs_uart_platform_info *pinfo;
-
-       struct platform_device* pdev = NULL;
-       if(index) { /*assume SMC2 here*/
-               pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC2];
-               pinfo = &mpc885_uart_pdata[1];
-       } else { /*over SMC1*/
-               pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC1];
-               pinfo = &mpc885_uart_pdata[0];
-       }
-
-       pinfo->uart_clk = bd->bi_intfreq;
-       pdev->dev.platform_data = pinfo;
-       ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR);
-       return NULL;
-}
-
diff --git a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c
deleted file mode 100644 (file)
index 7fc2e02..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * PQ2ADS platform support
- *
- * Author: Kumar Gala <galak@kernel.crashing.org>
- * Derived from: est8260_setup.c by Allen Curtis
- *
- * Copyright 2004 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/mpc8260.h>
-#include <asm/cpm2.h>
-#include <asm/immap_cpm2.h>
-
-void __init
-m82xx_board_setup(void)
-{
-       cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
-       u32 *bcsr = ioremap(BCSR_ADDR+4, sizeof(u32));
-
-       /* Enable the 2nd UART port */
-       clrbits32(bcsr, BCSR1_RS232_EN2);
-
-#ifdef CONFIG_SERIAL_CPM_SCC1
-       clrbits32((u32*)&immap->im_scc[0].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
-       clrbits32((u32*)&immap->im_scc[0].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-#endif
-
-#ifdef CONFIG_SERIAL_CPM_SCC2
-       clrbits32((u32*)&immap->im_scc[1].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
-       clrbits32((u32*)&immap->im_scc[1].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-#endif
-
-#ifdef CONFIG_SERIAL_CPM_SCC3
-       clrbits32((u32*)&immap->im_scc[2].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
-       clrbits32((u32*)&immap->im_scc[2].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-#endif
-
-#ifdef CONFIG_SERIAL_CPM_SCC4
-       clrbits32((u32*)&immap->im_scc[3].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
-       clrbits32((u32*)&immap->im_scc[3].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-#endif
-
-       iounmap(bcsr);
-       iounmap(immap);
-}
diff --git a/arch/ppc/platforms/pq2ads.h b/arch/ppc/platforms/pq2ads.h
deleted file mode 100644 (file)
index 2b287f4..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * A collection of structures, addresses, and values associated with
- * the Motorola MPC8260ADS/MPC8266ADS-PCI boards.
- * Copied from the RPX-Classic and SBS8260 stuff.
- *
- * Copyright (c) 2001 Dan Malek (dan@mvista.com)
- */
-#ifdef __KERNEL__
-#ifndef __MACH_ADS8260_DEFS
-#define __MACH_ADS8260_DEFS
-
-
-#include <asm/ppcboot.h>
-
-#if defined(CONFIG_ADS8272)
-#define BOARD_CHIP_NAME "8272"
-#endif
-
-/* Memory map is configured by the PROM startup.
- * We just map a few things we need.  The CSR is actually 4 byte-wide
- * registers that can be accessed as 8-, 16-, or 32-bit values.
- */
-#define CPM_MAP_ADDR           ((uint)0xf0000000)
-#define BCSR_ADDR              ((uint)0xf4500000)
-#define BCSR_SIZE              ((uint)(32 * 1024))
-
-#define BOOTROM_RESTART_ADDR   ((uint)0xff000104)
-
-/* For our show_cpuinfo hooks. */
-#define CPUINFO_VENDOR         "Motorola"
-#define CPUINFO_MACHINE                "PQ2 ADS PowerPC"
-
-/* The ADS8260 has 16, 32-bit wide control/status registers, accessed
- * only on word boundaries.
- * Not all are used (yet), or are interesting to us (yet).
- */
-
-/* Things of interest in the CSR.
-*/
-#define BCSR0_LED0             ((uint)0x02000000)      /* 0 == on */
-#define BCSR0_LED1             ((uint)0x01000000)      /* 0 == on */
-#define BCSR1_FETHIEN          ((uint)0x08000000)      /* 0 == enable */
-#define BCSR1_FETH_RST         ((uint)0x04000000)      /* 0 == reset */
-#define BCSR1_RS232_EN1                ((uint)0x02000000)      /* 0 == enable */
-#define BCSR1_RS232_EN2                ((uint)0x01000000)      /* 0 == enable */
-#define BCSR3_FETHIEN2         ((uint)0x10000000)      /* 0 == enable */
-#define BCSR3_FETH2_RST        ((uint)0x80000000)      /* 0 == reset */
-
-#define PHY_INTERRUPT  SIU_INT_IRQ7
-
-#ifdef CONFIG_PCI
-/* PCI interrupt controller */
-#define PCI_INT_STAT_REG       0xF8200000
-#define PCI_INT_MASK_REG       0xF8200004
-#define PIRQA                  (NR_CPM_INTS + 0)
-#define PIRQB                  (NR_CPM_INTS + 1)
-#define PIRQC                  (NR_CPM_INTS + 2)
-#define PIRQD                  (NR_CPM_INTS + 3)
-
-/*
- * PCI memory map definitions for MPC8266ADS-PCI.
- *
- * processor view
- *     local address           PCI address             target
- *     0x80000000-0x9FFFFFFF   0x80000000-0x9FFFFFFF   PCI mem with prefetch
- *     0xA0000000-0xBFFFFFFF   0xA0000000-0xBFFFFFFF   PCI mem w/o prefetch
- *     0xF4000000-0xF7FFFFFF   0x00000000-0x03FFFFFF   PCI IO
- *
- * PCI master view
- *     local address           PCI address             target
- *     0x00000000-0x1FFFFFFF   0x00000000-0x1FFFFFFF   MPC8266 local memory
- */
-
-/* All the other PCI memory map definitions reside at syslib/m82xx_pci.h
-   Here we should redefine what is unique for this board */
-#define M82xx_PCI_SLAVE_MEM_LOCAL      0x00000000      /* Local base */
-#define M82xx_PCI_SLAVE_MEM_BUS                0x00000000      /* PCI base */
-#define M82xx_PCI_SLAVE_MEM_SIZE       0x10000000      /* 256 Mb */
-
-#define M82xx_PCI_SLAVE_SEC_WND_SIZE   ~(0x40000000 - 1U)      /* 2 x 512Mb  */
-#define M82xx_PCI_SLAVE_SEC_WND_BASE   0x80000000              /* PCI Memory base */
-
-#if defined(CONFIG_ADS8272)
-#define PCI_INT_TO_SIU         SIU_INT_IRQ2
-#elif defined(CONFIG_PQ2FADS)
-#define PCI_INT_TO_SIU         SIU_INT_IRQ6
-#else
-#warning PCI Bridge will be without interrupts support
-#endif
-
-#endif /* CONFIG_PCI */
-
-#endif /* __MACH_ADS8260_DEFS */
-#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/pq2ads_pd.h b/arch/ppc/platforms/pq2ads_pd.h
deleted file mode 100644 (file)
index 672483d..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef __PQ2ADS_PD_H
-#define __PQ2ADS_PD_H
-/*
- * arch/ppc/platforms/82xx/pq2ads_pd.h
- *
- * Some defines for MPC82xx board-specific PlatformDevice descriptions
- *
- * 2005 (c) MontaVista Software, Inc.
- * Vitaly Bordug <vbordug@ru.mvista.com>
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-/* FCC1 Clock Source Configuration.  These can be redefined in the board specific file.
-   Can only choose from CLK9-12 */
-
-#define F1_RXCLK       11
-#define F1_TXCLK       10
-
-/* FCC2 Clock Source Configuration.  These can be redefined in the board specific file.
-   Can only choose from CLK13-16 */
-#define F2_RXCLK       15
-#define F2_TXCLK       16
-
-/* FCC3 Clock Source Configuration.  These can be redefined in the board specific file.
-   Can only choose from CLK13-16 */
-#define F3_RXCLK       13
-#define F3_TXCLK       14
-
-#endif
index 46588fa9438139657fc04f188d8ca258e27c5f39..b40583724de3459b2e992b0f6bf2e3fa04033049 100644 (file)
@@ -175,12 +175,6 @@ m8260_init_IRQ(void)
         * in case the boot rom changed something on us.
         */
        cpm2_immr->im_intctl.ic_siprr = 0x05309770;
-
-#if defined(CONFIG_PCI) && (defined(CONFIG_ADS8272) || defined(CONFIG_PQ2FADS))
-       /* Initialize stuff for the 82xx CPLD IC and install demux  */
-       pq2pci_init_irq();
-#endif
-
 }
 
 /*
index fe860d52e2e4c1e3d6a2c2a9cc41fe96bb98e519..657a1c25a2abad7d31e1776fc638530b6746c0aa 100644 (file)
@@ -150,14 +150,6 @@ pq2pci_init_irq(void)
 {
        int irq;
        volatile cpm2_map_t *immap = cpm2_immr;
-#if defined CONFIG_ADS8272
-       /* configure chip select for PCI interrupt controller */
-       immap->im_memctl.memc_br3 = PCI_INT_STAT_REG | 0x00001801;
-       immap->im_memctl.memc_or3 = 0xffff8010;
-#elif defined CONFIG_PQ2FADS
-       immap->im_memctl.memc_br8 = PCI_INT_STAT_REG | 0x00001801;
-       immap->im_memctl.memc_or8 = 0xffff8010;
-#endif
        for (irq = NR_CPM_INTS; irq < NR_CPM_INTS + 4; irq++)
                irq_desc[irq].chip = &pq2pci_ic;
 
@@ -222,26 +214,6 @@ pq2ads_setup_pci(struct pci_controller *hose)
        immap->im_memctl.memc_pcibr1  = M82xx_PCI_SEC_WND_BASE | PCIBR_ENABLE;
 #endif
 
-#if defined CONFIG_ADS8272
-       immap->im_siu_conf.siu_82xx.sc_siumcr =
-               (immap->im_siu_conf.siu_82xx.sc_siumcr &
-               ~(SIUMCR_BBD | SIUMCR_ESE | SIUMCR_PBSE |
-               SIUMCR_CDIS | SIUMCR_DPPC11 | SIUMCR_L2CPC11 |
-               SIUMCR_LBPC11 | SIUMCR_APPC11 |
-               SIUMCR_CS10PC11 | SIUMCR_BCTLC11 | SIUMCR_MMR11)) |
-               SIUMCR_DPPC11 | SIUMCR_L2CPC01 | SIUMCR_LBPC00 |
-               SIUMCR_APPC10 | SIUMCR_CS10PC00 |
-               SIUMCR_BCTLC00 | SIUMCR_MMR11 ;
-
-#elif defined CONFIG_PQ2FADS
-       /*
-        * Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]),
-        * and local bus for PCI (SIUMCR [LBPC]).
-        */
-       immap->im_siu_conf.siu_82xx.sc_siumcr = (immap->im_siu_conf.siu_82xx.sc_siumcr &
-                               ~(SIUMCR_L2CPC11 | SIUMCR_LBPC11 | SIUMCR_CS10PC11 | SIUMCR_APPC11) |
-                               SIUMCR_BBD | SIUMCR_LBPC01 | SIUMCR_DPPC11 | SIUMCR_APPC10);
-#endif
        /* Enable PCI  */
        immap->im_pci.pci_gcr = cpu_to_le32(PCIGCR_PCI_BUS_EN);
 
@@ -284,12 +256,6 @@ pq2ads_setup_pci(struct pci_controller *hose)
        immap->im_pci.pci_pibar0 = cpu_to_le32(M82xx_PCI_SLAVE_MEM_BUS  >> PITA_ADDR_SHIFT);
        immap->im_pci.pci_pitar0 = cpu_to_le32(M82xx_PCI_SLAVE_MEM_LOCAL>> PITA_ADDR_SHIFT);
 
-#if defined CONFIG_ADS8272
-       /* PCI int highest prio */
-       immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x01236745;
-#elif defined CONFIG_PQ2FADS
-       immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x03124567;
-#endif
        /* park bus on PCI */
        immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI;
 
@@ -320,10 +286,6 @@ void __init pq2_find_bridges(void)
        hose->bus_offset = 0;
        hose->last_busno = 0xff;
 
-#ifdef CONFIG_ADS8272
-       hose->set_cfg_type = 1;
-#endif
-
        setup_m8260_indirect_pci(hose,
                                 (unsigned long)&cpm2_immr->im_pci.pci_cfg_addr,
                                 (unsigned long)&cpm2_immr->im_pci.pci_cfg_data);
index 19749e9bcf91f3f3e382455b7d8a6648d3d2dc42..18da720fc1b0efca76b36f883012d99a26e753d5 100644 (file)
@@ -139,16 +139,6 @@ m8xx_setup_arch(void)
                }
        }
 #endif
-#endif
-
-#if defined (CONFIG_MPC86XADS) || defined (CONFIG_MPC885ADS)
-#if defined(CONFIG_MTD_PHYSMAP)
-       physmap_configure(binfo->bi_flashstart, binfo->bi_flashsize,
-                                               MPC8xxADS_BANK_WIDTH, NULL);
-#ifdef CONFIG_MTD_PARTITIONS
-       physmap_set_partitions(mpc8xxads_partitions, mpc8xxads_part_num);
-#endif /* CONFIG_MTD_PARTITIONS */
-#endif /* CONFIG_MTD_PHYSMAP */
 #endif
 
        board_init();
index f6a68e178fc52952f31e4e95e7123af44252a919..8f5f02160ffcef2d57c458790537456ee3c06626 100644 (file)
@@ -62,6 +62,10 @@ config GENERIC_LOCKBREAK
        default y
        depends on SMP && PREEMPT
 
+config PGSTE
+       bool
+       default y if KVM
+
 mainmenu "Linux Kernel Configuration"
 
 config S390
@@ -69,6 +73,7 @@ config S390
        select HAVE_OPROFILE
        select HAVE_KPROBES
        select HAVE_KRETPROBES
+       select HAVE_KVM if 64BIT
 
 source "init/Kconfig"
 
@@ -515,6 +520,13 @@ config ZFCPDUMP
          Select this option if you want to build an zfcpdump enabled kernel.
          Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this.
 
+config S390_GUEST
+bool "s390 guest support (EXPERIMENTAL)"
+       depends on 64BIT && EXPERIMENTAL
+       select VIRTIO
+       select VIRTIO_RING
+       help
+         Select this option if you want to run the kernel under s390 linux
 endmenu
 
 source "net/Kconfig"
@@ -536,3 +548,5 @@ source "security/Kconfig"
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
+
+source "arch/s390/kvm/Kconfig"
index f708be367b030b672ffe58684e20fbcebc90c77a..792a4e7743cee19ef0b41d4b896d104df48aa73e 100644 (file)
@@ -87,7 +87,7 @@ LDFLAGS_vmlinux := -e start
 head-y         := arch/s390/kernel/head.o arch/s390/kernel/init_task.o
 
 core-y         += arch/s390/mm/ arch/s390/kernel/ arch/s390/crypto/ \
-                  arch/s390/appldata/ arch/s390/hypfs/
+                  arch/s390/appldata/ arch/s390/hypfs/ arch/s390/kvm/
 libs-y         += arch/s390/lib/
 drivers-y      += drivers/s390/
 drivers-$(CONFIG_MATHEMU) += arch/s390/math-emu/
index 540a67f979b64820e4b45319451b1e3897ebb0e0..68ec4083bf73910641d32334494c809318ae7c17 100644 (file)
@@ -144,6 +144,10 @@ static noinline __init void detect_machine_type(void)
        /* Running on a P/390 ? */
        if (cpuinfo->cpu_id.machine == 0x7490)
                machine_flags |= 4;
+
+       /* Running under KVM ? */
+       if (cpuinfo->cpu_id.version == 0xfe)
+               machine_flags |= 64;
 }
 
 #ifdef CONFIG_64BIT
index 7141147e6b639a2035e4542c167ac7d8a3b50c59..a9d18aafa5f47f610db88996985270c1bda30f35 100644 (file)
@@ -316,7 +316,11 @@ static int __init early_parse_ipldelay(char *p)
 early_param("ipldelay", early_parse_ipldelay);
 
 #ifdef CONFIG_S390_SWITCH_AMODE
+#ifdef CONFIG_PGSTE
+unsigned int switch_amode = 1;
+#else
 unsigned int switch_amode = 0;
+#endif
 EXPORT_SYMBOL_GPL(switch_amode);
 
 static void set_amode_and_uaccess(unsigned long user_amode,
@@ -797,9 +801,13 @@ setup_arch(char **cmdline_p)
               "This machine has an IEEE fpu\n" :
               "This machine has no IEEE fpu\n");
 #else /* CONFIG_64BIT */
-       printk((MACHINE_IS_VM) ?
-              "We are running under VM (64 bit mode)\n" :
-              "We are running native (64 bit mode)\n");
+       if (MACHINE_IS_VM)
+               printk("We are running under VM (64 bit mode)\n");
+       else if (MACHINE_IS_KVM) {
+               printk("We are running under KVM (64 bit mode)\n");
+               add_preferred_console("ttyS", 1, NULL);
+       } else
+               printk("We are running native (64 bit mode)\n");
 #endif /* CONFIG_64BIT */
 
        /* Save unparsed command line copy for /proc/cmdline */
index c5f05b3fb2c30f1548a062280be08fc12411340d..ca90ee3f930edc0ffc364d8a094826df731b3415 100644 (file)
@@ -110,6 +110,7 @@ void account_system_vtime(struct task_struct *tsk)
        S390_lowcore.steal_clock -= cputime << 12;
        account_system_time(tsk, 0, cputime);
 }
+EXPORT_SYMBOL_GPL(account_system_vtime);
 
 static inline void set_vtimer(__u64 expires)
 {
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
new file mode 100644 (file)
index 0000000..1761b74
--- /dev/null
@@ -0,0 +1,46 @@
+#
+# KVM configuration
+#
+config HAVE_KVM
+       bool
+
+menuconfig VIRTUALIZATION
+       bool "Virtualization"
+       default y
+       ---help---
+         Say Y here to get to see options for using your Linux host to run other
+         operating systems inside virtual machines (guests).
+         This option alone does not add any kernel code.
+
+         If you say N, all options in this submenu will be skipped and disabled.
+
+if VIRTUALIZATION
+
+config KVM
+       tristate "Kernel-based Virtual Machine (KVM) support"
+       depends on HAVE_KVM && EXPERIMENTAL
+       select PREEMPT_NOTIFIERS
+       select ANON_INODES
+       select S390_SWITCH_AMODE
+       select PREEMPT
+       ---help---
+         Support hosting paravirtualized guest machines using the SIE
+         virtualization capability on the mainframe. This should work
+         on any 64bit machine.
+
+         This module provides access to the hardware capabilities through
+         a character device node named /dev/kvm.
+
+         To compile this as a module, choose M here: the module
+         will be called kvm.
+
+         If unsure, say N.
+
+config KVM_TRACE
+       bool
+
+# OK, it's a little counter-intuitive to do this, but it puts it neatly under
+# the virtualization menu.
+source drivers/virtio/Kconfig
+
+endif # VIRTUALIZATION
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile
new file mode 100644 (file)
index 0000000..e5221ec
--- /dev/null
@@ -0,0 +1,14 @@
+# Makefile for kernel virtual machines on s390
+#
+# Copyright IBM Corp. 2008
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License (version 2 only)
+# as published by the Free Software Foundation.
+
+common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o)
+
+EXTRA_CFLAGS += -Ivirt/kvm -Iarch/s390/kvm
+
+kvm-objs := $(common-objs) kvm-s390.o sie64a.o intercept.o interrupt.o priv.o sigp.o diag.o
+obj-$(CONFIG_KVM) += kvm.o
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c
new file mode 100644 (file)
index 0000000..f639a15
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * diag.c - handling diagnose instructions
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Carsten Otte <cotte@de.ibm.com>
+ *               Christian Borntraeger <borntraeger@de.ibm.com>
+ */
+
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include "kvm-s390.h"
+
+static int __diag_time_slice_end(struct kvm_vcpu *vcpu)
+{
+       VCPU_EVENT(vcpu, 5, "%s", "diag time slice end");
+       vcpu->stat.diagnose_44++;
+       vcpu_put(vcpu);
+       schedule();
+       vcpu_load(vcpu);
+       return 0;
+}
+
+static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
+{
+       unsigned int reg = vcpu->arch.sie_block->ipa & 0xf;
+       unsigned long subcode = vcpu->arch.guest_gprs[reg] & 0xffff;
+
+       VCPU_EVENT(vcpu, 5, "diag ipl functions, subcode %lx", subcode);
+       switch (subcode) {
+       case 3:
+               vcpu->run->s390_reset_flags = KVM_S390_RESET_CLEAR;
+               break;
+       case 4:
+               vcpu->run->s390_reset_flags = 0;
+               break;
+       default:
+               return -ENOTSUPP;
+       }
+
+       atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
+       vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM;
+       vcpu->run->s390_reset_flags |= KVM_S390_RESET_IPL;
+       vcpu->run->s390_reset_flags |= KVM_S390_RESET_CPU_INIT;
+       vcpu->run->exit_reason = KVM_EXIT_S390_RESET;
+       VCPU_EVENT(vcpu, 3, "requesting userspace resets %lx",
+         vcpu->run->s390_reset_flags);
+       return -EREMOTE;
+}
+
+int kvm_s390_handle_diag(struct kvm_vcpu *vcpu)
+{
+       int code = (vcpu->arch.sie_block->ipb & 0xfff0000) >> 16;
+
+       switch (code) {
+       case 0x44:
+               return __diag_time_slice_end(vcpu);
+       case 0x308:
+               return __diag_ipl_functions(vcpu);
+       default:
+               return -ENOTSUPP;
+       }
+}
diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h
new file mode 100644 (file)
index 0000000..4e0633c
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * gaccess.h -  access guest memory
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Carsten Otte <cotte@de.ibm.com>
+ */
+
+#ifndef __KVM_S390_GACCESS_H
+#define __KVM_S390_GACCESS_H
+
+#include <linux/compiler.h>
+#include <linux/kvm_host.h>
+#include <asm/uaccess.h>
+
+static inline void __user *__guestaddr_to_user(struct kvm_vcpu *vcpu,
+                                              u64 guestaddr)
+{
+       u64 prefix  = vcpu->arch.sie_block->prefix;
+       u64 origin  = vcpu->kvm->arch.guest_origin;
+       u64 memsize = vcpu->kvm->arch.guest_memsize;
+
+       if (guestaddr < 2 * PAGE_SIZE)
+               guestaddr += prefix;
+       else if ((guestaddr >= prefix) && (guestaddr < prefix + 2 * PAGE_SIZE))
+               guestaddr -= prefix;
+
+       if (guestaddr > memsize)
+               return (void __user __force *) ERR_PTR(-EFAULT);
+
+       guestaddr += origin;
+
+       return (void __user *) guestaddr;
+}
+
+static inline int get_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
+                               u64 *result)
+{
+       void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
+
+       BUG_ON(guestaddr & 7);
+
+       if (IS_ERR((void __force *) uptr))
+               return PTR_ERR((void __force *) uptr);
+
+       return get_user(*result, (u64 __user *) uptr);
+}
+
+static inline int get_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
+                               u32 *result)
+{
+       void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
+
+       BUG_ON(guestaddr & 3);
+
+       if (IS_ERR((void __force *) uptr))
+               return PTR_ERR((void __force *) uptr);
+
+       return get_user(*result, (u32 __user *) uptr);
+}
+
+static inline int get_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
+                               u16 *result)
+{
+       void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
+
+       BUG_ON(guestaddr & 1);
+
+       if (IS_ERR(uptr))
+               return PTR_ERR(uptr);
+
+       return get_user(*result, (u16 __user *) uptr);
+}
+
+static inline int get_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
+                              u8 *result)
+{
+       void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
+
+       if (IS_ERR((void __force *) uptr))
+               return PTR_ERR((void __force *) uptr);
+
+       return get_user(*result, (u8 __user *) uptr);
+}
+
+static inline int put_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
+                               u64 value)
+{
+       void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
+
+       BUG_ON(guestaddr & 7);
+
+       if (IS_ERR((void __force *) uptr))
+               return PTR_ERR((void __force *) uptr);
+
+       return put_user(value, (u64 __user *) uptr);
+}
+
+static inline int put_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
+                               u32 value)
+{
+       void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
+
+       BUG_ON(guestaddr & 3);
+
+       if (IS_ERR((void __force *) uptr))
+               return PTR_ERR((void __force *) uptr);
+
+       return put_user(value, (u32 __user *) uptr);
+}
+
+static inline int put_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
+                               u16 value)
+{
+       void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
+
+       BUG_ON(guestaddr & 1);
+
+       if (IS_ERR((void __force *) uptr))
+               return PTR_ERR((void __force *) uptr);
+
+       return put_user(value, (u16 __user *) uptr);
+}
+
+static inline int put_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
+                              u8 value)
+{
+       void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
+
+       if (IS_ERR((void __force *) uptr))
+               return PTR_ERR((void __force *) uptr);
+
+       return put_user(value, (u8 __user *) uptr);
+}
+
+
+static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu, u64 guestdest,
+                                      const void *from, unsigned long n)
+{
+       int rc;
+       unsigned long i;
+       const u8 *data = from;
+
+       for (i = 0; i < n; i++) {
+               rc = put_guest_u8(vcpu, guestdest++, *(data++));
+               if (rc < 0)
+                       return rc;
+       }
+       return 0;
+}
+
+static inline int copy_to_guest(struct kvm_vcpu *vcpu, u64 guestdest,
+                               const void *from, unsigned long n)
+{
+       u64 prefix  = vcpu->arch.sie_block->prefix;
+       u64 origin  = vcpu->kvm->arch.guest_origin;
+       u64 memsize = vcpu->kvm->arch.guest_memsize;
+
+       if ((guestdest < 2 * PAGE_SIZE) && (guestdest + n > 2 * PAGE_SIZE))
+               goto slowpath;
+
+       if ((guestdest < prefix) && (guestdest + n > prefix))
+               goto slowpath;
+
+       if ((guestdest < prefix + 2 * PAGE_SIZE)
+           && (guestdest + n > prefix + 2 * PAGE_SIZE))
+               goto slowpath;
+
+       if (guestdest < 2 * PAGE_SIZE)
+               guestdest += prefix;
+       else if ((guestdest >= prefix) && (guestdest < prefix + 2 * PAGE_SIZE))
+               guestdest -= prefix;
+
+       if (guestdest + n > memsize)
+               return -EFAULT;
+
+       if (guestdest + n < guestdest)
+               return -EFAULT;
+
+       guestdest += origin;
+
+       return copy_to_user((void __user *) guestdest, from, n);
+slowpath:
+       return __copy_to_guest_slow(vcpu, guestdest, from, n);
+}
+
+static inline int __copy_from_guest_slow(struct kvm_vcpu *vcpu, void *to,
+                                        u64 guestsrc, unsigned long n)
+{
+       int rc;
+       unsigned long i;
+       u8 *data = to;
+
+       for (i = 0; i < n; i++) {
+               rc = get_guest_u8(vcpu, guestsrc++, data++);
+               if (rc < 0)
+                       return rc;
+       }
+       return 0;
+}
+
+static inline int copy_from_guest(struct kvm_vcpu *vcpu, void *to,
+                                 u64 guestsrc, unsigned long n)
+{
+       u64 prefix  = vcpu->arch.sie_block->prefix;
+       u64 origin  = vcpu->kvm->arch.guest_origin;
+       u64 memsize = vcpu->kvm->arch.guest_memsize;
+
+       if ((guestsrc < 2 * PAGE_SIZE) && (guestsrc + n > 2 * PAGE_SIZE))
+               goto slowpath;
+
+       if ((guestsrc < prefix) && (guestsrc + n > prefix))
+               goto slowpath;
+
+       if ((guestsrc < prefix + 2 * PAGE_SIZE)
+           && (guestsrc + n > prefix + 2 * PAGE_SIZE))
+               goto slowpath;
+
+       if (guestsrc < 2 * PAGE_SIZE)
+               guestsrc += prefix;
+       else if ((guestsrc >= prefix) && (guestsrc < prefix + 2 * PAGE_SIZE))
+               guestsrc -= prefix;
+
+       if (guestsrc + n > memsize)
+               return -EFAULT;
+
+       if (guestsrc + n < guestsrc)
+               return -EFAULT;
+
+       guestsrc += origin;
+
+       return copy_from_user(to, (void __user *) guestsrc, n);
+slowpath:
+       return __copy_from_guest_slow(vcpu, to, guestsrc, n);
+}
+
+static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu, u64 guestdest,
+                                        const void *from, unsigned long n)
+{
+       u64 origin  = vcpu->kvm->arch.guest_origin;
+       u64 memsize = vcpu->kvm->arch.guest_memsize;
+
+       if (guestdest + n > memsize)
+               return -EFAULT;
+
+       if (guestdest + n < guestdest)
+               return -EFAULT;
+
+       guestdest += origin;
+
+       return copy_to_user((void __user *) guestdest, from, n);
+}
+
+static inline int copy_from_guest_absolute(struct kvm_vcpu *vcpu, void *to,
+                                          u64 guestsrc, unsigned long n)
+{
+       u64 origin  = vcpu->kvm->arch.guest_origin;
+       u64 memsize = vcpu->kvm->arch.guest_memsize;
+
+       if (guestsrc + n > memsize)
+               return -EFAULT;
+
+       if (guestsrc + n < guestsrc)
+               return -EFAULT;
+
+       guestsrc += origin;
+
+       return copy_from_user(to, (void __user *) guestsrc, n);
+}
+#endif
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
new file mode 100644 (file)
index 0000000..349581a
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * intercept.c - in-kernel handling for sie intercepts
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Carsten Otte <cotte@de.ibm.com>
+ *               Christian Borntraeger <borntraeger@de.ibm.com>
+ */
+
+#include <linux/kvm_host.h>
+#include <linux/errno.h>
+#include <linux/pagemap.h>
+
+#include <asm/kvm_host.h>
+
+#include "kvm-s390.h"
+#include "gaccess.h"
+
+static int handle_lctg(struct kvm_vcpu *vcpu)
+{
+       int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
+       int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
+       int base2 = vcpu->arch.sie_block->ipb >> 28;
+       int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16) +
+                       ((vcpu->arch.sie_block->ipb & 0xff00) << 4);
+       u64 useraddr;
+       int reg, rc;
+
+       vcpu->stat.instruction_lctg++;
+       if ((vcpu->arch.sie_block->ipb & 0xff) != 0x2f)
+               return -ENOTSUPP;
+
+       useraddr = disp2;
+       if (base2)
+               useraddr += vcpu->arch.guest_gprs[base2];
+
+       reg = reg1;
+
+       VCPU_EVENT(vcpu, 5, "lctg r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
+                  disp2);
+
+       do {
+               rc = get_guest_u64(vcpu, useraddr,
+                                  &vcpu->arch.sie_block->gcr[reg]);
+               if (rc == -EFAULT) {
+                       kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+                       break;
+               }
+               useraddr += 8;
+               if (reg == reg3)
+                       break;
+               reg = (reg + 1) % 16;
+       } while (1);
+       return 0;
+}
+
+static int handle_lctl(struct kvm_vcpu *vcpu)
+{
+       int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
+       int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
+       int base2 = vcpu->arch.sie_block->ipb >> 28;
+       int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
+       u64 useraddr;
+       u32 val = 0;
+       int reg, rc;
+
+       vcpu->stat.instruction_lctl++;
+
+       useraddr = disp2;
+       if (base2)
+               useraddr += vcpu->arch.guest_gprs[base2];
+
+       VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
+                  disp2);
+
+       reg = reg1;
+       do {
+               rc = get_guest_u32(vcpu, useraddr, &val);
+               if (rc == -EFAULT) {
+                       kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+                       break;
+               }
+               vcpu->arch.sie_block->gcr[reg] &= 0xffffffff00000000ul;
+               vcpu->arch.sie_block->gcr[reg] |= val;
+               useraddr += 4;
+               if (reg == reg3)
+                       break;
+               reg = (reg + 1) % 16;
+       } while (1);
+       return 0;
+}
+
+static intercept_handler_t instruction_handlers[256] = {
+       [0x83] = kvm_s390_handle_diag,
+       [0xae] = kvm_s390_handle_sigp,
+       [0xb2] = kvm_s390_handle_priv,
+       [0xb7] = handle_lctl,
+       [0xeb] = handle_lctg,
+};
+
+static int handle_noop(struct kvm_vcpu *vcpu)
+{
+       switch (vcpu->arch.sie_block->icptcode) {
+       case 0x10:
+               vcpu->stat.exit_external_request++;
+               break;
+       case 0x14:
+               vcpu->stat.exit_external_interrupt++;
+               break;
+       default:
+               break; /* nothing */
+       }
+       return 0;
+}
+
+static int handle_stop(struct kvm_vcpu *vcpu)
+{
+       int rc;
+
+       vcpu->stat.exit_stop_request++;
+       atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
+       spin_lock_bh(&vcpu->arch.local_int.lock);
+       if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) {
+               vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP;
+               rc = __kvm_s390_vcpu_store_status(vcpu,
+                                                 KVM_S390_STORE_STATUS_NOADDR);
+               if (rc >= 0)
+                       rc = -ENOTSUPP;
+       }
+
+       if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) {
+               vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP;
+               VCPU_EVENT(vcpu, 3, "%s", "cpu stopped");
+               rc = -ENOTSUPP;
+       } else
+               rc = 0;
+       spin_unlock_bh(&vcpu->arch.local_int.lock);
+       return rc;
+}
+
+static int handle_validity(struct kvm_vcpu *vcpu)
+{
+       int viwhy = vcpu->arch.sie_block->ipb >> 16;
+       vcpu->stat.exit_validity++;
+       if (viwhy == 0x37) {
+               fault_in_pages_writeable((char __user *)
+                                        vcpu->kvm->arch.guest_origin +
+                                        vcpu->arch.sie_block->prefix,
+                                        PAGE_SIZE);
+               return 0;
+       }
+       VCPU_EVENT(vcpu, 2, "unhandled validity intercept code %d",
+                  viwhy);
+       return -ENOTSUPP;
+}
+
+static int handle_instruction(struct kvm_vcpu *vcpu)
+{
+       intercept_handler_t handler;
+
+       vcpu->stat.exit_instruction++;
+       handler = instruction_handlers[vcpu->arch.sie_block->ipa >> 8];
+       if (handler)
+               return handler(vcpu);
+       return -ENOTSUPP;
+}
+
+static int handle_prog(struct kvm_vcpu *vcpu)
+{
+       vcpu->stat.exit_program_interruption++;
+       return kvm_s390_inject_program_int(vcpu, vcpu->arch.sie_block->iprcc);
+}
+
+static int handle_instruction_and_prog(struct kvm_vcpu *vcpu)
+{
+       int rc, rc2;
+
+       vcpu->stat.exit_instr_and_program++;
+       rc = handle_instruction(vcpu);
+       rc2 = handle_prog(vcpu);
+
+       if (rc == -ENOTSUPP)
+               vcpu->arch.sie_block->icptcode = 0x04;
+       if (rc)
+               return rc;
+       return rc2;
+}
+
+static const intercept_handler_t intercept_funcs[0x48 >> 2] = {
+       [0x00 >> 2] = handle_noop,
+       [0x04 >> 2] = handle_instruction,
+       [0x08 >> 2] = handle_prog,
+       [0x0C >> 2] = handle_instruction_and_prog,
+       [0x10 >> 2] = handle_noop,
+       [0x14 >> 2] = handle_noop,
+       [0x1C >> 2] = kvm_s390_handle_wait,
+       [0x20 >> 2] = handle_validity,
+       [0x28 >> 2] = handle_stop,
+};
+
+int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)
+{
+       intercept_handler_t func;
+       u8 code = vcpu->arch.sie_block->icptcode;
+
+       if (code & 3 || code > 0x48)
+               return -ENOTSUPP;
+       func = intercept_funcs[code >> 2];
+       if (func)
+               return func(vcpu);
+       return -ENOTSUPP;
+}
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
new file mode 100644 (file)
index 0000000..fcd1ed8
--- /dev/null
@@ -0,0 +1,592 @@
+/*
+ * interrupt.c - handling kvm guest interrupts
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Carsten Otte <cotte@de.ibm.com>
+ */
+
+#include <asm/lowcore.h>
+#include <asm/uaccess.h>
+#include <linux/kvm_host.h>
+#include "kvm-s390.h"
+#include "gaccess.h"
+
+static int psw_extint_disabled(struct kvm_vcpu *vcpu)
+{
+       return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_EXT);
+}
+
+static int psw_interrupts_disabled(struct kvm_vcpu *vcpu)
+{
+       if ((vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PER) ||
+           (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_IO) ||
+           (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_EXT))
+               return 0;
+       return 1;
+}
+
+static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu,
+                                     struct interrupt_info *inti)
+{
+       switch (inti->type) {
+       case KVM_S390_INT_EMERGENCY:
+               if (psw_extint_disabled(vcpu))
+                       return 0;
+               if (vcpu->arch.sie_block->gcr[0] & 0x4000ul)
+                       return 1;
+               return 0;
+       case KVM_S390_INT_SERVICE:
+               if (psw_extint_disabled(vcpu))
+                       return 0;
+               if (vcpu->arch.sie_block->gcr[0] & 0x200ul)
+                       return 1;
+               return 0;
+       case KVM_S390_INT_VIRTIO:
+               if (psw_extint_disabled(vcpu))
+                       return 0;
+               if (vcpu->arch.sie_block->gcr[0] & 0x200ul)
+                       return 1;
+               return 0;
+       case KVM_S390_PROGRAM_INT:
+       case KVM_S390_SIGP_STOP:
+       case KVM_S390_SIGP_SET_PREFIX:
+       case KVM_S390_RESTART:
+               return 1;
+       default:
+               BUG();
+       }
+       return 0;
+}
+
+static void __set_cpu_idle(struct kvm_vcpu *vcpu)
+{
+       BUG_ON(vcpu->vcpu_id > KVM_MAX_VCPUS - 1);
+       atomic_set_mask(CPUSTAT_WAIT, &vcpu->arch.sie_block->cpuflags);
+       set_bit(vcpu->vcpu_id, vcpu->arch.local_int.float_int->idle_mask);
+}
+
+static void __unset_cpu_idle(struct kvm_vcpu *vcpu)
+{
+       BUG_ON(vcpu->vcpu_id > KVM_MAX_VCPUS - 1);
+       atomic_clear_mask(CPUSTAT_WAIT, &vcpu->arch.sie_block->cpuflags);
+       clear_bit(vcpu->vcpu_id, vcpu->arch.local_int.float_int->idle_mask);
+}
+
+static void __reset_intercept_indicators(struct kvm_vcpu *vcpu)
+{
+       atomic_clear_mask(CPUSTAT_ECALL_PEND |
+               CPUSTAT_IO_INT | CPUSTAT_EXT_INT | CPUSTAT_STOP_INT,
+               &vcpu->arch.sie_block->cpuflags);
+       vcpu->arch.sie_block->lctl = 0x0000;
+}
+
+static void __set_cpuflag(struct kvm_vcpu *vcpu, u32 flag)
+{
+       atomic_set_mask(flag, &vcpu->arch.sie_block->cpuflags);
+}
+
+static void __set_intercept_indicator(struct kvm_vcpu *vcpu,
+                                     struct interrupt_info *inti)
+{
+       switch (inti->type) {
+       case KVM_S390_INT_EMERGENCY:
+       case KVM_S390_INT_SERVICE:
+       case KVM_S390_INT_VIRTIO:
+               if (psw_extint_disabled(vcpu))
+                       __set_cpuflag(vcpu, CPUSTAT_EXT_INT);
+               else
+                       vcpu->arch.sie_block->lctl |= LCTL_CR0;
+               break;
+       case KVM_S390_SIGP_STOP:
+               __set_cpuflag(vcpu, CPUSTAT_STOP_INT);
+               break;
+       default:
+               BUG();
+       }
+}
+
+static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
+                                  struct interrupt_info *inti)
+{
+       const unsigned short table[] = { 2, 4, 4, 6 };
+       int rc, exception = 0;
+
+       switch (inti->type) {
+       case KVM_S390_INT_EMERGENCY:
+               VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp emerg");
+               vcpu->stat.deliver_emergency_signal++;
+               rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x1201);
+               if (rc == -EFAULT)
+                       exception = 1;
+
+               rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
+                        &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+               if (rc == -EFAULT)
+                       exception = 1;
+
+               rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+                       __LC_EXT_NEW_PSW, sizeof(psw_t));
+               if (rc == -EFAULT)
+                       exception = 1;
+               break;
+
+       case KVM_S390_INT_SERVICE:
+               VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x",
+                          inti->ext.ext_params);
+               vcpu->stat.deliver_service_signal++;
+               rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x2401);
+               if (rc == -EFAULT)
+                       exception = 1;
+
+               rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
+                        &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+               if (rc == -EFAULT)
+                       exception = 1;
+
+               rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+                       __LC_EXT_NEW_PSW, sizeof(psw_t));
+               if (rc == -EFAULT)
+                       exception = 1;
+
+               rc = put_guest_u32(vcpu, __LC_EXT_PARAMS, inti->ext.ext_params);
+               if (rc == -EFAULT)
+                       exception = 1;
+               break;
+
+       case KVM_S390_INT_VIRTIO:
+               VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%lx",
+                          inti->ext.ext_params, inti->ext.ext_params2);
+               vcpu->stat.deliver_virtio_interrupt++;
+               rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x2603);
+               if (rc == -EFAULT)
+                       exception = 1;
+
+               rc = put_guest_u16(vcpu, __LC_CPU_ADDRESS, 0x0d00);
+               if (rc == -EFAULT)
+                       exception = 1;
+
+               rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
+                        &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+               if (rc == -EFAULT)
+                       exception = 1;
+
+               rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+                       __LC_EXT_NEW_PSW, sizeof(psw_t));
+               if (rc == -EFAULT)
+                       exception = 1;
+
+               rc = put_guest_u32(vcpu, __LC_EXT_PARAMS, inti->ext.ext_params);
+               if (rc == -EFAULT)
+                       exception = 1;
+
+               rc = put_guest_u64(vcpu, __LC_PFAULT_INTPARM,
+                       inti->ext.ext_params2);
+               if (rc == -EFAULT)
+                       exception = 1;
+               break;
+
+       case KVM_S390_SIGP_STOP:
+               VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu stop");
+               vcpu->stat.deliver_stop_signal++;
+               __set_intercept_indicator(vcpu, inti);
+               break;
+
+       case KVM_S390_SIGP_SET_PREFIX:
+               VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x",
+                          inti->prefix.address);
+               vcpu->stat.deliver_prefix_signal++;
+               vcpu->arch.sie_block->prefix = inti->prefix.address;
+               vcpu->arch.sie_block->ihcpu = 0xffff;
+               break;
+
+       case KVM_S390_RESTART:
+               VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu restart");
+               vcpu->stat.deliver_restart_signal++;
+               rc = copy_to_guest(vcpu, offsetof(struct _lowcore,
+                 restart_old_psw), &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+               if (rc == -EFAULT)
+                       exception = 1;
+
+               rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+                       offsetof(struct _lowcore, restart_psw), sizeof(psw_t));
+               if (rc == -EFAULT)
+                       exception = 1;
+               break;
+
+       case KVM_S390_PROGRAM_INT:
+               VCPU_EVENT(vcpu, 4, "interrupt: pgm check code:%x, ilc:%x",
+                          inti->pgm.code,
+                          table[vcpu->arch.sie_block->ipa >> 14]);
+               vcpu->stat.deliver_program_int++;
+               rc = put_guest_u16(vcpu, __LC_PGM_INT_CODE, inti->pgm.code);
+               if (rc == -EFAULT)
+                       exception = 1;
+
+               rc = put_guest_u16(vcpu, __LC_PGM_ILC,
+                       table[vcpu->arch.sie_block->ipa >> 14]);
+               if (rc == -EFAULT)
+                       exception = 1;
+
+               rc = copy_to_guest(vcpu, __LC_PGM_OLD_PSW,
+                        &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+               if (rc == -EFAULT)
+                       exception = 1;
+
+               rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+                       __LC_PGM_NEW_PSW, sizeof(psw_t));
+               if (rc == -EFAULT)
+                       exception = 1;
+               break;
+
+       default:
+               BUG();
+       }
+
+       if (exception) {
+               VCPU_EVENT(vcpu, 1, "%s", "program exception while delivering"
+                          " interrupt");
+               kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+               if (inti->type == KVM_S390_PROGRAM_INT) {
+                       printk(KERN_WARNING "kvm: recursive program check\n");
+                       BUG();
+               }
+       }
+}
+
+static int __try_deliver_ckc_interrupt(struct kvm_vcpu *vcpu)
+{
+       int rc, exception = 0;
+
+       if (psw_extint_disabled(vcpu))
+               return 0;
+       if (!(vcpu->arch.sie_block->gcr[0] & 0x800ul))
+               return 0;
+       rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x1004);
+       if (rc == -EFAULT)
+               exception = 1;
+       rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
+                &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+       if (rc == -EFAULT)
+               exception = 1;
+       rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+               __LC_EXT_NEW_PSW, sizeof(psw_t));
+       if (rc == -EFAULT)
+               exception = 1;
+
+       if (exception) {
+               VCPU_EVENT(vcpu, 1, "%s", "program exception while delivering" \
+                          " ckc interrupt");
+               kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+               return 0;
+       }
+
+       return 1;
+}
+
+int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu)
+{
+       struct local_interrupt *li = &vcpu->arch.local_int;
+       struct float_interrupt *fi = vcpu->arch.local_int.float_int;
+       struct interrupt_info  *inti;
+       int rc = 0;
+
+       if (atomic_read(&li->active)) {
+               spin_lock_bh(&li->lock);
+               list_for_each_entry(inti, &li->list, list)
+                       if (__interrupt_is_deliverable(vcpu, inti)) {
+                               rc = 1;
+                               break;
+                       }
+               spin_unlock_bh(&li->lock);
+       }
+
+       if ((!rc) && atomic_read(&fi->active)) {
+               spin_lock_bh(&fi->lock);
+               list_for_each_entry(inti, &fi->list, list)
+                       if (__interrupt_is_deliverable(vcpu, inti)) {
+                               rc = 1;
+                               break;
+                       }
+               spin_unlock_bh(&fi->lock);
+       }
+
+       if ((!rc) && (vcpu->arch.sie_block->ckc <
+               get_clock() + vcpu->arch.sie_block->epoch)) {
+               if ((!psw_extint_disabled(vcpu)) &&
+                       (vcpu->arch.sie_block->gcr[0] & 0x800ul))
+                       rc = 1;
+       }
+
+       return rc;
+}
+
+int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
+{
+       return 0;
+}
+
+int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
+{
+       u64 now, sltime;
+       DECLARE_WAITQUEUE(wait, current);
+
+       vcpu->stat.exit_wait_state++;
+       if (kvm_cpu_has_interrupt(vcpu))
+               return 0;
+
+       if (psw_interrupts_disabled(vcpu)) {
+               VCPU_EVENT(vcpu, 3, "%s", "disabled wait");
+               __unset_cpu_idle(vcpu);
+               return -ENOTSUPP; /* disabled wait */
+       }
+
+       if (psw_extint_disabled(vcpu) ||
+           (!(vcpu->arch.sie_block->gcr[0] & 0x800ul))) {
+               VCPU_EVENT(vcpu, 3, "%s", "enabled wait w/o timer");
+               goto no_timer;
+       }
+
+       now = get_clock() + vcpu->arch.sie_block->epoch;
+       if (vcpu->arch.sie_block->ckc < now) {
+               __unset_cpu_idle(vcpu);
+               return 0;
+       }
+
+       sltime = (vcpu->arch.sie_block->ckc - now) / (0xf4240000ul / HZ) + 1;
+
+       vcpu->arch.ckc_timer.expires = jiffies + sltime;
+
+       add_timer(&vcpu->arch.ckc_timer);
+       VCPU_EVENT(vcpu, 5, "enabled wait timer:%lx jiffies", sltime);
+no_timer:
+       spin_lock_bh(&vcpu->arch.local_int.float_int->lock);
+       spin_lock_bh(&vcpu->arch.local_int.lock);
+       __set_cpu_idle(vcpu);
+       vcpu->arch.local_int.timer_due = 0;
+       add_wait_queue(&vcpu->arch.local_int.wq, &wait);
+       while (list_empty(&vcpu->arch.local_int.list) &&
+               list_empty(&vcpu->arch.local_int.float_int->list) &&
+               (!vcpu->arch.local_int.timer_due) &&
+               !signal_pending(current)) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               spin_unlock_bh(&vcpu->arch.local_int.lock);
+               spin_unlock_bh(&vcpu->arch.local_int.float_int->lock);
+               vcpu_put(vcpu);
+               schedule();
+               vcpu_load(vcpu);
+               spin_lock_bh(&vcpu->arch.local_int.float_int->lock);
+               spin_lock_bh(&vcpu->arch.local_int.lock);
+       }
+       __unset_cpu_idle(vcpu);
+       __set_current_state(TASK_RUNNING);
+       remove_wait_queue(&vcpu->wq, &wait);
+       spin_unlock_bh(&vcpu->arch.local_int.lock);
+       spin_unlock_bh(&vcpu->arch.local_int.float_int->lock);
+       del_timer(&vcpu->arch.ckc_timer);
+       return 0;
+}
+
+void kvm_s390_idle_wakeup(unsigned long data)
+{
+       struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
+
+       spin_lock_bh(&vcpu->arch.local_int.lock);
+       vcpu->arch.local_int.timer_due = 1;
+       if (waitqueue_active(&vcpu->arch.local_int.wq))
+               wake_up_interruptible(&vcpu->arch.local_int.wq);
+       spin_unlock_bh(&vcpu->arch.local_int.lock);
+}
+
+
+void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
+{
+       struct local_interrupt *li = &vcpu->arch.local_int;
+       struct float_interrupt *fi = vcpu->arch.local_int.float_int;
+       struct interrupt_info  *n, *inti = NULL;
+       int deliver;
+
+       __reset_intercept_indicators(vcpu);
+       if (atomic_read(&li->active)) {
+               do {
+                       deliver = 0;
+                       spin_lock_bh(&li->lock);
+                       list_for_each_entry_safe(inti, n, &li->list, list) {
+                               if (__interrupt_is_deliverable(vcpu, inti)) {
+                                       list_del(&inti->list);
+                                       deliver = 1;
+                                       break;
+                               }
+                               __set_intercept_indicator(vcpu, inti);
+                       }
+                       if (list_empty(&li->list))
+                               atomic_set(&li->active, 0);
+                       spin_unlock_bh(&li->lock);
+                       if (deliver) {
+                               __do_deliver_interrupt(vcpu, inti);
+                               kfree(inti);
+                       }
+               } while (deliver);
+       }
+
+       if ((vcpu->arch.sie_block->ckc <
+               get_clock() + vcpu->arch.sie_block->epoch))
+               __try_deliver_ckc_interrupt(vcpu);
+
+       if (atomic_read(&fi->active)) {
+               do {
+                       deliver = 0;
+                       spin_lock_bh(&fi->lock);
+                       list_for_each_entry_safe(inti, n, &fi->list, list) {
+                               if (__interrupt_is_deliverable(vcpu, inti)) {
+                                       list_del(&inti->list);
+                                       deliver = 1;
+                                       break;
+                               }
+                               __set_intercept_indicator(vcpu, inti);
+                       }
+                       if (list_empty(&fi->list))
+                               atomic_set(&fi->active, 0);
+                       spin_unlock_bh(&fi->lock);
+                       if (deliver) {
+                               __do_deliver_interrupt(vcpu, inti);
+                               kfree(inti);
+                       }
+               } while (deliver);
+       }
+}
+
+int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
+{
+       struct local_interrupt *li = &vcpu->arch.local_int;
+       struct interrupt_info *inti;
+
+       inti = kzalloc(sizeof(*inti), GFP_KERNEL);
+       if (!inti)
+               return -ENOMEM;
+
+       inti->type = KVM_S390_PROGRAM_INT;;
+       inti->pgm.code = code;
+
+       VCPU_EVENT(vcpu, 3, "inject: program check %d (from kernel)", code);
+       spin_lock_bh(&li->lock);
+       list_add(&inti->list, &li->list);
+       atomic_set(&li->active, 1);
+       BUG_ON(waitqueue_active(&li->wq));
+       spin_unlock_bh(&li->lock);
+       return 0;
+}
+
+int kvm_s390_inject_vm(struct kvm *kvm,
+                      struct kvm_s390_interrupt *s390int)
+{
+       struct local_interrupt *li;
+       struct float_interrupt *fi;
+       struct interrupt_info *inti;
+       int sigcpu;
+
+       inti = kzalloc(sizeof(*inti), GFP_KERNEL);
+       if (!inti)
+               return -ENOMEM;
+
+       switch (s390int->type) {
+       case KVM_S390_INT_VIRTIO:
+               VM_EVENT(kvm, 5, "inject: virtio parm:%x,parm64:%lx",
+                        s390int->parm, s390int->parm64);
+               inti->type = s390int->type;
+               inti->ext.ext_params = s390int->parm;
+               inti->ext.ext_params2 = s390int->parm64;
+               break;
+       case KVM_S390_INT_SERVICE:
+               VM_EVENT(kvm, 5, "inject: sclp parm:%x", s390int->parm);
+               inti->type = s390int->type;
+               inti->ext.ext_params = s390int->parm;
+               break;
+       case KVM_S390_PROGRAM_INT:
+       case KVM_S390_SIGP_STOP:
+       case KVM_S390_INT_EMERGENCY:
+       default:
+               kfree(inti);
+               return -EINVAL;
+       }
+
+       mutex_lock(&kvm->lock);
+       fi = &kvm->arch.float_int;
+       spin_lock_bh(&fi->lock);
+       list_add_tail(&inti->list, &fi->list);
+       atomic_set(&fi->active, 1);
+       sigcpu = find_first_bit(fi->idle_mask, KVM_MAX_VCPUS);
+       if (sigcpu == KVM_MAX_VCPUS) {
+               do {
+                       sigcpu = fi->next_rr_cpu++;
+                       if (sigcpu == KVM_MAX_VCPUS)
+                               sigcpu = fi->next_rr_cpu = 0;
+               } while (fi->local_int[sigcpu] == NULL);
+       }
+       li = fi->local_int[sigcpu];
+       spin_lock_bh(&li->lock);
+       atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
+       if (waitqueue_active(&li->wq))
+               wake_up_interruptible(&li->wq);
+       spin_unlock_bh(&li->lock);
+       spin_unlock_bh(&fi->lock);
+       mutex_unlock(&kvm->lock);
+       return 0;
+}
+
+int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
+                        struct kvm_s390_interrupt *s390int)
+{
+       struct local_interrupt *li;
+       struct interrupt_info *inti;
+
+       inti = kzalloc(sizeof(*inti), GFP_KERNEL);
+       if (!inti)
+               return -ENOMEM;
+
+       switch (s390int->type) {
+       case KVM_S390_PROGRAM_INT:
+               if (s390int->parm & 0xffff0000) {
+                       kfree(inti);
+                       return -EINVAL;
+               }
+               inti->type = s390int->type;
+               inti->pgm.code = s390int->parm;
+               VCPU_EVENT(vcpu, 3, "inject: program check %d (from user)",
+                          s390int->parm);
+               break;
+       case KVM_S390_SIGP_STOP:
+       case KVM_S390_RESTART:
+       case KVM_S390_SIGP_SET_PREFIX:
+       case KVM_S390_INT_EMERGENCY:
+               VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
+               inti->type = s390int->type;
+               break;
+       case KVM_S390_INT_VIRTIO:
+       case KVM_S390_INT_SERVICE:
+       default:
+               kfree(inti);
+               return -EINVAL;
+       }
+
+       mutex_lock(&vcpu->kvm->lock);
+       li = &vcpu->arch.local_int;
+       spin_lock_bh(&li->lock);
+       if (inti->type == KVM_S390_PROGRAM_INT)
+               list_add(&inti->list, &li->list);
+       else
+               list_add_tail(&inti->list, &li->list);
+       atomic_set(&li->active, 1);
+       if (inti->type == KVM_S390_SIGP_STOP)
+               li->action_bits |= ACTION_STOP_ON_STOP;
+       atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
+       if (waitqueue_active(&li->wq))
+               wake_up_interruptible(&vcpu->arch.local_int.wq);
+       spin_unlock_bh(&li->lock);
+       mutex_unlock(&vcpu->kvm->lock);
+       return 0;
+}
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
new file mode 100644 (file)
index 0000000..98d1e73
--- /dev/null
@@ -0,0 +1,685 @@
+/*
+ * s390host.c --  hosting zSeries kernel virtual machines
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Carsten Otte <cotte@de.ibm.com>
+ *               Christian Borntraeger <borntraeger@de.ibm.com>
+ *               Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <asm/lowcore.h>
+#include <asm/pgtable.h>
+
+#include "kvm-s390.h"
+#include "gaccess.h"
+
+#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
+
+struct kvm_stats_debugfs_item debugfs_entries[] = {
+       { "userspace_handled", VCPU_STAT(exit_userspace) },
+       { "exit_validity", VCPU_STAT(exit_validity) },
+       { "exit_stop_request", VCPU_STAT(exit_stop_request) },
+       { "exit_external_request", VCPU_STAT(exit_external_request) },
+       { "exit_external_interrupt", VCPU_STAT(exit_external_interrupt) },
+       { "exit_instruction", VCPU_STAT(exit_instruction) },
+       { "exit_program_interruption", VCPU_STAT(exit_program_interruption) },
+       { "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) },
+       { "instruction_lctg", VCPU_STAT(instruction_lctg) },
+       { "instruction_lctl", VCPU_STAT(instruction_lctl) },
+       { "deliver_emergency_signal", VCPU_STAT(deliver_emergency_signal) },
+       { "deliver_service_signal", VCPU_STAT(deliver_service_signal) },
+       { "deliver_virtio_interrupt", VCPU_STAT(deliver_virtio_interrupt) },
+       { "deliver_stop_signal", VCPU_STAT(deliver_stop_signal) },
+       { "deliver_prefix_signal", VCPU_STAT(deliver_prefix_signal) },
+       { "deliver_restart_signal", VCPU_STAT(deliver_restart_signal) },
+       { "deliver_program_interruption", VCPU_STAT(deliver_program_int) },
+       { "exit_wait_state", VCPU_STAT(exit_wait_state) },
+       { "instruction_stidp", VCPU_STAT(instruction_stidp) },
+       { "instruction_spx", VCPU_STAT(instruction_spx) },
+       { "instruction_stpx", VCPU_STAT(instruction_stpx) },
+       { "instruction_stap", VCPU_STAT(instruction_stap) },
+       { "instruction_storage_key", VCPU_STAT(instruction_storage_key) },
+       { "instruction_stsch", VCPU_STAT(instruction_stsch) },
+       { "instruction_chsc", VCPU_STAT(instruction_chsc) },
+       { "instruction_stsi", VCPU_STAT(instruction_stsi) },
+       { "instruction_stfl", VCPU_STAT(instruction_stfl) },
+       { "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) },
+       { "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) },
+       { "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) },
+       { "instruction_sigp_set_arch", VCPU_STAT(instruction_sigp_arch) },
+       { "instruction_sigp_set_prefix", VCPU_STAT(instruction_sigp_prefix) },
+       { "instruction_sigp_restart", VCPU_STAT(instruction_sigp_restart) },
+       { "diagnose_44", VCPU_STAT(diagnose_44) },
+       { NULL }
+};
+
+
+/* Section: not file related */
+void kvm_arch_hardware_enable(void *garbage)
+{
+       /* every s390 is virtualization enabled ;-) */
+}
+
+void kvm_arch_hardware_disable(void *garbage)
+{
+}
+
+void decache_vcpus_on_cpu(int cpu)
+{
+}
+
+int kvm_arch_hardware_setup(void)
+{
+       return 0;
+}
+
+void kvm_arch_hardware_unsetup(void)
+{
+}
+
+void kvm_arch_check_processor_compat(void *rtn)
+{
+}
+
+int kvm_arch_init(void *opaque)
+{
+       return 0;
+}
+
+void kvm_arch_exit(void)
+{
+}
+
+/* Section: device related */
+long kvm_arch_dev_ioctl(struct file *filp,
+                       unsigned int ioctl, unsigned long arg)
+{
+       if (ioctl == KVM_S390_ENABLE_SIE)
+               return s390_enable_sie();
+       return -EINVAL;
+}
+
+int kvm_dev_ioctl_check_extension(long ext)
+{
+       return 0;
+}
+
+/* Section: vm related */
+/*
+ * Get (and clear) the dirty memory log for a memory slot.
+ */
+int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
+                              struct kvm_dirty_log *log)
+{
+       return 0;
+}
+
+long kvm_arch_vm_ioctl(struct file *filp,
+                      unsigned int ioctl, unsigned long arg)
+{
+       struct kvm *kvm = filp->private_data;
+       void __user *argp = (void __user *)arg;
+       int r;
+
+       switch (ioctl) {
+       case KVM_S390_INTERRUPT: {
+               struct kvm_s390_interrupt s390int;
+
+               r = -EFAULT;
+               if (copy_from_user(&s390int, argp, sizeof(s390int)))
+                       break;
+               r = kvm_s390_inject_vm(kvm, &s390int);
+               break;
+       }
+       default:
+               r = -EINVAL;
+       }
+
+       return r;
+}
+
+struct kvm *kvm_arch_create_vm(void)
+{
+       struct kvm *kvm;
+       int rc;
+       char debug_name[16];
+
+       rc = s390_enable_sie();
+       if (rc)
+               goto out_nokvm;
+
+       rc = -ENOMEM;
+       kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL);
+       if (!kvm)
+               goto out_nokvm;
+
+       kvm->arch.sca = (struct sca_block *) get_zeroed_page(GFP_KERNEL);
+       if (!kvm->arch.sca)
+               goto out_nosca;
+
+       sprintf(debug_name, "kvm-%u", current->pid);
+
+       kvm->arch.dbf = debug_register(debug_name, 8, 2, 8 * sizeof(long));
+       if (!kvm->arch.dbf)
+               goto out_nodbf;
+
+       spin_lock_init(&kvm->arch.float_int.lock);
+       INIT_LIST_HEAD(&kvm->arch.float_int.list);
+
+       debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
+       VM_EVENT(kvm, 3, "%s", "vm created");
+
+       try_module_get(THIS_MODULE);
+
+       return kvm;
+out_nodbf:
+       free_page((unsigned long)(kvm->arch.sca));
+out_nosca:
+       kfree(kvm);
+out_nokvm:
+       return ERR_PTR(rc);
+}
+
+void kvm_arch_destroy_vm(struct kvm *kvm)
+{
+       debug_unregister(kvm->arch.dbf);
+       free_page((unsigned long)(kvm->arch.sca));
+       kfree(kvm);
+       module_put(THIS_MODULE);
+}
+
+/* Section: vcpu related */
+int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
+{
+       return 0;
+}
+
+void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
+{
+       /* kvm common code refers to this, but does'nt call it */
+       BUG();
+}
+
+void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+       save_fp_regs(&vcpu->arch.host_fpregs);
+       save_access_regs(vcpu->arch.host_acrs);
+       vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK;
+       restore_fp_regs(&vcpu->arch.guest_fpregs);
+       restore_access_regs(vcpu->arch.guest_acrs);
+
+       if (signal_pending(current))
+               atomic_set_mask(CPUSTAT_STOP_INT,
+                       &vcpu->arch.sie_block->cpuflags);
+}
+
+void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
+{
+       save_fp_regs(&vcpu->arch.guest_fpregs);
+       save_access_regs(vcpu->arch.guest_acrs);
+       restore_fp_regs(&vcpu->arch.host_fpregs);
+       restore_access_regs(vcpu->arch.host_acrs);
+}
+
+static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
+{
+       /* this equals initial cpu reset in pop, but we don't switch to ESA */
+       vcpu->arch.sie_block->gpsw.mask = 0UL;
+       vcpu->arch.sie_block->gpsw.addr = 0UL;
+       vcpu->arch.sie_block->prefix    = 0UL;
+       vcpu->arch.sie_block->ihcpu     = 0xffff;
+       vcpu->arch.sie_block->cputm     = 0UL;
+       vcpu->arch.sie_block->ckc       = 0UL;
+       vcpu->arch.sie_block->todpr     = 0;
+       memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64));
+       vcpu->arch.sie_block->gcr[0]  = 0xE0UL;
+       vcpu->arch.sie_block->gcr[14] = 0xC2000000UL;
+       vcpu->arch.guest_fpregs.fpc = 0;
+       asm volatile("lfpc %0" : : "Q" (vcpu->arch.guest_fpregs.fpc));
+       vcpu->arch.sie_block->gbea = 1;
+}
+
+int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
+{
+       atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH);
+       vcpu->arch.sie_block->gmslm = 0xffffffffffUL;
+       vcpu->arch.sie_block->gmsor = 0x000000000000;
+       vcpu->arch.sie_block->ecb   = 2;
+       vcpu->arch.sie_block->eca   = 0xC1002001U;
+       setup_timer(&vcpu->arch.ckc_timer, kvm_s390_idle_wakeup,
+                (unsigned long) vcpu);
+       get_cpu_id(&vcpu->arch.cpu_id);
+       vcpu->arch.cpu_id.version = 0xfe;
+       return 0;
+}
+
+struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
+                                     unsigned int id)
+{
+       struct kvm_vcpu *vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
+       int rc = -ENOMEM;
+
+       if (!vcpu)
+               goto out_nomem;
+
+       vcpu->arch.sie_block = (struct sie_block *) get_zeroed_page(GFP_KERNEL);
+
+       if (!vcpu->arch.sie_block)
+               goto out_free_cpu;
+
+       vcpu->arch.sie_block->icpua = id;
+       BUG_ON(!kvm->arch.sca);
+       BUG_ON(kvm->arch.sca->cpu[id].sda);
+       kvm->arch.sca->cpu[id].sda = (__u64) vcpu->arch.sie_block;
+       vcpu->arch.sie_block->scaoh = (__u32)(((__u64)kvm->arch.sca) >> 32);
+       vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca;
+
+       spin_lock_init(&vcpu->arch.local_int.lock);
+       INIT_LIST_HEAD(&vcpu->arch.local_int.list);
+       vcpu->arch.local_int.float_int = &kvm->arch.float_int;
+       spin_lock_bh(&kvm->arch.float_int.lock);
+       kvm->arch.float_int.local_int[id] = &vcpu->arch.local_int;
+       init_waitqueue_head(&vcpu->arch.local_int.wq);
+       vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
+       spin_unlock_bh(&kvm->arch.float_int.lock);
+
+       rc = kvm_vcpu_init(vcpu, kvm, id);
+       if (rc)
+               goto out_free_cpu;
+       VM_EVENT(kvm, 3, "create cpu %d at %p, sie block at %p", id, vcpu,
+                vcpu->arch.sie_block);
+
+       try_module_get(THIS_MODULE);
+
+       return vcpu;
+out_free_cpu:
+       kfree(vcpu);
+out_nomem:
+       return ERR_PTR(rc);
+}
+
+void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+       VCPU_EVENT(vcpu, 3, "%s", "destroy cpu");
+       free_page((unsigned long)(vcpu->arch.sie_block));
+       kfree(vcpu);
+       module_put(THIS_MODULE);
+}
+
+int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
+{
+       /* kvm common code refers to this, but never calls it */
+       BUG();
+       return 0;
+}
+
+static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
+{
+       vcpu_load(vcpu);
+       kvm_s390_vcpu_initial_reset(vcpu);
+       vcpu_put(vcpu);
+       return 0;
+}
+
+int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+       vcpu_load(vcpu);
+       memcpy(&vcpu->arch.guest_gprs, &regs->gprs, sizeof(regs->gprs));
+       vcpu_put(vcpu);
+       return 0;
+}
+
+int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+       vcpu_load(vcpu);
+       memcpy(&regs->gprs, &vcpu->arch.guest_gprs, sizeof(regs->gprs));
+       vcpu_put(vcpu);
+       return 0;
+}
+
+int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
+                                 struct kvm_sregs *sregs)
+{
+       vcpu_load(vcpu);
+       memcpy(&vcpu->arch.guest_acrs, &sregs->acrs, sizeof(sregs->acrs));
+       memcpy(&vcpu->arch.sie_block->gcr, &sregs->crs, sizeof(sregs->crs));
+       vcpu_put(vcpu);
+       return 0;
+}
+
+int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
+                                 struct kvm_sregs *sregs)
+{
+       vcpu_load(vcpu);
+       memcpy(&sregs->acrs, &vcpu->arch.guest_acrs, sizeof(sregs->acrs));
+       memcpy(&sregs->crs, &vcpu->arch.sie_block->gcr, sizeof(sregs->crs));
+       vcpu_put(vcpu);
+       return 0;
+}
+
+int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+       vcpu_load(vcpu);
+       memcpy(&vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
+       vcpu->arch.guest_fpregs.fpc = fpu->fpc;
+       vcpu_put(vcpu);
+       return 0;
+}
+
+int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+       vcpu_load(vcpu);
+       memcpy(&fpu->fprs, &vcpu->arch.guest_fpregs.fprs, sizeof(fpu->fprs));
+       fpu->fpc = vcpu->arch.guest_fpregs.fpc;
+       vcpu_put(vcpu);
+       return 0;
+}
+
+static int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw)
+{
+       int rc = 0;
+
+       vcpu_load(vcpu);
+       if (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_RUNNING)
+               rc = -EBUSY;
+       else
+               vcpu->arch.sie_block->gpsw = psw;
+       vcpu_put(vcpu);
+       return rc;
+}
+
+int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
+                                 struct kvm_translation *tr)
+{
+       return -EINVAL; /* not implemented yet */
+}
+
+int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
+                                   struct kvm_debug_guest *dbg)
+{
+       return -EINVAL; /* not implemented yet */
+}
+
+int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
+                                   struct kvm_mp_state *mp_state)
+{
+       return -EINVAL; /* not implemented yet */
+}
+
+int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
+                                   struct kvm_mp_state *mp_state)
+{
+       return -EINVAL; /* not implemented yet */
+}
+
+static void __vcpu_run(struct kvm_vcpu *vcpu)
+{
+       memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16);
+
+       if (need_resched())
+               schedule();
+
+       vcpu->arch.sie_block->icptcode = 0;
+       local_irq_disable();
+       kvm_guest_enter();
+       local_irq_enable();
+       VCPU_EVENT(vcpu, 6, "entering sie flags %x",
+                  atomic_read(&vcpu->arch.sie_block->cpuflags));
+       sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs);
+       VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
+                  vcpu->arch.sie_block->icptcode);
+       local_irq_disable();
+       kvm_guest_exit();
+       local_irq_enable();
+
+       memcpy(&vcpu->arch.guest_gprs[14], &vcpu->arch.sie_block->gg14, 16);
+}
+
+int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       int rc;
+       sigset_t sigsaved;
+
+       vcpu_load(vcpu);
+
+       if (vcpu->sigset_active)
+               sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
+
+       atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
+
+       BUG_ON(vcpu->kvm->arch.float_int.local_int[vcpu->vcpu_id] == NULL);
+
+       switch (kvm_run->exit_reason) {
+       case KVM_EXIT_S390_SIEIC:
+               vcpu->arch.sie_block->gpsw.mask = kvm_run->s390_sieic.mask;
+               vcpu->arch.sie_block->gpsw.addr = kvm_run->s390_sieic.addr;
+               break;
+       case KVM_EXIT_UNKNOWN:
+       case KVM_EXIT_S390_RESET:
+               break;
+       default:
+               BUG();
+       }
+
+       might_sleep();
+
+       do {
+               kvm_s390_deliver_pending_interrupts(vcpu);
+               __vcpu_run(vcpu);
+               rc = kvm_handle_sie_intercept(vcpu);
+       } while (!signal_pending(current) && !rc);
+
+       if (signal_pending(current) && !rc)
+               rc = -EINTR;
+
+       if (rc == -ENOTSUPP) {
+               /* intercept cannot be handled in-kernel, prepare kvm-run */
+               kvm_run->exit_reason         = KVM_EXIT_S390_SIEIC;
+               kvm_run->s390_sieic.icptcode = vcpu->arch.sie_block->icptcode;
+               kvm_run->s390_sieic.mask     = vcpu->arch.sie_block->gpsw.mask;
+               kvm_run->s390_sieic.addr     = vcpu->arch.sie_block->gpsw.addr;
+               kvm_run->s390_sieic.ipa      = vcpu->arch.sie_block->ipa;
+               kvm_run->s390_sieic.ipb      = vcpu->arch.sie_block->ipb;
+               rc = 0;
+       }
+
+       if (rc == -EREMOTE) {
+               /* intercept was handled, but userspace support is needed
+                * kvm_run has been prepared by the handler */
+               rc = 0;
+       }
+
+       if (vcpu->sigset_active)
+               sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+       vcpu_put(vcpu);
+
+       vcpu->stat.exit_userspace++;
+       return rc;
+}
+
+static int __guestcopy(struct kvm_vcpu *vcpu, u64 guestdest, const void *from,
+                      unsigned long n, int prefix)
+{
+       if (prefix)
+               return copy_to_guest(vcpu, guestdest, from, n);
+       else
+               return copy_to_guest_absolute(vcpu, guestdest, from, n);
+}
+
+/*
+ * store status at address
+ * we use have two special cases:
+ * KVM_S390_STORE_STATUS_NOADDR: -> 0x1200 on 64 bit
+ * KVM_S390_STORE_STATUS_PREFIXED: -> prefix
+ */
+int __kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
+{
+       const unsigned char archmode = 1;
+       int prefix;
+
+       if (addr == KVM_S390_STORE_STATUS_NOADDR) {
+               if (copy_to_guest_absolute(vcpu, 163ul, &archmode, 1))
+                       return -EFAULT;
+               addr = SAVE_AREA_BASE;
+               prefix = 0;
+       } else if (addr == KVM_S390_STORE_STATUS_PREFIXED) {
+               if (copy_to_guest(vcpu, 163ul, &archmode, 1))
+                       return -EFAULT;
+               addr = SAVE_AREA_BASE;
+               prefix = 1;
+       } else
+               prefix = 0;
+
+       if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, fp_regs),
+                       vcpu->arch.guest_fpregs.fprs, 128, prefix))
+               return -EFAULT;
+
+       if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, gp_regs),
+                       vcpu->arch.guest_gprs, 128, prefix))
+               return -EFAULT;
+
+       if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, psw),
+                       &vcpu->arch.sie_block->gpsw, 16, prefix))
+               return -EFAULT;
+
+       if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, pref_reg),
+                       &vcpu->arch.sie_block->prefix, 4, prefix))
+               return -EFAULT;
+
+       if (__guestcopy(vcpu,
+                       addr + offsetof(struct save_area_s390x, fp_ctrl_reg),
+                       &vcpu->arch.guest_fpregs.fpc, 4, prefix))
+               return -EFAULT;
+
+       if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, tod_reg),
+                       &vcpu->arch.sie_block->todpr, 4, prefix))
+               return -EFAULT;
+
+       if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, timer),
+                       &vcpu->arch.sie_block->cputm, 8, prefix))
+               return -EFAULT;
+
+       if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, clk_cmp),
+                       &vcpu->arch.sie_block->ckc, 8, prefix))
+               return -EFAULT;
+
+       if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, acc_regs),
+                       &vcpu->arch.guest_acrs, 64, prefix))
+               return -EFAULT;
+
+       if (__guestcopy(vcpu,
+                       addr + offsetof(struct save_area_s390x, ctrl_regs),
+                       &vcpu->arch.sie_block->gcr, 128, prefix))
+               return -EFAULT;
+       return 0;
+}
+
+static int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
+{
+       int rc;
+
+       vcpu_load(vcpu);
+       rc = __kvm_s390_vcpu_store_status(vcpu, addr);
+       vcpu_put(vcpu);
+       return rc;
+}
+
+long kvm_arch_vcpu_ioctl(struct file *filp,
+                        unsigned int ioctl, unsigned long arg)
+{
+       struct kvm_vcpu *vcpu = filp->private_data;
+       void __user *argp = (void __user *)arg;
+
+       switch (ioctl) {
+       case KVM_S390_INTERRUPT: {
+               struct kvm_s390_interrupt s390int;
+
+               if (copy_from_user(&s390int, argp, sizeof(s390int)))
+                       return -EFAULT;
+               return kvm_s390_inject_vcpu(vcpu, &s390int);
+       }
+       case KVM_S390_STORE_STATUS:
+               return kvm_s390_vcpu_store_status(vcpu, arg);
+       case KVM_S390_SET_INITIAL_PSW: {
+               psw_t psw;
+
+               if (copy_from_user(&psw, argp, sizeof(psw)))
+                       return -EFAULT;
+               return kvm_arch_vcpu_ioctl_set_initial_psw(vcpu, psw);
+       }
+       case KVM_S390_INITIAL_RESET:
+               return kvm_arch_vcpu_ioctl_initial_reset(vcpu);
+       default:
+               ;
+       }
+       return -EINVAL;
+}
+
+/* Section: memory related */
+int kvm_arch_set_memory_region(struct kvm *kvm,
+                               struct kvm_userspace_memory_region *mem,
+                               struct kvm_memory_slot old,
+                               int user_alloc)
+{
+       /* A few sanity checks. We can have exactly one memory slot which has
+          to start at guest virtual zero and which has to be located at a
+          page boundary in userland and which has to end at a page boundary.
+          The memory in userland is ok to be fragmented into various different
+          vmas. It is okay to mmap() and munmap() stuff in this slot after
+          doing this call at any time */
+
+       if (mem->slot)
+               return -EINVAL;
+
+       if (mem->guest_phys_addr)
+               return -EINVAL;
+
+       if (mem->userspace_addr & (PAGE_SIZE - 1))
+               return -EINVAL;
+
+       if (mem->memory_size & (PAGE_SIZE - 1))
+               return -EINVAL;
+
+       kvm->arch.guest_origin = mem->userspace_addr;
+       kvm->arch.guest_memsize = mem->memory_size;
+
+       /* FIXME: we do want to interrupt running CPUs and update their memory
+          configuration now to avoid race conditions. But hey, changing the
+          memory layout while virtual CPUs are running is usually bad
+          programming practice. */
+
+       return 0;
+}
+
+gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
+{
+       return gfn;
+}
+
+static int __init kvm_s390_init(void)
+{
+       return kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE);
+}
+
+static void __exit kvm_s390_exit(void)
+{
+       kvm_exit();
+}
+
+module_init(kvm_s390_init);
+module_exit(kvm_s390_exit);
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
new file mode 100644 (file)
index 0000000..3893cf1
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * kvm_s390.h -  definition for kvm on s390
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Carsten Otte <cotte@de.ibm.com>
+ *               Christian Borntraeger <borntraeger@de.ibm.com>
+ */
+
+#ifndef ARCH_S390_KVM_S390_H
+#define ARCH_S390_KVM_S390_H
+
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+
+typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu);
+
+int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu);
+
+#define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\
+do { \
+       debug_sprintf_event(d_kvm->arch.dbf, d_loglevel, d_string "\n", \
+         d_args); \
+} while (0)
+
+#define VCPU_EVENT(d_vcpu, d_loglevel, d_string, d_args...)\
+do { \
+       debug_sprintf_event(d_vcpu->kvm->arch.dbf, d_loglevel, \
+         "%02d[%016lx-%016lx]: " d_string "\n", d_vcpu->vcpu_id, \
+         d_vcpu->arch.sie_block->gpsw.mask, d_vcpu->arch.sie_block->gpsw.addr,\
+         d_args); \
+} while (0)
+
+static inline int __cpu_is_stopped(struct kvm_vcpu *vcpu)
+{
+       return atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOP_INT;
+}
+
+int kvm_s390_handle_wait(struct kvm_vcpu *vcpu);
+void kvm_s390_idle_wakeup(unsigned long data);
+void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu);
+int kvm_s390_inject_vm(struct kvm *kvm,
+               struct kvm_s390_interrupt *s390int);
+int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
+               struct kvm_s390_interrupt *s390int);
+int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code);
+
+/* implemented in priv.c */
+int kvm_s390_handle_priv(struct kvm_vcpu *vcpu);
+
+/* implemented in sigp.c */
+int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu);
+
+/* implemented in kvm-s390.c */
+int __kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu,
+                                unsigned long addr);
+/* implemented in diag.c */
+int kvm_s390_handle_diag(struct kvm_vcpu *vcpu);
+
+#endif
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
new file mode 100644 (file)
index 0000000..1465946
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * priv.c - handling privileged instructions
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Carsten Otte <cotte@de.ibm.com>
+ *               Christian Borntraeger <borntraeger@de.ibm.com>
+ */
+
+#include <linux/kvm.h>
+#include <linux/errno.h>
+#include <asm/current.h>
+#include <asm/debug.h>
+#include <asm/ebcdic.h>
+#include <asm/sysinfo.h>
+#include "gaccess.h"
+#include "kvm-s390.h"
+
+static int handle_set_prefix(struct kvm_vcpu *vcpu)
+{
+       int base2 = vcpu->arch.sie_block->ipb >> 28;
+       int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
+       u64 operand2;
+       u32 address = 0;
+       u8 tmp;
+
+       vcpu->stat.instruction_spx++;
+
+       operand2 = disp2;
+       if (base2)
+               operand2 += vcpu->arch.guest_gprs[base2];
+
+       /* must be word boundary */
+       if (operand2 & 3) {
+               kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+               goto out;
+       }
+
+       /* get the value */
+       if (get_guest_u32(vcpu, operand2, &address)) {
+               kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+               goto out;
+       }
+
+       address = address & 0x7fffe000u;
+
+       /* make sure that the new value is valid memory */
+       if (copy_from_guest_absolute(vcpu, &tmp, address, 1) ||
+          (copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1))) {
+               kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+               goto out;
+       }
+
+       vcpu->arch.sie_block->prefix = address;
+       vcpu->arch.sie_block->ihcpu = 0xffff;
+
+       VCPU_EVENT(vcpu, 5, "setting prefix to %x", address);
+out:
+       return 0;
+}
+
+static int handle_store_prefix(struct kvm_vcpu *vcpu)
+{
+       int base2 = vcpu->arch.sie_block->ipb >> 28;
+       int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
+       u64 operand2;
+       u32 address;
+
+       vcpu->stat.instruction_stpx++;
+       operand2 = disp2;
+       if (base2)
+               operand2 += vcpu->arch.guest_gprs[base2];
+
+       /* must be word boundary */
+       if (operand2 & 3) {
+               kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+               goto out;
+       }
+
+       address = vcpu->arch.sie_block->prefix;
+       address = address & 0x7fffe000u;
+
+       /* get the value */
+       if (put_guest_u32(vcpu, operand2, address)) {
+               kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+               goto out;
+       }
+
+       VCPU_EVENT(vcpu, 5, "storing prefix to %x", address);
+out:
+       return 0;
+}
+
+static int handle_store_cpu_address(struct kvm_vcpu *vcpu)
+{
+       int base2 = vcpu->arch.sie_block->ipb >> 28;
+       int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
+       u64 useraddr;
+       int rc;
+
+       vcpu->stat.instruction_stap++;
+       useraddr = disp2;
+       if (base2)
+               useraddr += vcpu->arch.guest_gprs[base2];
+
+       if (useraddr & 1) {
+               kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+               goto out;
+       }
+
+       rc = put_guest_u16(vcpu, useraddr, vcpu->vcpu_id);
+       if (rc == -EFAULT) {
+               kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+               goto out;
+       }
+
+       VCPU_EVENT(vcpu, 5, "storing cpu address to %lx", useraddr);
+out:
+       return 0;
+}
+
+static int handle_skey(struct kvm_vcpu *vcpu)
+{
+       vcpu->stat.instruction_storage_key++;
+       vcpu->arch.sie_block->gpsw.addr -= 4;
+       VCPU_EVENT(vcpu, 4, "%s", "retrying storage key operation");
+       return 0;
+}
+
+static int handle_stsch(struct kvm_vcpu *vcpu)
+{
+       vcpu->stat.instruction_stsch++;
+       VCPU_EVENT(vcpu, 4, "%s", "store subchannel - CC3");
+       /* condition code 3 */
+       vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
+       vcpu->arch.sie_block->gpsw.mask |= (3 & 3ul) << 44;
+       return 0;
+}
+
+static int handle_chsc(struct kvm_vcpu *vcpu)
+{
+       vcpu->stat.instruction_chsc++;
+       VCPU_EVENT(vcpu, 4, "%s", "channel subsystem call - CC3");
+       /* condition code 3 */
+       vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
+       vcpu->arch.sie_block->gpsw.mask |= (3 & 3ul) << 44;
+       return 0;
+}
+
+static unsigned int kvm_stfl(void)
+{
+       asm volatile(
+               "       .insn   s,0xb2b10000,0(0)\n" /* stfl */
+               "0:\n"
+               EX_TABLE(0b, 0b));
+       return S390_lowcore.stfl_fac_list;
+}
+
+static int handle_stfl(struct kvm_vcpu *vcpu)
+{
+       unsigned int facility_list = kvm_stfl();
+       int rc;
+
+       vcpu->stat.instruction_stfl++;
+       facility_list &= ~(1UL<<24); /* no stfle */
+
+       rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list),
+                          &facility_list, sizeof(facility_list));
+       if (rc == -EFAULT)
+               kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+       else
+               VCPU_EVENT(vcpu, 5, "store facility list value %x",
+                          facility_list);
+       return 0;
+}
+
+static int handle_stidp(struct kvm_vcpu *vcpu)
+{
+       int base2 = vcpu->arch.sie_block->ipb >> 28;
+       int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
+       u64 operand2;
+       int rc;
+
+       vcpu->stat.instruction_stidp++;
+       operand2 = disp2;
+       if (base2)
+               operand2 += vcpu->arch.guest_gprs[base2];
+
+       if (operand2 & 7) {
+               kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+               goto out;
+       }
+
+       rc = put_guest_u64(vcpu, operand2, vcpu->arch.stidp_data);
+       if (rc == -EFAULT) {
+               kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+               goto out;
+       }
+
+       VCPU_EVENT(vcpu, 5, "%s", "store cpu id");
+out:
+       return 0;
+}
+
+static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem)
+{
+       struct float_interrupt *fi = &vcpu->kvm->arch.float_int;
+       int cpus = 0;
+       int n;
+
+       spin_lock_bh(&fi->lock);
+       for (n = 0; n < KVM_MAX_VCPUS; n++)
+               if (fi->local_int[n])
+                       cpus++;
+       spin_unlock_bh(&fi->lock);
+
+       /* deal with other level 3 hypervisors */
+       if (stsi(mem, 3, 2, 2) == -ENOSYS)
+               mem->count = 0;
+       if (mem->count < 8)
+               mem->count++;
+       for (n = mem->count - 1; n > 0 ; n--)
+               memcpy(&mem->vm[n], &mem->vm[n - 1], sizeof(mem->vm[0]));
+
+       mem->vm[0].cpus_total = cpus;
+       mem->vm[0].cpus_configured = cpus;
+       mem->vm[0].cpus_standby = 0;
+       mem->vm[0].cpus_reserved = 0;
+       mem->vm[0].caf = 1000;
+       memcpy(mem->vm[0].name, "KVMguest", 8);
+       ASCEBC(mem->vm[0].name, 8);
+       memcpy(mem->vm[0].cpi, "KVM/Linux       ", 16);
+       ASCEBC(mem->vm[0].cpi, 16);
+}
+
+static int handle_stsi(struct kvm_vcpu *vcpu)
+{
+       int fc = (vcpu->arch.guest_gprs[0] & 0xf0000000) >> 28;
+       int sel1 = vcpu->arch.guest_gprs[0] & 0xff;
+       int sel2 = vcpu->arch.guest_gprs[1] & 0xffff;
+       int base2 = vcpu->arch.sie_block->ipb >> 28;
+       int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
+       u64 operand2;
+       unsigned long mem;
+
+       vcpu->stat.instruction_stsi++;
+       VCPU_EVENT(vcpu, 4, "stsi: fc: %x sel1: %x sel2: %x", fc, sel1, sel2);
+
+       operand2 = disp2;
+       if (base2)
+               operand2 += vcpu->arch.guest_gprs[base2];
+
+       if (operand2 & 0xfff && fc > 0)
+               return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+
+       switch (fc) {
+       case 0:
+               vcpu->arch.guest_gprs[0] = 3 << 28;
+               vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
+               return 0;
+       case 1: /* same handling for 1 and 2 */
+       case 2:
+               mem = get_zeroed_page(GFP_KERNEL);
+               if (!mem)
+                       goto out_fail;
+               if (stsi((void *) mem, fc, sel1, sel2) == -ENOSYS)
+                       goto out_mem;
+               break;
+       case 3:
+               if (sel1 != 2 || sel2 != 2)
+                       goto out_fail;
+               mem = get_zeroed_page(GFP_KERNEL);
+               if (!mem)
+                       goto out_fail;
+               handle_stsi_3_2_2(vcpu, (void *) mem);
+               break;
+       default:
+               goto out_fail;
+       }
+
+       if (copy_to_guest_absolute(vcpu, operand2, (void *) mem, PAGE_SIZE)) {
+               kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+               goto out_mem;
+       }
+       free_page(mem);
+       vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
+       vcpu->arch.guest_gprs[0] = 0;
+       return 0;
+out_mem:
+       free_page(mem);
+out_fail:
+       /* condition code 3 */
+       vcpu->arch.sie_block->gpsw.mask |= 3ul << 44;
+       return 0;
+}
+
+static intercept_handler_t priv_handlers[256] = {
+       [0x02] = handle_stidp,
+       [0x10] = handle_set_prefix,
+       [0x11] = handle_store_prefix,
+       [0x12] = handle_store_cpu_address,
+       [0x29] = handle_skey,
+       [0x2a] = handle_skey,
+       [0x2b] = handle_skey,
+       [0x34] = handle_stsch,
+       [0x5f] = handle_chsc,
+       [0x7d] = handle_stsi,
+       [0xb1] = handle_stfl,
+};
+
+int kvm_s390_handle_priv(struct kvm_vcpu *vcpu)
+{
+       intercept_handler_t handler;
+
+       handler = priv_handlers[vcpu->arch.sie_block->ipa & 0x00ff];
+       if (handler)
+               return handler(vcpu);
+       return -ENOTSUPP;
+}
diff --git a/arch/s390/kvm/sie64a.S b/arch/s390/kvm/sie64a.S
new file mode 100644 (file)
index 0000000..934fd6a
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * sie64a.S - low level sie call
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#include <linux/errno.h>
+#include <asm/asm-offsets.h>
+
+SP_R5 =        5 * 8   # offset into stackframe
+SP_R6 =        6 * 8
+
+/*
+ * sie64a calling convention:
+ * %r2 pointer to sie control block
+ * %r3 guest register save area
+ */
+       .globl  sie64a
+sie64a:
+       lgr     %r5,%r3
+       stmg    %r5,%r14,SP_R5(%r15)    # save register on entry
+       lgr     %r14,%r2                # pointer to sie control block
+       lmg     %r0,%r13,0(%r3)         # load guest gprs 0-13
+sie_inst:
+       sie     0(%r14)
+       lg      %r14,SP_R5(%r15)
+       stmg    %r0,%r13,0(%r14)        # save guest gprs 0-13
+       lghi    %r2,0
+       lmg     %r6,%r14,SP_R6(%r15)
+       br      %r14
+
+sie_err:
+       lg      %r14,SP_R5(%r15)
+       stmg    %r0,%r13,0(%r14)        # save guest gprs 0-13
+       lghi    %r2,-EFAULT
+       lmg     %r6,%r14,SP_R6(%r15)
+       br      %r14
+
+       .section __ex_table,"a"
+       .quad   sie_inst,sie_err
+       .previous
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
new file mode 100644 (file)
index 0000000..0a236ac
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * sigp.c - handlinge interprocessor communication
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Carsten Otte <cotte@de.ibm.com>
+ *               Christian Borntraeger <borntraeger@de.ibm.com>
+ */
+
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include "gaccess.h"
+#include "kvm-s390.h"
+
+/* sigp order codes */
+#define SIGP_SENSE             0x01
+#define SIGP_EXTERNAL_CALL     0x02
+#define SIGP_EMERGENCY         0x03
+#define SIGP_START             0x04
+#define SIGP_STOP              0x05
+#define SIGP_RESTART           0x06
+#define SIGP_STOP_STORE_STATUS 0x09
+#define SIGP_INITIAL_CPU_RESET 0x0b
+#define SIGP_CPU_RESET         0x0c
+#define SIGP_SET_PREFIX        0x0d
+#define SIGP_STORE_STATUS_ADDR 0x0e
+#define SIGP_SET_ARCH          0x12
+
+/* cpu status bits */
+#define SIGP_STAT_EQUIPMENT_CHECK   0x80000000UL
+#define SIGP_STAT_INCORRECT_STATE   0x00000200UL
+#define SIGP_STAT_INVALID_PARAMETER 0x00000100UL
+#define SIGP_STAT_EXT_CALL_PENDING  0x00000080UL
+#define SIGP_STAT_STOPPED           0x00000040UL
+#define SIGP_STAT_OPERATOR_INTERV   0x00000020UL
+#define SIGP_STAT_CHECK_STOP        0x00000010UL
+#define SIGP_STAT_INOPERATIVE       0x00000004UL
+#define SIGP_STAT_INVALID_ORDER     0x00000002UL
+#define SIGP_STAT_RECEIVER_CHECK    0x00000001UL
+
+
+static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr, u64 *reg)
+{
+       struct float_interrupt *fi = &vcpu->kvm->arch.float_int;
+       int rc;
+
+       if (cpu_addr >= KVM_MAX_VCPUS)
+               return 3; /* not operational */
+
+       spin_lock_bh(&fi->lock);
+       if (fi->local_int[cpu_addr] == NULL)
+               rc = 3; /* not operational */
+       else if (atomic_read(fi->local_int[cpu_addr]->cpuflags)
+                & CPUSTAT_RUNNING) {
+               *reg &= 0xffffffff00000000UL;
+               rc = 1; /* status stored */
+       } else {
+               *reg &= 0xffffffff00000000UL;
+               *reg |= SIGP_STAT_STOPPED;
+               rc = 1; /* status stored */
+       }
+       spin_unlock_bh(&fi->lock);
+
+       VCPU_EVENT(vcpu, 4, "sensed status of cpu %x rc %x", cpu_addr, rc);
+       return rc;
+}
+
+static int __sigp_emergency(struct kvm_vcpu *vcpu, u16 cpu_addr)
+{
+       struct float_interrupt *fi = &vcpu->kvm->arch.float_int;
+       struct local_interrupt *li;
+       struct interrupt_info *inti;
+       int rc;
+
+       if (cpu_addr >= KVM_MAX_VCPUS)
+               return 3; /* not operational */
+
+       inti = kzalloc(sizeof(*inti), GFP_KERNEL);
+       if (!inti)
+               return -ENOMEM;
+
+       inti->type = KVM_S390_INT_EMERGENCY;
+
+       spin_lock_bh(&fi->lock);
+       li = fi->local_int[cpu_addr];
+       if (li == NULL) {
+               rc = 3; /* not operational */
+               kfree(inti);
+               goto unlock;
+       }
+       spin_lock_bh(&li->lock);
+       list_add_tail(&inti->list, &li->list);
+       atomic_set(&li->active, 1);
+       atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
+       if (waitqueue_active(&li->wq))
+               wake_up_interruptible(&li->wq);
+       spin_unlock_bh(&li->lock);
+       rc = 0; /* order accepted */
+unlock:
+       spin_unlock_bh(&fi->lock);
+       VCPU_EVENT(vcpu, 4, "sent sigp emerg to cpu %x", cpu_addr);
+       return rc;
+}
+
+static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int store)
+{
+       struct float_interrupt *fi = &vcpu->kvm->arch.float_int;
+       struct local_interrupt *li;
+       struct interrupt_info *inti;
+       int rc;
+
+       if (cpu_addr >= KVM_MAX_VCPUS)
+               return 3; /* not operational */
+
+       inti = kzalloc(sizeof(*inti), GFP_KERNEL);
+       if (!inti)
+               return -ENOMEM;
+
+       inti->type = KVM_S390_SIGP_STOP;
+
+       spin_lock_bh(&fi->lock);
+       li = fi->local_int[cpu_addr];
+       if (li == NULL) {
+               rc = 3; /* not operational */
+               kfree(inti);
+               goto unlock;
+       }
+       spin_lock_bh(&li->lock);
+       list_add_tail(&inti->list, &li->list);
+       atomic_set(&li->active, 1);
+       atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags);
+       if (store)
+               li->action_bits |= ACTION_STORE_ON_STOP;
+       li->action_bits |= ACTION_STOP_ON_STOP;
+       if (waitqueue_active(&li->wq))
+               wake_up_interruptible(&li->wq);
+       spin_unlock_bh(&li->lock);
+       rc = 0; /* order accepted */
+unlock:
+       spin_unlock_bh(&fi->lock);
+       VCPU_EVENT(vcpu, 4, "sent sigp stop to cpu %x", cpu_addr);
+       return rc;
+}
+
+static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter)
+{
+       int rc;
+
+       switch (parameter & 0xff) {
+       case 0:
+               printk(KERN_WARNING "kvm: request to switch to ESA/390 mode"
+                                                       " not supported");
+               rc = 3; /* not operational */
+               break;
+       case 1:
+       case 2:
+               rc = 0; /* order accepted */
+               break;
+       default:
+               rc = -ENOTSUPP;
+       }
+       return rc;
+}
+
+static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
+                            u64 *reg)
+{
+       struct float_interrupt *fi = &vcpu->kvm->arch.float_int;
+       struct local_interrupt *li;
+       struct interrupt_info *inti;
+       int rc;
+       u8 tmp;
+
+       /* make sure that the new value is valid memory */
+       address = address & 0x7fffe000u;
+       if ((copy_from_guest(vcpu, &tmp,
+               (u64) (address + vcpu->kvm->arch.guest_origin) , 1)) ||
+          (copy_from_guest(vcpu, &tmp, (u64) (address +
+                       vcpu->kvm->arch.guest_origin + PAGE_SIZE), 1))) {
+               *reg |= SIGP_STAT_INVALID_PARAMETER;
+               return 1; /* invalid parameter */
+       }
+
+       inti = kzalloc(sizeof(*inti), GFP_KERNEL);
+       if (!inti)
+               return 2; /* busy */
+
+       spin_lock_bh(&fi->lock);
+       li = fi->local_int[cpu_addr];
+
+       if ((cpu_addr >= KVM_MAX_VCPUS) || (li == NULL)) {
+               rc = 1; /* incorrect state */
+               *reg &= SIGP_STAT_INCORRECT_STATE;
+               kfree(inti);
+               goto out_fi;
+       }
+
+       spin_lock_bh(&li->lock);
+       /* cpu must be in stopped state */
+       if (atomic_read(li->cpuflags) & CPUSTAT_RUNNING) {
+               rc = 1; /* incorrect state */
+               *reg &= SIGP_STAT_INCORRECT_STATE;
+               kfree(inti);
+               goto out_li;
+       }
+
+       inti->type = KVM_S390_SIGP_SET_PREFIX;
+       inti->prefix.address = address;
+
+       list_add_tail(&inti->list, &li->list);
+       atomic_set(&li->active, 1);
+       if (waitqueue_active(&li->wq))
+               wake_up_interruptible(&li->wq);
+       rc = 0; /* order accepted */
+
+       VCPU_EVENT(vcpu, 4, "set prefix of cpu %02x to %x", cpu_addr, address);
+out_li:
+       spin_unlock_bh(&li->lock);
+out_fi:
+       spin_unlock_bh(&fi->lock);
+       return rc;
+}
+
+int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
+{
+       int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
+       int r3 = vcpu->arch.sie_block->ipa & 0x000f;
+       int base2 = vcpu->arch.sie_block->ipb >> 28;
+       int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
+       u32 parameter;
+       u16 cpu_addr = vcpu->arch.guest_gprs[r3];
+       u8 order_code;
+       int rc;
+
+       order_code = disp2;
+       if (base2)
+               order_code += vcpu->arch.guest_gprs[base2];
+
+       if (r1 % 2)
+               parameter = vcpu->arch.guest_gprs[r1];
+       else
+               parameter = vcpu->arch.guest_gprs[r1 + 1];
+
+       switch (order_code) {
+       case SIGP_SENSE:
+               vcpu->stat.instruction_sigp_sense++;
+               rc = __sigp_sense(vcpu, cpu_addr,
+                                 &vcpu->arch.guest_gprs[r1]);
+               break;
+       case SIGP_EMERGENCY:
+               vcpu->stat.instruction_sigp_emergency++;
+               rc = __sigp_emergency(vcpu, cpu_addr);
+               break;
+       case SIGP_STOP:
+               vcpu->stat.instruction_sigp_stop++;
+               rc = __sigp_stop(vcpu, cpu_addr, 0);
+               break;
+       case SIGP_STOP_STORE_STATUS:
+               vcpu->stat.instruction_sigp_stop++;
+               rc = __sigp_stop(vcpu, cpu_addr, 1);
+               break;
+       case SIGP_SET_ARCH:
+               vcpu->stat.instruction_sigp_arch++;
+               rc = __sigp_set_arch(vcpu, parameter);
+               break;
+       case SIGP_SET_PREFIX:
+               vcpu->stat.instruction_sigp_prefix++;
+               rc = __sigp_set_prefix(vcpu, cpu_addr, parameter,
+                                      &vcpu->arch.guest_gprs[r1]);
+               break;
+       case SIGP_RESTART:
+               vcpu->stat.instruction_sigp_restart++;
+               /* user space must know about restart */
+       default:
+               return -ENOTSUPP;
+       }
+
+       if (rc < 0)
+               return rc;
+
+       vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
+       vcpu->arch.sie_block->gpsw.mask |= (rc & 3ul) << 44;
+       return 0;
+}
index fd072013f88ce11658adab8b7db4818a6479f50b..5c1aea97cd1229b2e231c7dd838ee71663087316 100644 (file)
 #define TABLES_PER_PAGE        4
 #define FRAG_MASK      15UL
 #define SECOND_HALVES  10UL
+
+void clear_table_pgstes(unsigned long *table)
+{
+       clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE/4);
+       memset(table + 256, 0, PAGE_SIZE/4);
+       clear_table(table + 512, _PAGE_TYPE_EMPTY, PAGE_SIZE/4);
+       memset(table + 768, 0, PAGE_SIZE/4);
+}
+
 #else
 #define ALLOC_ORDER    2
 #define TABLES_PER_PAGE        2
 #define FRAG_MASK      3UL
 #define SECOND_HALVES  2UL
+
+void clear_table_pgstes(unsigned long *table)
+{
+       clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE/2);
+       memset(table + 256, 0, PAGE_SIZE/2);
+}
+
 #endif
 
 unsigned long *crst_table_alloc(struct mm_struct *mm, int noexec)
@@ -153,7 +169,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
        unsigned long *table;
        unsigned long bits;
 
-       bits = mm->context.noexec ? 3UL : 1UL;
+       bits = (mm->context.noexec || mm->context.pgstes) ? 3UL : 1UL;
        spin_lock(&mm->page_table_lock);
        page = NULL;
        if (!list_empty(&mm->context.pgtable_list)) {
@@ -170,7 +186,10 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
                pgtable_page_ctor(page);
                page->flags &= ~FRAG_MASK;
                table = (unsigned long *) page_to_phys(page);
-               clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
+               if (mm->context.pgstes)
+                       clear_table_pgstes(table);
+               else
+                       clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
                spin_lock(&mm->page_table_lock);
                list_add(&page->lru, &mm->context.pgtable_list);
        }
@@ -191,7 +210,7 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
        struct page *page;
        unsigned long bits;
 
-       bits = mm->context.noexec ? 3UL : 1UL;
+       bits = (mm->context.noexec || mm->context.pgstes) ? 3UL : 1UL;
        bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long);
        page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
        spin_lock(&mm->page_table_lock);
@@ -228,3 +247,43 @@ void disable_noexec(struct mm_struct *mm, struct task_struct *tsk)
        mm->context.noexec = 0;
        update_mm(mm, tsk);
 }
+
+/*
+ * switch on pgstes for its userspace process (for kvm)
+ */
+int s390_enable_sie(void)
+{
+       struct task_struct *tsk = current;
+       struct mm_struct *mm;
+       int rc;
+
+       task_lock(tsk);
+
+       rc = 0;
+       if (tsk->mm->context.pgstes)
+               goto unlock;
+
+       rc = -EINVAL;
+       if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 ||
+           tsk->mm != tsk->active_mm || tsk->mm->ioctx_list)
+               goto unlock;
+
+       tsk->mm->context.pgstes = 1;    /* dirty little tricks .. */
+       mm = dup_mm(tsk);
+       tsk->mm->context.pgstes = 0;
+
+       rc = -ENOMEM;
+       if (!mm)
+               goto unlock;
+       mmput(tsk->mm);
+       tsk->mm = tsk->active_mm = mm;
+       preempt_disable();
+       update_mm(mm, tsk);
+       cpu_set(smp_processor_id(), mm->cpu_vm_mask);
+       preempt_enable();
+       rc = 0;
+unlock:
+       task_unlock(tsk);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(s390_enable_sie);
index 524b88920947d268233825aefec54b549d0ba21f..409dd71f2738c88f59ae367bdc93aceb2e83455a 100644 (file)
@@ -866,14 +866,21 @@ void smp_call_function_client(int irq, struct pt_regs *regs)
        void *info = call_data->info;
 
        clear_softint(1 << irq);
+
+       irq_enter();
+
+       if (!call_data->wait) {
+               /* let initiator proceed after getting data */
+               atomic_inc(&call_data->finished);
+       }
+
+       func(info);
+
+       irq_exit();
+
        if (call_data->wait) {
                /* let initiator proceed only after completion */
-               func(info);
                atomic_inc(&call_data->finished);
-       } else {
-               /* let initiator proceed after getting data */
-               atomic_inc(&call_data->finished);
-               func(info);
        }
 }
 
@@ -1032,7 +1039,9 @@ void smp_receive_signal(int cpu)
 
 void smp_receive_signal_client(int irq, struct pt_regs *regs)
 {
+       irq_enter();
        clear_softint(1 << irq);
+       irq_exit();
 }
 
 void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
@@ -1040,6 +1049,8 @@ void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
        struct mm_struct *mm;
        unsigned long flags;
 
+       irq_enter();
+
        clear_softint(1 << irq);
 
        /* See if we need to allocate a new TLB context because
@@ -1059,6 +1070,8 @@ void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
        load_secondary_context(mm);
        __flush_tlb_mm(CTX_HWBITS(mm->context),
                       SECONDARY_CONTEXT);
+
+       irq_exit();
 }
 
 void smp_new_mmu_context_version(void)
@@ -1217,6 +1230,8 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
 {
        clear_softint(1 << irq);
 
+       irq_enter();
+
        preempt_disable();
 
        __asm__ __volatile__("flushw");
@@ -1229,6 +1244,8 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
        prom_world(0);
 
        preempt_enable();
+
+       irq_exit();
 }
 
 /* /proc/profile writes can call this, don't __init it please. */
index 73ed01ba40dc340951508ff819a296914efeaad7..8d4761f15fa932cdede6dc4dc4336fdaa2b1cc88 100644 (file)
@@ -454,8 +454,8 @@ asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second,
                        err = sys_semget(first, (int)second, (int)third);
                        goto out;
                case SEMCTL: {
-                       err = sys_semctl(first, third,
-                                        (int)second | IPC_64,
+                       err = sys_semctl(first, second,
+                                        (int)third | IPC_64,
                                         (union semun) ptr);
                        goto out;
                }
index 3fbe69e359edcd6ddcc7b18e701c7a04071741fa..5696e7b374b31904b7559d045b7235b4e25bcf3e 100644 (file)
@@ -1,3 +1,10 @@
+
+menu "Host processor type and features"
+
+source "arch/x86/Kconfig.cpu"
+
+endmenu
+
 config UML_X86
        bool
        default y
index f4bd349d441222fb7c400ac63d8e7b8c390784a2..f25c29a12d007676d736ed8b8fcb9c9e47a0eaed 100644 (file)
@@ -14,6 +14,7 @@
 #include "os.h"
 #include "um_malloc.h"
 #include "user.h"
+#include <linux/limits.h>
 
 struct helper_data {
        void (*pre_exec)(void*);
index 964dc1a04c37a7774f56a5d0842d737d477c85c4..598b5c1903af11f10c5c171402b6d283ba9e7565 100644 (file)
@@ -6,7 +6,7 @@ obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
        ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
        sys_call_table.o tls.o
 
-subarch-obj-y = lib/bitops_32.o lib/semaphore_32.o lib/string_32.o
+subarch-obj-y = lib/semaphore_32.o lib/string_32.o
 subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o
 subarch-obj-$(CONFIG_MODULES) += kernel/module_32.o
 
index 3c22de532088b4c5baef1bee93cb85d9cd668840..c8b4cce9cfe1ce333dd877c8644f5b7d4fab3558 100644 (file)
@@ -10,7 +10,7 @@ obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
 
 obj-$(CONFIG_MODULES) += um_module.o
 
-subarch-obj-y = lib/bitops_64.o lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o
+subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o
 subarch-obj-$(CONFIG_MODULES) += kernel/module_64.o
 
 ldt-y = ../sys-i386/ldt.o
index 87a693cf2bb79f6cebbd82368bb2da35e3b45cf9..e5790fe9e330acf69482fd7e988c47b9075295b5 100644 (file)
@@ -23,7 +23,7 @@ config X86
        select HAVE_KPROBES
        select HAVE_KRETPROBES
        select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64)
-       select HAVE_ARCH_KGDB
+       select HAVE_ARCH_KGDB if !X86_VOYAGER
 
 
 config GENERIC_LOCKBREAK
@@ -142,6 +142,9 @@ config AUDIT_ARCH
 config ARCH_SUPPORTS_AOUT
        def_bool y
 
+config ARCH_SUPPORTS_OPTIMIZED_INLINING
+       def_bool y
+
 # Use the generic interrupt handling code in kernel/irq/:
 config GENERIC_HARDIRQS
        bool
@@ -370,6 +373,25 @@ config VMI
          at the moment), by linking the kernel to a GPL-ed ROM module
          provided by the hypervisor.
 
+config KVM_CLOCK
+       bool "KVM paravirtualized clock"
+       select PARAVIRT
+       depends on !(X86_VISWS || X86_VOYAGER)
+       help
+         Turning on this option will allow you to run a paravirtualized clock
+         when running over the KVM hypervisor. Instead of relying on a PIT
+         (or probably other) emulation by the underlying device model, the host
+         provides the guest with timing infrastructure such as time of day, and
+         system time
+
+config KVM_GUEST
+       bool "KVM Guest support"
+       select PARAVIRT
+       depends on !(X86_VISWS || X86_VOYAGER)
+       help
+        This option enables various optimizations for running under the KVM
+        hypervisor.
+
 source "arch/x86/lguest/Kconfig"
 
 config PARAVIRT
@@ -1049,9 +1071,9 @@ config MTRR
          See <file:Documentation/mtrr.txt> for more information.
 
 config X86_PAT
-       def_bool y
+       bool
        prompt "x86 PAT support"
-       depends on MTRR && NONPROMISC_DEVMEM
+       depends on MTRR
        help
          Use PAT attributes to setup page level cache control.
 
index 57072f2716f98881fd67a6addd82cffa27ab7817..7ef18b01f0bca49c4da9ed1ed78b330ab1506da4 100644 (file)
@@ -21,8 +21,8 @@ config M386
 
          Here are the settings recommended for greatest speed:
          - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI
-         486DLC/DLC2, UMC 486SX-S and NexGen Nx586.  Only "386" kernels
-         will run on a 386 class machine.
+         486DLC/DLC2, and UMC 486SX-S.  Only "386" kernels will run on a 386
+         class machine.
          - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or
          SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S.
          - "586" for generic Pentium CPUs lacking the TSC
@@ -278,6 +278,11 @@ config GENERIC_CPU
 
 endchoice
 
+config X86_CPU
+       def_bool y
+       select GENERIC_FIND_FIRST_BIT
+       select GENERIC_FIND_NEXT_BIT
+
 config X86_GENERIC
        bool "Generic x86 support"
        depends on X86_32
@@ -398,7 +403,7 @@ config X86_TSC
 # generates cmov.
 config X86_CMOV
        def_bool y
-       depends on (MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7)
+       depends on (MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || X86_64)
 
 config X86_MINIMUM_CPU_FAMILY
        int
index 610aaecc19f820013ecfb9564f6c7b9762fdb82c..5b1979a45a1ea07f6ffc8d6b563fc1ddcb64dae3 100644 (file)
@@ -5,6 +5,17 @@ config TRACE_IRQFLAGS_SUPPORT
 
 source "lib/Kconfig.debug"
 
+config NONPROMISC_DEVMEM
+       bool "Disable promiscuous /dev/mem"
+       help
+         The /dev/mem file by default only allows userspace access to PCI
+         space and the BIOS code and data regions. This is sufficient for
+         dosemu and X and all common users of /dev/mem. With this config
+         option, you allow userspace access to all of memory, including
+         kernel and userspace memory. Accidental access to this is
+         obviously disasterous, but specific access can be used by people
+         debugging the kernel.
+
 config EARLY_PRINTK
        bool "Early printk" if EMBEDDED
        default y
@@ -246,3 +257,16 @@ config CPA_DEBUG
          Do change_page_attr() self-tests every 30 seconds.
 
 endmenu
+
+config OPTIMIZE_INLINING
+       bool "Allow gcc to uninline functions marked 'inline'"
+       default y
+       help
+         This option determines if the kernel forces gcc to inline the functions
+         developers have marked 'inline'. Doing so takes away freedom from gcc to
+         do what it thinks is best, which is desirable for the gcc 3.x series of
+         compilers. The gcc 4.x series have a rewritten inlining algorithm and
+         disabling this option will generate a smaller kernel there. Hopefully
+         this algorithm is so good that allowing gcc4 to make the decision can
+         become the default in the future, until then this option is there to
+         test gcc for this.
index b1bdc4c6f9f29c8de2ad322980f5d1f28c0c9a8e..172cf8a98bdd2541e0d930e2a92903f5f8f9d448 100644 (file)
@@ -1,7 +1,8 @@
 bootsect
 bzImage
+cpustr.h
+mkcpustr
+offsets.h
 setup
 setup.bin
 setup.elf
-cpustr.h
-mkcpustr
index 6d2df8d61c54089a553c0cdee879dde6f421130c..af86e431acfae2af91957a9932c3bf5fb96bd5fb 100644 (file)
@@ -120,7 +120,7 @@ _start:
        # Part 2 of the header, from the old setup.S
 
                .ascii  "HdrS"          # header signature
-               .word   0x0208          # header version number (>= 0x0105)
+               .word   0x0209          # header version number (>= 0x0105)
                                        # or else old loadlin-1.5 will fail)
                .globl realmode_swtch
 realmode_swtch:        .word   0, 0            # default_switch, SETUPSEG
@@ -227,6 +227,10 @@ hardware_subarch_data:     .quad 0
 payload_offset:                .long input_data
 payload_length:                .long input_data_end-input_data
 
+setup_data:            .quad 0                 # 64-bit physical pointer to
+                                               # single linked list of
+                                               # struct setup_data
+
 # End of setup header #####################################################
 
        .section ".inittext", "ax"
index 3df340b54e57e93ab09dc6430184f38a2e4b49f3..ad7ddaaff588aaa619010fabe29af2ee2559d54d 100644 (file)
@@ -1421,6 +1421,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_FRAME_POINTER is not set
+CONFIG_OPTIMIZE_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_LKDTM is not set
 # CONFIG_FAULT_INJECTION is not set
index eef98cb00c629f118ae3982c4f654290de6c2102..2d6f5b2809d2f4644e82ccfd323acbe587693bf5 100644 (file)
@@ -1346,6 +1346,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_FRAME_POINTER is not set
+CONFIG_OPTIMIZE_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_LKDTM is not set
 # CONFIG_FAULT_INJECTION is not set
index 05e155d3fb6c6eebb668ac74ac52fa916f53df5b..bbed3a26ce5567abb107f0371651c906b5f368a7 100644 (file)
@@ -499,11 +499,6 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
        regs->cs = __USER32_CS;
        regs->ss = __USER32_DS;
 
-       set_fs(USER_DS);
-       regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-
 #if DEBUG_SIG
        printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
               current->comm, current->pid, frame, regs->ip, frame->pretcode);
@@ -599,11 +594,6 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->cs = __USER32_CS;
        regs->ss = __USER32_DS;
 
-       set_fs(USER_DS);
-       regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-
 #if DEBUG_SIG
        printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
               current->comm, current->pid, frame, regs->ip, frame->pretcode);
index ae7158bce4d62d6b0ec1bfec5c52ead3b3e48049..b5e329da166cfa2a48a74339a47539739ec939ac 100644 (file)
@@ -430,7 +430,7 @@ ia32_sys_call_table:
        .quad sys_setuid16
        .quad sys_getuid16
        .quad compat_sys_stime  /* stime */             /* 25 */
-       .quad sys32_ptrace      /* ptrace */
+       .quad compat_sys_ptrace /* ptrace */
        .quad sys_alarm
        .quad sys_fstat /* (old)fstat */
        .quad sys_pause
index 90e092d0af0c639211932fc44a0f5dd959ec590b..fa19c3819540d0f823bd675f61457bab2fc31b30 100644 (file)
@@ -80,6 +80,8 @@ obj-$(CONFIG_DEBUG_RODATA_TEST)       += test_rodata.o
 obj-$(CONFIG_DEBUG_NX_TEST)    += test_nx.o
 
 obj-$(CONFIG_VMI)              += vmi_32.o vmiclock_32.o
+obj-$(CONFIG_KVM_GUEST)                += kvm.o
+obj-$(CONFIG_KVM_CLOCK)                += kvmclock.o
 obj-$(CONFIG_PARAVIRT)         += paravirt.o paravirt_patch_$(BITS).o
 
 ifdef CONFIG_INPUT_PCSPKR
index 057ccf1d5ad453891fa78f4c85622386ccfe8728..977ed5cdeaa3b1b6a8d5f78b3446df7be7e21b53 100644 (file)
@@ -697,10 +697,6 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table)
 #define HPET_RESOURCE_NAME_SIZE 9
        hpet_res = alloc_bootmem(sizeof(*hpet_res) + HPET_RESOURCE_NAME_SIZE);
 
-       if (!hpet_res)
-               return 0;
-
-       memset(hpet_res, 0, sizeof(*hpet_res));
        hpet_res->name = (void *)&hpet_res[1];
        hpet_res->flags = IORESOURCE_MEM;
        snprintf((char *)hpet_res->name, HPET_RESOURCE_NAME_SIZE, "HPET %u",
diff --git a/arch/x86/kernel/acpi/realmode/.gitignore b/arch/x86/kernel/acpi/realmode/.gitignore
new file mode 100644 (file)
index 0000000..58f1f48
--- /dev/null
@@ -0,0 +1,3 @@
+wakeup.bin
+wakeup.elf
+wakeup.lds
index df4099dc1c682eb4af7c4af22badf4e4f3cd770c..65c7857a90ddfc6ff084c6817baba045ced0ad71 100644 (file)
@@ -511,31 +511,30 @@ void *__kprobes text_poke(void *addr, const void *opcode, size_t len)
        unsigned long flags;
        char *vaddr;
        int nr_pages = 2;
+       struct page *pages[2];
+       int i;
 
-       BUG_ON(len > sizeof(long));
-       BUG_ON((((long)addr + len - 1) & ~(sizeof(long) - 1))
-               - ((long)addr & ~(sizeof(long) - 1)));
-       if (kernel_text_address((unsigned long)addr)) {
-               struct page *pages[2] = { virt_to_page(addr),
-                       virt_to_page(addr + PAGE_SIZE) };
-               if (!pages[1])
-                       nr_pages = 1;
-               vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL);
-               BUG_ON(!vaddr);
-               local_irq_save(flags);
-               memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len);
-               local_irq_restore(flags);
-               vunmap(vaddr);
+       if (!core_kernel_text((unsigned long)addr)) {
+               pages[0] = vmalloc_to_page(addr);
+               pages[1] = vmalloc_to_page(addr + PAGE_SIZE);
        } else {
-               /*
-                * modules are in vmalloc'ed memory, always writable.
-                */
-               local_irq_save(flags);
-               memcpy(addr, opcode, len);
-               local_irq_restore(flags);
+               pages[0] = virt_to_page(addr);
+               WARN_ON(!PageReserved(pages[0]));
+               pages[1] = virt_to_page(addr + PAGE_SIZE);
        }
+       BUG_ON(!pages[0]);
+       if (!pages[1])
+               nr_pages = 1;
+       vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL);
+       BUG_ON(!vaddr);
+       local_irq_save(flags);
+       memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len);
+       local_irq_restore(flags);
+       vunmap(vaddr);
        sync_core();
        /* Could also do a CLFLUSH here to speed up CPU recovery; but
           that causes hangs on some VIA CPUs. */
+       for (i = 0; i < len; i++)
+               BUG_ON(((char *)addr)[i] != ((char *)opcode)[i]);
        return addr;
 }
index 687208190b065d0b0b17650b5335f1f931fffe50..4b99b1bdeb6cbb090e5868138922b259da7d98fe 100644 (file)
@@ -451,7 +451,8 @@ void __init setup_boot_APIC_clock(void)
        }
 
        /* Calculate the scaled math multiplication factor */
-       lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, 32);
+       lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS,
+                                      lapic_clockevent.shift);
        lapic_clockevent.max_delta_ns =
                clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
        lapic_clockevent.min_delta_ns =
@@ -902,7 +903,7 @@ void __init init_bsp_APIC(void)
        apic_write_around(APIC_LVT1, value);
 }
 
-void __cpuinit lapic_setup_esr(void)
+static void __cpuinit lapic_setup_esr(void)
 {
        unsigned long oldvalue, value, maxlvt;
        if (lapic_is_integrated() && !esr_disable) {
index 9e8e5c050c55f7fa9418c0621c17030f9fea3b54..5910020c3f24f20f4a1be57650d1e2d9c9a3a1fa 100644 (file)
@@ -360,7 +360,8 @@ static void __init calibrate_APIC_clock(void)
                result / 1000 / 1000, result / 1000 % 1000);
 
        /* Calculate the scaled math multiplication factor */
-       lapic_clockevent.mult = div_sc(result, NSEC_PER_SEC, 32);
+       lapic_clockevent.mult = div_sc(result, NSEC_PER_SEC,
+                                      lapic_clockevent.shift);
        lapic_clockevent.max_delta_ns =
                clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
        lapic_clockevent.min_delta_ns =
@@ -429,7 +430,7 @@ void __init setup_boot_APIC_clock(void)
  * set the DUMMY flag again and force the broadcast mode in the
  * clockevents layer.
  */
-void __cpuinit check_boot_apic_timer_broadcast(void)
+static void __cpuinit check_boot_apic_timer_broadcast(void)
 {
        if (!disable_apic_timer ||
            (lapic_clockevent.features & CLOCK_EVT_FEAT_DUMMY))
@@ -834,7 +835,7 @@ void __cpuinit setup_local_APIC(void)
        preempt_enable();
 }
 
-void __cpuinit lapic_setup_esr(void)
+static void __cpuinit lapic_setup_esr(void)
 {
        unsigned maxlvt = lapic_get_maxlvt();
 
index f0030a0999c74f01785c4acd7a499778de58a4ff..e4ea362e84800a6c28bf8056ec340aff5fea4bad 100644 (file)
@@ -904,6 +904,7 @@ recalc:
                        original_pm_idle();
                else
                        default_idle();
+               local_irq_disable();
                jiffies_since_last_check = jiffies - last_jiffies;
                if (jiffies_since_last_check > idle_period)
                        goto recalc;
@@ -911,6 +912,8 @@ recalc:
 
        if (apm_idle_done)
                apm_do_busy();
+
+       local_irq_enable();
 }
 
 /**
index ee7c45235e547a769f091842a8fe3cf959ce5fcc..a0c6f8190887f4220b4b76e531e57ad471fc1acb 100644 (file)
@@ -11,7 +11,6 @@ obj-$(CONFIG_X86_32)  += cyrix.o
 obj-$(CONFIG_X86_32)   += centaur.o
 obj-$(CONFIG_X86_32)   += transmeta.o
 obj-$(CONFIG_X86_32)   += intel.o
-obj-$(CONFIG_X86_32)   += nexgen.o
 obj-$(CONFIG_X86_32)   += umc.o
 
 obj-$(CONFIG_X86_MCE)  += mcheck/
index 0173065dc3b7bd81995f0d8ed5d84c7876624452..245866828294c6be3fcf369d0ea76a0a3eed59cb 100644 (file)
@@ -343,10 +343,4 @@ static struct cpu_dev amd_cpu_dev __cpuinitdata = {
        .c_size_cache   = amd_size_cache,
 };
 
-int __init amd_init_cpu(void)
-{
-       cpu_devs[X86_VENDOR_AMD] = &amd_cpu_dev;
-       return 0;
-}
-
 cpu_vendor_dev_register(X86_VENDOR_AMD, &amd_cpu_dev);
index 9a699ed035982ddeac48c4800478d5c8d4a0a5c4..e07e8c068ae00c464cdbf828cfbc8c67aaf76202 100644 (file)
@@ -49,7 +49,7 @@ static int banks;
 static unsigned long bank[NR_BANKS] = { [0 ... NR_BANKS-1] = ~0UL };
 static unsigned long notify_user;
 static int rip_msr;
-static int mce_bootlog = 1;
+static int mce_bootlog = -1;
 static atomic_t mce_events;
 
 static char trigger[128];
@@ -471,13 +471,15 @@ static void mce_init(void *dummy)
 static void __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c)
 {
        /* This should be disabled by the BIOS, but isn't always */
-       if (c->x86_vendor == X86_VENDOR_AMD && c->x86 == 15) {
-               /* disable GART TBL walk error reporting, which trips off
-                  incorrectly with the IOMMU & 3ware & Cerberus. */
-               clear_bit(10, &bank[4]);
-               /* Lots of broken BIOS around that don't clear them
-                  by default and leave crap in there. Don't log. */
-               mce_bootlog = 0;
+       if (c->x86_vendor == X86_VENDOR_AMD) {
+               if(c->x86 == 15)
+                       /* disable GART TBL walk error reporting, which trips off
+                          incorrectly with the IOMMU & 3ware & Cerberus. */
+                       clear_bit(10, &bank[4]);
+               if(c->x86 <= 17 && mce_bootlog < 0)
+                       /* Lots of broken BIOS around that don't clear them
+                          by default and leave crap in there. Don't log. */
+                       mce_bootlog = 0;
        }
 
 }
diff --git a/arch/x86/kernel/cpu/nexgen.c b/arch/x86/kernel/cpu/nexgen.c
deleted file mode 100644 (file)
index 5d5e1c1..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <asm/processor.h>
-
-#include "cpu.h"
-
-/*
- *     Detect a NexGen CPU running without BIOS hypercode new enough
- *     to have CPUID. (Thanks to Herbert Oppmann)
- */
-
-static int __cpuinit deep_magic_nexgen_probe(void)
-{
-       int ret;
-
-       __asm__ __volatile__ (
-               "       movw    $0x5555, %%ax\n"
-               "       xorw    %%dx,%%dx\n"
-               "       movw    $2, %%cx\n"
-               "       divw    %%cx\n"
-               "       movl    $0, %%eax\n"
-               "       jnz     1f\n"
-               "       movl    $1, %%eax\n"
-               "1:\n"
-               : "=a" (ret) : : "cx", "dx");
-       return  ret;
-}
-
-static void __cpuinit init_nexgen(struct cpuinfo_x86 *c)
-{
-       c->x86_cache_size = 256; /* A few had 1 MB... */
-}
-
-static void __cpuinit nexgen_identify(struct cpuinfo_x86 *c)
-{
-       /* Detect NexGen with old hypercode */
-       if (deep_magic_nexgen_probe())
-               strcpy(c->x86_vendor_id, "NexGenDriven");
-}
-
-static struct cpu_dev nexgen_cpu_dev __cpuinitdata = {
-       .c_vendor       = "Nexgen",
-       .c_ident        = { "NexGenDriven" },
-       .c_models = {
-                       { .vendor = X86_VENDOR_NEXGEN,
-                         .family = 5,
-                         .model_names = { [1] = "Nx586" }
-                       },
-       },
-       .c_init         = init_nexgen,
-       .c_identify     = nexgen_identify,
-};
-
-int __init nexgen_init_cpu(void)
-{
-       cpu_devs[X86_VENDOR_NEXGEN] = &nexgen_cpu_dev;
-       return 0;
-}
index b943e10ad81438aa528ee1c7dad5f7a528488a38..f9ae93adffe5a58619b2c687e39cfbb43e00d987 100644 (file)
@@ -614,16 +614,6 @@ static struct wd_ops intel_arch_wd_ops __read_mostly = {
        .evntsel = MSR_ARCH_PERFMON_EVENTSEL1,
 };
 
-static struct wd_ops coreduo_wd_ops = {
-       .reserve = single_msr_reserve,
-       .unreserve = single_msr_unreserve,
-       .setup = setup_intel_arch_watchdog,
-       .rearm = p6_rearm,
-       .stop = single_msr_stop_watchdog,
-       .perfctr = MSR_ARCH_PERFMON_PERFCTR0,
-       .evntsel = MSR_ARCH_PERFMON_EVENTSEL0,
-};
-
 static void probe_nmi_watchdog(void)
 {
        switch (boot_cpu_data.x86_vendor) {
@@ -637,8 +627,8 @@ static void probe_nmi_watchdog(void)
                /* Work around Core Duo (Yonah) errata AE49 where perfctr1
                   doesn't have a working enable bit. */
                if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 14) {
-                       wd_ops = &coreduo_wd_ops;
-                       break;
+                       intel_arch_wd_ops.perfctr = MSR_ARCH_PERFMON_PERFCTR0;
+                       intel_arch_wd_ops.evntsel = MSR_ARCH_PERFMON_EVENTSEL0;
                }
                if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
                        wd_ops = &intel_arch_wd_ops;
index 2251d0ae9570de24259a6c132aec2c4ef2d05f46..2685538179097a1e8e073ebf07cd49e898ef4f6e 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/hpet.h>
 #include <linux/kdebug.h>
 #include <asm/smp.h>
+#include <asm/reboot.h>
 
 #include <mach_ipi.h>
 
@@ -117,7 +118,7 @@ static void nmi_shootdown_cpus(void)
 }
 #endif
 
-void machine_crash_shutdown(struct pt_regs *regs)
+void native_machine_crash_shutdown(struct pt_regs *regs)
 {
        /* This function is only called after the system
         * has panicked or is otherwise in a critical state.
index cbd42e51cb082d82b8f287eaa1c244913268d64c..645ee5e32a27184c714355c8e916951ef3605711 100644 (file)
@@ -84,14 +84,41 @@ void __init reserve_early(unsigned long start, unsigned long end, char *name)
                strncpy(r->name, name, sizeof(r->name) - 1);
 }
 
-void __init early_res_to_bootmem(void)
+void __init free_early(unsigned long start, unsigned long end)
+{
+       struct early_res *r;
+       int i, j;
+
+       for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
+               r = &early_res[i];
+               if (start == r->start && end == r->end)
+                       break;
+       }
+       if (i >= MAX_EARLY_RES || !early_res[i].end)
+               panic("free_early on not reserved area: %lx-%lx!", start, end);
+
+       for (j = i + 1; j < MAX_EARLY_RES && early_res[j].end; j++)
+               ;
+
+       memcpy(&early_res[i], &early_res[i + 1],
+              (j - 1 - i) * sizeof(struct early_res));
+
+       early_res[j - 1].end = 0;
+}
+
+void __init early_res_to_bootmem(unsigned long start, unsigned long end)
 {
        int i;
+       unsigned long final_start, final_end;
        for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
                struct early_res *r = &early_res[i];
-               printk(KERN_INFO "early res: %d [%lx-%lx] %s\n", i,
-                       r->start, r->end - 1, r->name);
-               reserve_bootmem_generic(r->start, r->end - r->start);
+               final_start = max(start, r->start);
+               final_end = min(end, r->end);
+               if (final_start >= final_end)
+                       continue;
+               printk(KERN_INFO "  early res: %d [%lx-%lx] %s\n", i,
+                       final_start, final_end - 1, r->name);
+               reserve_bootmem_generic(final_start, final_end - final_start);
        }
 }
 
index f0f8934fc30324fc29af50dc436db6f14b198a93..2a609dc3271c3dc2008ad740133f314e5ed177b6 100644 (file)
@@ -409,7 +409,7 @@ restore_nocheck_notrace:
 irq_return:
        INTERRUPT_RETURN
 .section .fixup,"ax"
-iret_exc:
+ENTRY(iret_exc)
        pushl $0                        # no error code
        pushl $do_iret_error
        jmp error_code
@@ -1017,6 +1017,13 @@ ENTRY(kernel_thread_helper)
 ENDPROC(kernel_thread_helper)
 
 #ifdef CONFIG_XEN
+/* Xen doesn't set %esp to be precisely what the normal sysenter
+   entrypoint expects, so fix it up before using the normal path. */
+ENTRY(xen_sysenter_target)
+       RING0_INT_FRAME
+       addl $5*4, %esp         /* remove xen-provided frame */
+       jmp sysenter_past_esp
+
 ENTRY(xen_hypervisor_callback)
        CFI_STARTPROC
        pushl $0
@@ -1035,8 +1042,9 @@ ENTRY(xen_hypervisor_callback)
        cmpl $xen_iret_end_crit,%eax
        jae  1f
 
-       call xen_iret_crit_fixup
+       jmp  xen_iret_crit_fixup
 
+ENTRY(xen_do_upcall)
 1:     mov %esp, %eax
        call xen_evtchn_do_upcall
        jmp  ret_from_intr
index 9546ef408b92c95177f58ba5cce6287951789735..021624c835832d81f00f1ed6ef5d5437e9303813 100644 (file)
@@ -51,7 +51,7 @@ void __init setup_apic_routing(void)
        else
 #endif
 
-       if (cpus_weight(cpu_possible_map) <= 8)
+       if (num_possible_cpus() <= 8)
                genapic = &apic_flat;
        else
                genapic = &apic_physflat;
index 993c767732564afe285e7ddc23228511108b7b11..e25c57b8aa844937742f246288e9ffa2e2be5229 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/string.h>
 #include <linux/percpu.h>
 #include <linux/start_kernel.h>
+#include <linux/io.h>
 
 #include <asm/processor.h>
 #include <asm/proto.h>
@@ -22,6 +23,7 @@
 #include <asm/sections.h>
 #include <asm/kdebug.h>
 #include <asm/e820.h>
+#include <asm/bios_ebda.h>
 
 static void __init zap_identity_mappings(void)
 {
@@ -49,7 +51,6 @@ static void __init copy_bootdata(char *real_mode_data)
        }
 }
 
-#define BIOS_EBDA_SEGMENT 0x40E
 #define BIOS_LOWMEM_KILOBYTES 0x413
 
 /*
@@ -80,8 +81,7 @@ static void __init reserve_ebda_region(void)
        lowmem <<= 10;
 
        /* start of EBDA area */
-       ebda_addr = *(unsigned short *)__va(BIOS_EBDA_SEGMENT);
-       ebda_addr <<= 4;
+       ebda_addr = get_bios_ebda();
 
        /* Fixup: bios puts an EBDA in the top 64K segment */
        /* of conventional memory, but does not adjust lowmem. */
@@ -101,6 +101,24 @@ static void __init reserve_ebda_region(void)
        reserve_early(lowmem, 0x100000, "BIOS reserved");
 }
 
+static void __init reserve_setup_data(void)
+{
+       struct setup_data *data;
+       unsigned long pa_data;
+       char buf[32];
+
+       if (boot_params.hdr.version < 0x0209)
+               return;
+       pa_data = boot_params.hdr.setup_data;
+       while (pa_data) {
+               data = early_ioremap(pa_data, sizeof(*data));
+               sprintf(buf, "setup data %x", data->type);
+               reserve_early(pa_data, pa_data+sizeof(*data)+data->len, buf);
+               pa_data = data->next;
+               early_iounmap(data, sizeof(*data));
+       }
+}
+
 void __init x86_64_start_kernel(char * real_mode_data)
 {
        int i;
@@ -157,6 +175,7 @@ void __init x86_64_start_kernel(char * real_mode_data)
 #endif
 
        reserve_ebda_region();
+       reserve_setup_data();
 
        /*
         * At this point everything still needed from the boot loader
index 36652ea1a2658d10d729647e0f613c01ccc88ee6..9007f9ea64eed80e9537be44d391fe55d6f7f749 100644 (file)
@@ -218,7 +218,7 @@ static void hpet_legacy_clockevent_register(void)
        hpet_freq = 1000000000000000ULL;
        do_div(hpet_freq, hpet_period);
        hpet_clockevent.mult = div_sc((unsigned long) hpet_freq,
-                                     NSEC_PER_SEC, 32);
+                                     NSEC_PER_SEC, hpet_clockevent.shift);
        /* Calculate the min / max delta */
        hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
                                                           &hpet_clockevent);
index 8540abe86ade2d0b1f3fd26ad0dff18b5733a6e1..c1b5e3ece1f241f9ef8716abd02d98ad6721ffa7 100644 (file)
@@ -115,7 +115,8 @@ void __init setup_pit_timer(void)
         * IO_APIC has been initialized.
         */
        pit_clockevent.cpumask = cpumask_of_cpu(smp_processor_id());
-       pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, 32);
+       pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
+                                    pit_clockevent.shift);
        pit_clockevent.max_delta_ns =
                clockevent_delta2ns(0x7FFF, &pit_clockevent);
        pit_clockevent.min_delta_ns =
@@ -224,7 +225,8 @@ static int __init init_pit_clocksource(void)
            pit_clockevent.mode != CLOCK_EVT_MODE_PERIODIC)
                return 0;
 
-       clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20);
+       clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE,
+                                                  clocksource_pit.shift);
        return clocksource_register(&clocksource_pit);
 }
 arch_initcall(init_pit_clocksource);
index 2e2f42074e18e0fa0de175b47325c5b895635c4d..696b8e4e66bbf89bd9b71499f549697b0f68f745 100644 (file)
@@ -2068,7 +2068,7 @@ static void __init setup_nmi(void)
  * cycles as some i82489DX-based boards have glue logic that keeps the
  * 8259A interrupt line asserted until INTA.  --macro
  */
-static inline void unlock_ExtINT_logic(void)
+static inline void __init unlock_ExtINT_logic(void)
 {
        int apic, pin, i;
        struct IO_APIC_route_entry entry0, entry1;
index 9ba11d07920f794c71e11de98d51d8430e129cf2..ef1a8dfcc529a36643bdbe34f835eb1819c5f265 100644 (file)
@@ -1599,7 +1599,7 @@ static void __init setup_nmi(void)
  * cycles as some i82489DX-based boards have glue logic that keeps the
  * 8259A interrupt line asserted until INTA.  --macro
  */
-static inline void unlock_ExtINT_logic(void)
+static inline void __init unlock_ExtINT_logic(void)
 {
        int apic, pin, i;
        struct IO_APIC_route_entry entry0, entry1;
index 6ea67b76a21452f3b7ffacdec52ae8b155f2a21a..00bda7bcda63741178db3ad46b444fe25c8b87a7 100644 (file)
@@ -134,7 +134,7 @@ unsigned int do_IRQ(struct pt_regs *regs)
                        : "=a" (arg1), "=d" (arg2), "=b" (bx)
                        :  "0" (irq),   "1" (desc),  "2" (isp),
                           "D" (desc->handle_irq)
-                       : "memory", "cc"
+                       : "memory", "cc", "ecx"
                );
        } else
 #endif
index 73354302fda76c3ee5a326e63deed6f37acca3a9..c03205991718b30da8adfed31d915f7f325b2aa0 100644 (file)
  *
  * This file is released under the GPLv2.
  */
-
 #include <linux/debugfs.h>
+#include <linux/uaccess.h>
 #include <linux/stat.h>
 #include <linux/init.h>
+#include <linux/io.h>
+#include <linux/mm.h>
 
 #include <asm/setup.h>
 
 #ifdef CONFIG_DEBUG_BOOT_PARAMS
+struct setup_data_node {
+       u64 paddr;
+       u32 type;
+       u32 len;
+};
+
+static ssize_t
+setup_data_read(struct file *file, char __user *user_buf, size_t count,
+               loff_t *ppos)
+{
+       struct setup_data_node *node = file->private_data;
+       unsigned long remain;
+       loff_t pos = *ppos;
+       struct page *pg;
+       void *p;
+       u64 pa;
+
+       if (pos < 0)
+               return -EINVAL;
+       if (pos >= node->len)
+               return 0;
+
+       if (count > node->len - pos)
+               count = node->len - pos;
+       pa = node->paddr + sizeof(struct setup_data) + pos;
+       pg = pfn_to_page((pa + count - 1) >> PAGE_SHIFT);
+       if (PageHighMem(pg)) {
+               p = ioremap_cache(pa, count);
+               if (!p)
+                       return -ENXIO;
+       } else {
+               p = __va(pa);
+       }
+
+       remain = copy_to_user(user_buf, p, count);
+
+       if (PageHighMem(pg))
+               iounmap(p);
+
+       if (remain)
+               return -EFAULT;
+
+       *ppos = pos + count;
+
+       return count;
+}
+
+static int setup_data_open(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+static const struct file_operations fops_setup_data = {
+       .read =         setup_data_read,
+       .open =         setup_data_open,
+};
+
+static int __init
+create_setup_data_node(struct dentry *parent, int no,
+                      struct setup_data_node *node)
+{
+       struct dentry *d, *type, *data;
+       char buf[16];
+       int error;
+
+       sprintf(buf, "%d", no);
+       d = debugfs_create_dir(buf, parent);
+       if (!d) {
+               error = -ENOMEM;
+               goto err_return;
+       }
+       type = debugfs_create_x32("type", S_IRUGO, d, &node->type);
+       if (!type) {
+               error = -ENOMEM;
+               goto err_dir;
+       }
+       data = debugfs_create_file("data", S_IRUGO, d, node, &fops_setup_data);
+       if (!data) {
+               error = -ENOMEM;
+               goto err_type;
+       }
+       return 0;
+
+err_type:
+       debugfs_remove(type);
+err_dir:
+       debugfs_remove(d);
+err_return:
+       return error;
+}
+
+static int __init create_setup_data_nodes(struct dentry *parent)
+{
+       struct setup_data_node *node;
+       struct setup_data *data;
+       int error, no = 0;
+       struct dentry *d;
+       struct page *pg;
+       u64 pa_data;
+
+       d = debugfs_create_dir("setup_data", parent);
+       if (!d) {
+               error = -ENOMEM;
+               goto err_return;
+       }
+
+       pa_data = boot_params.hdr.setup_data;
+
+       while (pa_data) {
+               node = kmalloc(sizeof(*node), GFP_KERNEL);
+               if (!node) {
+                       error = -ENOMEM;
+                       goto err_dir;
+               }
+               pg = pfn_to_page((pa_data+sizeof(*data)-1) >> PAGE_SHIFT);
+               if (PageHighMem(pg)) {
+                       data = ioremap_cache(pa_data, sizeof(*data));
+                       if (!data) {
+                               error = -ENXIO;
+                               goto err_dir;
+                       }
+               } else {
+                       data = __va(pa_data);
+               }
+
+               node->paddr = pa_data;
+               node->type = data->type;
+               node->len = data->len;
+               error = create_setup_data_node(d, no, node);
+               pa_data = data->next;
+
+               if (PageHighMem(pg))
+                       iounmap(data);
+               if (error)
+                       goto err_dir;
+               no++;
+       }
+       return 0;
+
+err_dir:
+       debugfs_remove(d);
+err_return:
+       return error;
+}
+
 static struct debugfs_blob_wrapper boot_params_blob = {
-       .data = &boot_params,
-       .size = sizeof(boot_params),
+       .data           = &boot_params,
+       .size           = sizeof(boot_params),
 };
 
 static int __init boot_params_kdebugfs_init(void)
 {
-       int error;
        struct dentry *dbp, *version, *data;
+       int error;
 
        dbp = debugfs_create_dir("boot_params", NULL);
        if (!dbp) {
@@ -41,7 +189,13 @@ static int __init boot_params_kdebugfs_init(void)
                error = -ENOMEM;
                goto err_version;
        }
+       error = create_setup_data_nodes(dbp);
+       if (error)
+               goto err_data;
        return 0;
+
+err_data:
+       debugfs_remove(data);
 err_version:
        debugfs_remove(version);
 err_dir:
@@ -61,5 +215,4 @@ static int __init arch_kdebugfs_init(void)
 
        return error;
 }
-
 arch_initcall(arch_kdebugfs_init);
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
new file mode 100644 (file)
index 0000000..8b7a3cf
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * KVM paravirt_ops implementation
+ *
+ * This 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (C) 2007, Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ * Copyright IBM Corporation, 2007
+ *   Authors: Anthony Liguori <aliguori@us.ibm.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/kvm_para.h>
+#include <linux/cpu.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/hardirq.h>
+
+#define MMU_QUEUE_SIZE 1024
+
+struct kvm_para_state {
+       u8 mmu_queue[MMU_QUEUE_SIZE];
+       int mmu_queue_len;
+       enum paravirt_lazy_mode mode;
+};
+
+static DEFINE_PER_CPU(struct kvm_para_state, para_state);
+
+static struct kvm_para_state *kvm_para_state(void)
+{
+       return &per_cpu(para_state, raw_smp_processor_id());
+}
+
+/*
+ * No need for any "IO delay" on KVM
+ */
+static void kvm_io_delay(void)
+{
+}
+
+static void kvm_mmu_op(void *buffer, unsigned len)
+{
+       int r;
+       unsigned long a1, a2;
+
+       do {
+               a1 = __pa(buffer);
+               a2 = 0;   /* on i386 __pa() always returns <4G */
+               r = kvm_hypercall3(KVM_HC_MMU_OP, len, a1, a2);
+               buffer += r;
+               len -= r;
+       } while (len);
+}
+
+static void mmu_queue_flush(struct kvm_para_state *state)
+{
+       if (state->mmu_queue_len) {
+               kvm_mmu_op(state->mmu_queue, state->mmu_queue_len);
+               state->mmu_queue_len = 0;
+       }
+}
+
+static void kvm_deferred_mmu_op(void *buffer, int len)
+{
+       struct kvm_para_state *state = kvm_para_state();
+
+       if (state->mode != PARAVIRT_LAZY_MMU) {
+               kvm_mmu_op(buffer, len);
+               return;
+       }
+       if (state->mmu_queue_len + len > sizeof state->mmu_queue)
+               mmu_queue_flush(state);
+       memcpy(state->mmu_queue + state->mmu_queue_len, buffer, len);
+       state->mmu_queue_len += len;
+}
+
+static void kvm_mmu_write(void *dest, u64 val)
+{
+       __u64 pte_phys;
+       struct kvm_mmu_op_write_pte wpte;
+
+#ifdef CONFIG_HIGHPTE
+       struct page *page;
+       unsigned long dst = (unsigned long) dest;
+
+       page = kmap_atomic_to_page(dest);
+       pte_phys = page_to_pfn(page);
+       pte_phys <<= PAGE_SHIFT;
+       pte_phys += (dst & ~(PAGE_MASK));
+#else
+       pte_phys = (unsigned long)__pa(dest);
+#endif
+       wpte.header.op = KVM_MMU_OP_WRITE_PTE;
+       wpte.pte_val = val;
+       wpte.pte_phys = pte_phys;
+
+       kvm_deferred_mmu_op(&wpte, sizeof wpte);
+}
+
+/*
+ * We only need to hook operations that are MMU writes.  We hook these so that
+ * we can use lazy MMU mode to batch these operations.  We could probably
+ * improve the performance of the host code if we used some of the information
+ * here to simplify processing of batched writes.
+ */
+static void kvm_set_pte(pte_t *ptep, pte_t pte)
+{
+       kvm_mmu_write(ptep, pte_val(pte));
+}
+
+static void kvm_set_pte_at(struct mm_struct *mm, unsigned long addr,
+                          pte_t *ptep, pte_t pte)
+{
+       kvm_mmu_write(ptep, pte_val(pte));
+}
+
+static void kvm_set_pmd(pmd_t *pmdp, pmd_t pmd)
+{
+       kvm_mmu_write(pmdp, pmd_val(pmd));
+}
+
+#if PAGETABLE_LEVELS >= 3
+#ifdef CONFIG_X86_PAE
+static void kvm_set_pte_atomic(pte_t *ptep, pte_t pte)
+{
+       kvm_mmu_write(ptep, pte_val(pte));
+}
+
+static void kvm_set_pte_present(struct mm_struct *mm, unsigned long addr,
+                               pte_t *ptep, pte_t pte)
+{
+       kvm_mmu_write(ptep, pte_val(pte));
+}
+
+static void kvm_pte_clear(struct mm_struct *mm,
+                         unsigned long addr, pte_t *ptep)
+{
+       kvm_mmu_write(ptep, 0);
+}
+
+static void kvm_pmd_clear(pmd_t *pmdp)
+{
+       kvm_mmu_write(pmdp, 0);
+}
+#endif
+
+static void kvm_set_pud(pud_t *pudp, pud_t pud)
+{
+       kvm_mmu_write(pudp, pud_val(pud));
+}
+
+#if PAGETABLE_LEVELS == 4
+static void kvm_set_pgd(pgd_t *pgdp, pgd_t pgd)
+{
+       kvm_mmu_write(pgdp, pgd_val(pgd));
+}
+#endif
+#endif /* PAGETABLE_LEVELS >= 3 */
+
+static void kvm_flush_tlb(void)
+{
+       struct kvm_mmu_op_flush_tlb ftlb = {
+               .header.op = KVM_MMU_OP_FLUSH_TLB,
+       };
+
+       kvm_deferred_mmu_op(&ftlb, sizeof ftlb);
+}
+
+static void kvm_release_pt(u32 pfn)
+{
+       struct kvm_mmu_op_release_pt rpt = {
+               .header.op = KVM_MMU_OP_RELEASE_PT,
+               .pt_phys = (u64)pfn << PAGE_SHIFT,
+       };
+
+       kvm_mmu_op(&rpt, sizeof rpt);
+}
+
+static void kvm_enter_lazy_mmu(void)
+{
+       struct kvm_para_state *state = kvm_para_state();
+
+       paravirt_enter_lazy_mmu();
+       state->mode = paravirt_get_lazy_mode();
+}
+
+static void kvm_leave_lazy_mmu(void)
+{
+       struct kvm_para_state *state = kvm_para_state();
+
+       mmu_queue_flush(state);
+       paravirt_leave_lazy(paravirt_get_lazy_mode());
+       state->mode = paravirt_get_lazy_mode();
+}
+
+static void paravirt_ops_setup(void)
+{
+       pv_info.name = "KVM";
+       pv_info.paravirt_enabled = 1;
+
+       if (kvm_para_has_feature(KVM_FEATURE_NOP_IO_DELAY))
+               pv_cpu_ops.io_delay = kvm_io_delay;
+
+       if (kvm_para_has_feature(KVM_FEATURE_MMU_OP)) {
+               pv_mmu_ops.set_pte = kvm_set_pte;
+               pv_mmu_ops.set_pte_at = kvm_set_pte_at;
+               pv_mmu_ops.set_pmd = kvm_set_pmd;
+#if PAGETABLE_LEVELS >= 3
+#ifdef CONFIG_X86_PAE
+               pv_mmu_ops.set_pte_atomic = kvm_set_pte_atomic;
+               pv_mmu_ops.set_pte_present = kvm_set_pte_present;
+               pv_mmu_ops.pte_clear = kvm_pte_clear;
+               pv_mmu_ops.pmd_clear = kvm_pmd_clear;
+#endif
+               pv_mmu_ops.set_pud = kvm_set_pud;
+#if PAGETABLE_LEVELS == 4
+               pv_mmu_ops.set_pgd = kvm_set_pgd;
+#endif
+#endif
+               pv_mmu_ops.flush_tlb_user = kvm_flush_tlb;
+               pv_mmu_ops.release_pte = kvm_release_pt;
+               pv_mmu_ops.release_pmd = kvm_release_pt;
+               pv_mmu_ops.release_pud = kvm_release_pt;
+
+               pv_mmu_ops.lazy_mode.enter = kvm_enter_lazy_mmu;
+               pv_mmu_ops.lazy_mode.leave = kvm_leave_lazy_mmu;
+       }
+}
+
+void __init kvm_guest_init(void)
+{
+       if (!kvm_para_available())
+               return;
+
+       paravirt_ops_setup();
+}
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
new file mode 100644 (file)
index 0000000..ddee040
--- /dev/null
@@ -0,0 +1,187 @@
+/*  KVM paravirtual clock driver. A clocksource implementation
+    Copyright (C) 2008 Glauber de Oliveira Costa, Red Hat 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, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <linux/clocksource.h>
+#include <linux/kvm_para.h>
+#include <asm/arch_hooks.h>
+#include <asm/msr.h>
+#include <asm/apic.h>
+#include <linux/percpu.h>
+#include <asm/reboot.h>
+
+#define KVM_SCALE 22
+
+static int kvmclock = 1;
+
+static int parse_no_kvmclock(char *arg)
+{
+       kvmclock = 0;
+       return 0;
+}
+early_param("no-kvmclock", parse_no_kvmclock);
+
+/* The hypervisor will put information about time periodically here */
+static DEFINE_PER_CPU_SHARED_ALIGNED(struct kvm_vcpu_time_info, hv_clock);
+#define get_clock(cpu, field) per_cpu(hv_clock, cpu).field
+
+static inline u64 kvm_get_delta(u64 last_tsc)
+{
+       int cpu = smp_processor_id();
+       u64 delta = native_read_tsc() - last_tsc;
+       return (delta * get_clock(cpu, tsc_to_system_mul)) >> KVM_SCALE;
+}
+
+static struct kvm_wall_clock wall_clock;
+static cycle_t kvm_clock_read(void);
+/*
+ * The wallclock is the time of day when we booted. Since then, some time may
+ * have elapsed since the hypervisor wrote the data. So we try to account for
+ * that with system time
+ */
+unsigned long kvm_get_wallclock(void)
+{
+       u32 wc_sec, wc_nsec;
+       u64 delta;
+       struct timespec ts;
+       int version, nsec;
+       int low, high;
+
+       low = (int)__pa(&wall_clock);
+       high = ((u64)__pa(&wall_clock) >> 32);
+
+       delta = kvm_clock_read();
+
+       native_write_msr(MSR_KVM_WALL_CLOCK, low, high);
+       do {
+               version = wall_clock.wc_version;
+               rmb();
+               wc_sec = wall_clock.wc_sec;
+               wc_nsec = wall_clock.wc_nsec;
+               rmb();
+       } while ((wall_clock.wc_version != version) || (version & 1));
+
+       delta = kvm_clock_read() - delta;
+       delta += wc_nsec;
+       nsec = do_div(delta, NSEC_PER_SEC);
+       set_normalized_timespec(&ts, wc_sec + delta, nsec);
+       /*
+        * Of all mechanisms of time adjustment I've tested, this one
+        * was the champion!
+        */
+       return ts.tv_sec + 1;
+}
+
+int kvm_set_wallclock(unsigned long now)
+{
+       return 0;
+}
+
+/*
+ * This is our read_clock function. The host puts an tsc timestamp each time
+ * it updates a new time. Without the tsc adjustment, we can have a situation
+ * in which a vcpu starts to run earlier (smaller system_time), but probes
+ * time later (compared to another vcpu), leading to backwards time
+ */
+static cycle_t kvm_clock_read(void)
+{
+       u64 last_tsc, now;
+       int cpu;
+
+       preempt_disable();
+       cpu = smp_processor_id();
+
+       last_tsc = get_clock(cpu, tsc_timestamp);
+       now = get_clock(cpu, system_time);
+
+       now += kvm_get_delta(last_tsc);
+       preempt_enable();
+
+       return now;
+}
+static struct clocksource kvm_clock = {
+       .name = "kvm-clock",
+       .read = kvm_clock_read,
+       .rating = 400,
+       .mask = CLOCKSOURCE_MASK(64),
+       .mult = 1 << KVM_SCALE,
+       .shift = KVM_SCALE,
+       .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int kvm_register_clock(void)
+{
+       int cpu = smp_processor_id();
+       int low, high;
+       low = (int)__pa(&per_cpu(hv_clock, cpu)) | 1;
+       high = ((u64)__pa(&per_cpu(hv_clock, cpu)) >> 32);
+
+       return native_write_msr_safe(MSR_KVM_SYSTEM_TIME, low, high);
+}
+
+static void kvm_setup_secondary_clock(void)
+{
+       /*
+        * Now that the first cpu already had this clocksource initialized,
+        * we shouldn't fail.
+        */
+       WARN_ON(kvm_register_clock());
+       /* ok, done with our trickery, call native */
+       setup_secondary_APIC_clock();
+}
+
+/*
+ * After the clock is registered, the host will keep writing to the
+ * registered memory location. If the guest happens to shutdown, this memory
+ * won't be valid. In cases like kexec, in which you install a new kernel, this
+ * means a random memory location will be kept being written. So before any
+ * kind of shutdown from our side, we unregister the clock by writting anything
+ * that does not have the 'enable' bit set in the msr
+ */
+#ifdef CONFIG_KEXEC
+static void kvm_crash_shutdown(struct pt_regs *regs)
+{
+       native_write_msr_safe(MSR_KVM_SYSTEM_TIME, 0, 0);
+       native_machine_crash_shutdown(regs);
+}
+#endif
+
+static void kvm_shutdown(void)
+{
+       native_write_msr_safe(MSR_KVM_SYSTEM_TIME, 0, 0);
+       native_machine_shutdown();
+}
+
+void __init kvmclock_init(void)
+{
+       if (!kvm_para_available())
+               return;
+
+       if (kvmclock && kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE)) {
+               if (kvm_register_clock())
+                       return;
+               pv_time_ops.get_wallclock = kvm_get_wallclock;
+               pv_time_ops.set_wallclock = kvm_set_wallclock;
+               pv_time_ops.sched_clock = kvm_clock_read;
+               pv_apic_ops.setup_secondary_clock = kvm_setup_secondary_clock;
+               machine_ops.shutdown  = kvm_shutdown;
+#ifdef CONFIG_KEXEC
+               machine_ops.crash_shutdown  = kvm_crash_shutdown;
+#endif
+               clocksource_register(&kvm_clock);
+       }
+}
index b402c0f3f192213f84595197f067c28043545ea1..cfc2648d25ff924e704b9316286f5cca1bae3049 100644 (file)
@@ -364,7 +364,8 @@ int __init mfgpt_timer_setup(void)
        geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, val);
 
        /* Set up the clock event */
-       mfgpt_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC, 32);
+       mfgpt_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC,
+                                      mfgpt_clockevent.shift);
        mfgpt_clockevent.min_delta_ns = clockevent_delta2ns(0xF,
                        &mfgpt_clockevent);
        mfgpt_clockevent.max_delta_ns = clockevent_delta2ns(0xFFFE,
index 70744e344fa1f7541e249299f1a056d2689cf7c3..3e2c54dc8b29f2e907021bf84d55081b5f65ffa6 100644 (file)
@@ -686,13 +686,11 @@ void __init get_smp_config(void)
 static int __init smp_scan_config(unsigned long base, unsigned long length,
                                  unsigned reserve)
 {
-       extern void __bad_mpf_size(void);
        unsigned int *bp = phys_to_virt(base);
        struct intel_mp_floating *mpf;
 
        Dprintk("Scan SMP from %p for %ld bytes.\n", bp, length);
-       if (sizeof(*mpf) != 16)
-               __bad_mpf_size();
+       BUILD_BUG_ON(sizeof(*mpf) != 16);
 
        while (length > 0) {
                mpf = (struct intel_mp_floating *)bp;
@@ -801,7 +799,6 @@ void __init find_smp_config(void)
 #ifdef CONFIG_X86_IO_APIC
 
 #define MP_ISA_BUS             0
-#define MP_MAX_IOAPIC_PIN      127
 
 extern struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS];
 
@@ -820,7 +817,7 @@ static int mp_find_ioapic(int gsi)
        return -1;
 }
 
-static u8 uniq_ioapic_id(u8 id)
+static u8 __init uniq_ioapic_id(u8 id)
 {
 #ifdef CONFIG_X86_32
        if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
@@ -909,14 +906,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
        intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;     /* APIC ID */
        intsrc.mpc_dstirq = pin;        /* INTIN# */
 
-       Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n",
-               intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3,
-               (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus,
-               intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq);
-
-       mp_irqs[mp_irq_entries] = intsrc;
-       if (++mp_irq_entries == MAX_IRQ_SOURCES)
-               panic("Max # of irq sources exceeded!\n");
+       MP_intsrc_info(&intsrc);
 }
 
 int es7000_plat;
@@ -985,23 +975,14 @@ void __init mp_config_acpi_legacy_irqs(void)
                intsrc.mpc_srcbusirq = i;       /* Identity mapped */
                intsrc.mpc_dstirq = i;
 
-               Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, "
-                       "%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3,
-                       (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus,
-                       intsrc.mpc_srcbusirq, intsrc.mpc_dstapic,
-                       intsrc.mpc_dstirq);
-
-               mp_irqs[mp_irq_entries] = intsrc;
-               if (++mp_irq_entries == MAX_IRQ_SOURCES)
-                       panic("Max # of irq sources exceeded!\n");
+               MP_intsrc_info(&intsrc);
        }
 }
 
 int mp_register_gsi(u32 gsi, int triggering, int polarity)
 {
-       int ioapic = -1;
-       int ioapic_pin = 0;
-       int idx, bit = 0;
+       int ioapic;
+       int ioapic_pin;
 #ifdef CONFIG_X86_32
 #define MAX_GSI_NUM    4096
 #define IRQ_COMPRESSION_START  64
@@ -1041,15 +1022,13 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
         * with redundant pin->gsi mappings (but unique PCI devices);
         * we only program the IOAPIC on the first.
         */
-       bit = ioapic_pin % 32;
-       idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
-       if (idx > 3) {
+       if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
                printk(KERN_ERR "Invalid reference to IOAPIC pin "
                       "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
                       ioapic_pin);
                return gsi;
        }
-       if ((1 << bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
+       if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) {
                Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
                        mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
 #ifdef CONFIG_X86_32
@@ -1059,7 +1038,7 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
 #endif
        }
 
-       mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1 << bit);
+       set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed);
 #ifdef CONFIG_X86_32
        /*
         * For GSI >= 64, use IRQ compression
index 3733412d135773846c1b7259de4dc8dfbed99c46..74f0c5ea2a0388af848faa058804cd9df86f4391 100644 (file)
@@ -366,11 +366,13 @@ struct pv_mmu_ops pv_mmu_ops = {
        .flush_tlb_single = native_flush_tlb_single,
        .flush_tlb_others = native_flush_tlb_others,
 
-       .alloc_pt = paravirt_nop,
-       .alloc_pd = paravirt_nop,
-       .alloc_pd_clone = paravirt_nop,
-       .release_pt = paravirt_nop,
-       .release_pd = paravirt_nop,
+       .alloc_pte = paravirt_nop,
+       .alloc_pmd = paravirt_nop,
+       .alloc_pmd_clone = paravirt_nop,
+       .alloc_pud = paravirt_nop,
+       .release_pte = paravirt_nop,
+       .release_pmd = paravirt_nop,
+       .release_pud = paravirt_nop,
 
        .set_pte = native_set_pte,
        .set_pte_at = native_set_pte_at,
index 2edee22e9c307610f71b47799c792ea8009713be..e28ec497e142f49cc4847f833ff5a5f8f96833f6 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/rio.h>
+#include <asm/bios_ebda.h>
 
 #ifdef CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT
 int use_calgary __read_mostly = 1;
index 3004d716539dde2b882acd4e0576676531382965..67e9b4a1e89d5a1ac3a3851beaab9d48bbe22c0b 100644 (file)
@@ -4,6 +4,8 @@
 #include <linux/smp.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/pm.h>
 
 struct kmem_cache *task_xstate_cachep;
 
@@ -42,3 +44,118 @@ void arch_task_cache_init(void)
                                  __alignof__(union thread_xstate),
                                  SLAB_PANIC, NULL);
 }
+
+static void do_nothing(void *unused)
+{
+}
+
+/*
+ * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
+ * pm_idle and update to new pm_idle value. Required while changing pm_idle
+ * handler on SMP systems.
+ *
+ * Caller must have changed pm_idle to the new value before the call. Old
+ * pm_idle value will not be used by any CPU after the return of this function.
+ */
+void cpu_idle_wait(void)
+{
+       smp_mb();
+       /* kick all the CPUs so that they exit out of pm_idle */
+       smp_call_function(do_nothing, NULL, 0, 1);
+}
+EXPORT_SYMBOL_GPL(cpu_idle_wait);
+
+/*
+ * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
+ * which can obviate IPI to trigger checking of need_resched.
+ * We execute MONITOR against need_resched and enter optimized wait state
+ * through MWAIT. Whenever someone changes need_resched, we would be woken
+ * up from MWAIT (without an IPI).
+ *
+ * New with Core Duo processors, MWAIT can take some hints based on CPU
+ * capability.
+ */
+void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
+{
+       if (!need_resched()) {
+               __monitor((void *)&current_thread_info()->flags, 0, 0);
+               smp_mb();
+               if (!need_resched())
+                       __mwait(ax, cx);
+       }
+}
+
+/* Default MONITOR/MWAIT with no hints, used for default C1 state */
+static void mwait_idle(void)
+{
+       if (!need_resched()) {
+               __monitor((void *)&current_thread_info()->flags, 0, 0);
+               smp_mb();
+               if (!need_resched())
+                       __sti_mwait(0, 0);
+               else
+                       local_irq_enable();
+       } else
+               local_irq_enable();
+}
+
+
+static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c)
+{
+       if (force_mwait)
+               return 1;
+       /* Any C1 states supported? */
+       return c->cpuid_level >= 5 && ((cpuid_edx(5) >> 4) & 0xf) > 0;
+}
+
+/*
+ * On SMP it's slightly faster (but much more power-consuming!)
+ * to poll the ->work.need_resched flag instead of waiting for the
+ * cross-CPU IPI to arrive. Use this option with caution.
+ */
+static void poll_idle(void)
+{
+       local_irq_enable();
+       cpu_relax();
+}
+
+void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
+{
+       static int selected;
+
+       if (selected)
+               return;
+#ifdef CONFIG_X86_SMP
+       if (pm_idle == poll_idle && smp_num_siblings > 1) {
+               printk(KERN_WARNING "WARNING: polling idle and HT enabled,"
+                       " performance may degrade.\n");
+       }
+#endif
+       if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) {
+               /*
+                * Skip, if setup has overridden idle.
+                * One CPU supports mwait => All CPUs supports mwait
+                */
+               if (!pm_idle) {
+                       printk(KERN_INFO "using mwait in idle threads.\n");
+                       pm_idle = mwait_idle;
+               }
+       }
+       selected = 1;
+}
+
+static int __init idle_setup(char *str)
+{
+       if (!strcmp(str, "poll")) {
+               printk("using polling idle threads.\n");
+               pm_idle = poll_idle;
+       } else if (!strcmp(str, "mwait"))
+               force_mwait = 1;
+       else
+               return -1;
+
+       boot_option_idle_override = 1;
+       return 0;
+}
+early_param("idle", idle_setup);
+
index 7adad088e373fbf4bf5523dcf70f22665331b105..f8476dfbb60d9818f5da08d3a5b95a223930964f 100644 (file)
@@ -111,12 +111,10 @@ void default_idle(void)
                 */
                smp_mb();
 
-               local_irq_disable();
-               if (!need_resched()) {
+               if (!need_resched())
                        safe_halt();    /* enables interrupts racelessly */
-                       local_irq_disable();
-               }
-               local_irq_enable();
+               else
+                       local_irq_enable();
                current_thread_info()->status |= TS_POLLING;
        } else {
                local_irq_enable();
@@ -128,17 +126,6 @@ void default_idle(void)
 EXPORT_SYMBOL(default_idle);
 #endif
 
-/*
- * On SMP it's slightly faster (but much more power-consuming!)
- * to poll the ->work.need_resched flag instead of waiting for the
- * cross-CPU IPI to arrive. Use this option with caution.
- */
-static void poll_idle(void)
-{
-       local_irq_enable();
-       cpu_relax();
-}
-
 #ifdef CONFIG_HOTPLUG_CPU
 #include <asm/nmi.h>
 /* We don't actually take CPU down, just spin without interrupts. */
@@ -196,6 +183,7 @@ void cpu_idle(void)
                        if (cpu_is_offline(cpu))
                                play_dead();
 
+                       local_irq_disable();
                        __get_cpu_var(irq_stat).idle_timestamp = jiffies;
                        idle();
                }
@@ -206,104 +194,6 @@ void cpu_idle(void)
        }
 }
 
-static void do_nothing(void *unused)
-{
-}
-
-/*
- * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
- * pm_idle and update to new pm_idle value. Required while changing pm_idle
- * handler on SMP systems.
- *
- * Caller must have changed pm_idle to the new value before the call. Old
- * pm_idle value will not be used by any CPU after the return of this function.
- */
-void cpu_idle_wait(void)
-{
-       smp_mb();
-       /* kick all the CPUs so that they exit out of pm_idle */
-       smp_call_function(do_nothing, NULL, 0, 1);
-}
-EXPORT_SYMBOL_GPL(cpu_idle_wait);
-
-/*
- * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
- * which can obviate IPI to trigger checking of need_resched.
- * We execute MONITOR against need_resched and enter optimized wait state
- * through MWAIT. Whenever someone changes need_resched, we would be woken
- * up from MWAIT (without an IPI).
- *
- * New with Core Duo processors, MWAIT can take some hints based on CPU
- * capability.
- */
-void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
-{
-       if (!need_resched()) {
-               __monitor((void *)&current_thread_info()->flags, 0, 0);
-               smp_mb();
-               if (!need_resched())
-                       __sti_mwait(ax, cx);
-               else
-                       local_irq_enable();
-       } else
-               local_irq_enable();
-}
-
-/* Default MONITOR/MWAIT with no hints, used for default C1 state */
-static void mwait_idle(void)
-{
-       local_irq_enable();
-       mwait_idle_with_hints(0, 0);
-}
-
-static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c)
-{
-       if (force_mwait)
-               return 1;
-       /* Any C1 states supported? */
-       return c->cpuid_level >= 5 && ((cpuid_edx(5) >> 4) & 0xf) > 0;
-}
-
-void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
-{
-       static int selected;
-
-       if (selected)
-               return;
-#ifdef CONFIG_X86_SMP
-       if (pm_idle == poll_idle && smp_num_siblings > 1) {
-               printk(KERN_WARNING "WARNING: polling idle and HT enabled,"
-                       " performance may degrade.\n");
-       }
-#endif
-       if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) {
-               /*
-                * Skip, if setup has overridden idle.
-                * One CPU supports mwait => All CPUs supports mwait
-                */
-               if (!pm_idle) {
-                       printk(KERN_INFO "using mwait in idle threads.\n");
-                       pm_idle = mwait_idle;
-               }
-       }
-       selected = 1;
-}
-
-static int __init idle_setup(char *str)
-{
-       if (!strcmp(str, "poll")) {
-               printk("using polling idle threads.\n");
-               pm_idle = poll_idle;
-       } else if (!strcmp(str, "mwait"))
-               force_mwait = 1;
-       else
-               return -1;
-
-       boot_option_idle_override = 1;
-       return 0;
-}
-early_param("idle", idle_setup);
-
 void __show_registers(struct pt_regs *regs, int all)
 {
        unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
@@ -550,7 +440,7 @@ static void hard_enable_TSC(void)
        write_cr4(read_cr4() & ~X86_CR4_TSD);
 }
 
-void enable_TSC(void)
+static void enable_TSC(void)
 {
        preempt_disable();
        if (test_and_clear_thread_flag(TIF_NOTSC))
index 891af1a1b48a5cbf0ef303d9f1b5c5601b485869..e2319f39988b042f364a73174a0d2ac254a5b60d 100644 (file)
@@ -106,26 +106,13 @@ void default_idle(void)
         * test NEED_RESCHED:
         */
        smp_mb();
-       local_irq_disable();
-       if (!need_resched()) {
+       if (!need_resched())
                safe_halt();    /* enables interrupts racelessly */
-               local_irq_disable();
-       }
-       local_irq_enable();
+       else
+               local_irq_enable();
        current_thread_info()->status |= TS_POLLING;
 }
 
-/*
- * On SMP it's slightly faster (but much more power-consuming!)
- * to poll the ->need_resched flag instead of waiting for the
- * cross-CPU IPI to arrive. Use this option with caution.
- */
-static void poll_idle(void)
-{
-       local_irq_enable();
-       cpu_relax();
-}
-
 #ifdef CONFIG_HOTPLUG_CPU
 DECLARE_PER_CPU(int, cpu_state);
 
@@ -192,110 +179,6 @@ void cpu_idle(void)
        }
 }
 
-static void do_nothing(void *unused)
-{
-}
-
-/*
- * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
- * pm_idle and update to new pm_idle value. Required while changing pm_idle
- * handler on SMP systems.
- *
- * Caller must have changed pm_idle to the new value before the call. Old
- * pm_idle value will not be used by any CPU after the return of this function.
- */
-void cpu_idle_wait(void)
-{
-       smp_mb();
-       /* kick all the CPUs so that they exit out of pm_idle */
-       smp_call_function(do_nothing, NULL, 0, 1);
-}
-EXPORT_SYMBOL_GPL(cpu_idle_wait);
-
-/*
- * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
- * which can obviate IPI to trigger checking of need_resched.
- * We execute MONITOR against need_resched and enter optimized wait state
- * through MWAIT. Whenever someone changes need_resched, we would be woken
- * up from MWAIT (without an IPI).
- *
- * New with Core Duo processors, MWAIT can take some hints based on CPU
- * capability.
- */
-void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
-{
-       if (!need_resched()) {
-               __monitor((void *)&current_thread_info()->flags, 0, 0);
-               smp_mb();
-               if (!need_resched())
-                       __mwait(ax, cx);
-       }
-}
-
-/* Default MONITOR/MWAIT with no hints, used for default C1 state */
-static void mwait_idle(void)
-{
-       if (!need_resched()) {
-               __monitor((void *)&current_thread_info()->flags, 0, 0);
-               smp_mb();
-               if (!need_resched())
-                       __sti_mwait(0, 0);
-               else
-                       local_irq_enable();
-       } else {
-               local_irq_enable();
-       }
-}
-
-
-static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c)
-{
-       if (force_mwait)
-               return 1;
-       /* Any C1 states supported? */
-       return c->cpuid_level >= 5 && ((cpuid_edx(5) >> 4) & 0xf) > 0;
-}
-
-void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
-{
-       static int selected;
-
-       if (selected)
-               return;
-#ifdef CONFIG_X86_SMP
-       if (pm_idle == poll_idle && smp_num_siblings > 1) {
-               printk(KERN_WARNING "WARNING: polling idle and HT enabled,"
-                       " performance may degrade.\n");
-       }
-#endif
-       if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) {
-               /*
-                * Skip, if setup has overridden idle.
-                * One CPU supports mwait => All CPUs supports mwait
-                */
-               if (!pm_idle) {
-                       printk(KERN_INFO "using mwait in idle threads.\n");
-                       pm_idle = mwait_idle;
-               }
-       }
-       selected = 1;
-}
-
-static int __init idle_setup(char *str)
-{
-       if (!strcmp(str, "poll")) {
-               printk("using polling idle threads.\n");
-               pm_idle = poll_idle;
-       } else if (!strcmp(str, "mwait"))
-               force_mwait = 1;
-       else
-               return -1;
-
-       boot_option_idle_override = 1;
-       return 0;
-}
-early_param("idle", idle_setup);
-
 /* Prints also some state that isn't saved in the pt_regs */
 void __show_regs(struct pt_regs * regs)
 {
@@ -562,7 +445,7 @@ static void hard_enable_TSC(void)
        write_cr4(read_cr4() & ~X86_CR4_TSD);
 }
 
-void enable_TSC(void)
+static void enable_TSC(void)
 {
        preempt_disable();
        if (test_and_clear_thread_flag(TIF_NOTSC))
index 559c1b027417f66823d8f214b45c61f31bbb77f1..fb03ef380f0e230ebf5f3835bc7ec57e1c9fed20 100644 (file)
@@ -1207,96 +1207,15 @@ static int genregs32_set(struct task_struct *target,
        return ret;
 }
 
-static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data)
+long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
+                       compat_ulong_t caddr, compat_ulong_t cdata)
 {
-       siginfo_t __user *si = compat_alloc_user_space(sizeof(siginfo_t));
-       compat_siginfo_t __user *si32 = compat_ptr(data);
-       siginfo_t ssi;
-       int ret;
-
-       if (request == PTRACE_SETSIGINFO) {
-               memset(&ssi, 0, sizeof(siginfo_t));
-               ret = copy_siginfo_from_user32(&ssi, si32);
-               if (ret)
-                       return ret;
-               if (copy_to_user(si, &ssi, sizeof(siginfo_t)))
-                       return -EFAULT;
-       }
-       ret = sys_ptrace(request, pid, addr, (unsigned long)si);
-       if (ret)
-               return ret;
-       if (request == PTRACE_GETSIGINFO) {
-               if (copy_from_user(&ssi, si, sizeof(siginfo_t)))
-                       return -EFAULT;
-               ret = copy_siginfo_to_user32(si32, &ssi);
-       }
-       return ret;
-}
-
-asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
-{
-       struct task_struct *child;
-       struct pt_regs *childregs;
+       unsigned long addr = caddr;
+       unsigned long data = cdata;
        void __user *datap = compat_ptr(data);
        int ret;
        __u32 val;
 
-       switch (request) {
-       case PTRACE_TRACEME:
-       case PTRACE_ATTACH:
-       case PTRACE_KILL:
-       case PTRACE_CONT:
-       case PTRACE_SINGLESTEP:
-       case PTRACE_SINGLEBLOCK:
-       case PTRACE_DETACH:
-       case PTRACE_SYSCALL:
-       case PTRACE_OLDSETOPTIONS:
-       case PTRACE_SETOPTIONS:
-       case PTRACE_SET_THREAD_AREA:
-       case PTRACE_GET_THREAD_AREA:
-#ifdef X86_BTS
-       case PTRACE_BTS_CONFIG:
-       case PTRACE_BTS_STATUS:
-       case PTRACE_BTS_SIZE:
-       case PTRACE_BTS_GET:
-       case PTRACE_BTS_CLEAR:
-       case PTRACE_BTS_DRAIN:
-#endif
-               return sys_ptrace(request, pid, addr, data);
-
-       default:
-               return -EINVAL;
-
-       case PTRACE_PEEKTEXT:
-       case PTRACE_PEEKDATA:
-       case PTRACE_POKEDATA:
-       case PTRACE_POKETEXT:
-       case PTRACE_POKEUSR:
-       case PTRACE_PEEKUSR:
-       case PTRACE_GETREGS:
-       case PTRACE_SETREGS:
-       case PTRACE_SETFPREGS:
-       case PTRACE_GETFPREGS:
-       case PTRACE_SETFPXREGS:
-       case PTRACE_GETFPXREGS:
-       case PTRACE_GETEVENTMSG:
-               break;
-
-       case PTRACE_SETSIGINFO:
-       case PTRACE_GETSIGINFO:
-               return ptrace32_siginfo(request, pid, addr, data);
-       }
-
-       child = ptrace_get_task_struct(pid);
-       if (IS_ERR(child))
-               return PTR_ERR(child);
-
-       ret = ptrace_check_attach(child, request == PTRACE_KILL);
-       if (ret < 0)
-               goto out;
-
-       childregs = task_pt_regs(child);
-
        switch (request) {
        case PTRACE_PEEKUSR:
                ret = getreg32(child, addr, &val);
@@ -1343,12 +1262,14 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
                                             sizeof(struct user32_fxsr_struct),
                                             datap);
 
+       case PTRACE_GET_THREAD_AREA:
+       case PTRACE_SET_THREAD_AREA:
+               return arch_ptrace(child, request, addr, data);
+
        default:
                return compat_ptrace_request(child, request, addr, data);
        }
 
- out:
-       put_task_struct(child);
        return ret;
 }
 
index 19c9386ac1187e4f9b25144437732dc45b11a98c..a4a838306b2cc69f2856f1b8244b6045c86165c9 100644 (file)
@@ -8,6 +8,7 @@
 #include <asm/apic.h>
 #include <asm/desc.h>
 #include <asm/hpet.h>
+#include <asm/pgtable.h>
 #include <asm/reboot_fixups.h>
 #include <asm/reboot.h>
 
@@ -15,7 +16,6 @@
 # include <linux/dmi.h>
 # include <linux/ctype.h>
 # include <linux/mc146818rtc.h>
-# include <asm/pgtable.h>
 #else
 # include <asm/iommu.h>
 #endif
@@ -275,7 +275,7 @@ void machine_real_restart(unsigned char *code, int length)
        /* Remap the kernel at virtual address zero, as well as offset zero
           from the kernel segment.  This assumes the kernel segment starts at
           virtual address PAGE_OFFSET. */
-       memcpy(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
+       memcpy(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
                sizeof(swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
 
        /*
@@ -399,7 +399,7 @@ static void native_machine_emergency_restart(void)
        }
 }
 
-static void native_machine_shutdown(void)
+void native_machine_shutdown(void)
 {
        /* Stop the cpus and apics */
 #ifdef CONFIG_SMP
@@ -470,7 +470,10 @@ struct machine_ops machine_ops = {
        .shutdown = native_machine_shutdown,
        .emergency_restart = native_machine_emergency_restart,
        .restart = native_machine_restart,
-       .halt = native_machine_halt
+       .halt = native_machine_halt,
+#ifdef CONFIG_KEXEC
+       .crash_shutdown = native_machine_crash_shutdown,
+#endif
 };
 
 void machine_power_off(void)
@@ -498,3 +501,9 @@ void machine_halt(void)
        machine_ops.halt();
 }
 
+#ifdef CONFIG_KEXEC
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+       machine_ops.crash_shutdown(regs);
+}
+#endif
index 0d1f44ae6eea83b3ab32d17fe04a817227dd2acf..c0c68c18a788dff30e0103b144cb0b76a09ec775 100644 (file)
@@ -18,8 +18,6 @@ unsigned disabled_cpus __cpuinitdata;
 unsigned int boot_cpu_physical_apicid = -1U;
 EXPORT_SYMBOL(boot_cpu_physical_apicid);
 
-physid_mask_t phys_cpu_present_map;
-
 DEFINE_PER_CPU(u16, x86_cpu_to_apicid) = BAD_APICID;
 EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
 
index 78828b0f604fb387f1e847ae16f35272d51cb44a..2283422af7946fef30a86189dddb0a7a12fe3fc1 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/pfn.h>
 #include <linux/pci.h>
 #include <linux/init_ohci1394_dma.h>
+#include <linux/kvm_para.h>
 
 #include <video/edid.h>
 
@@ -389,7 +390,6 @@ unsigned long __init find_max_low_pfn(void)
        return max_low_pfn;
 }
 
-#define BIOS_EBDA_SEGMENT 0x40E
 #define BIOS_LOWMEM_KILOBYTES 0x413
 
 /*
@@ -420,8 +420,7 @@ static void __init reserve_ebda_region(void)
        lowmem <<= 10;
 
        /* start of EBDA area */
-       ebda_addr = *(unsigned short *)__va(BIOS_EBDA_SEGMENT);
-       ebda_addr <<= 4;
+       ebda_addr = get_bios_ebda();
 
        /* Fixup: bios puts an EBDA in the top 64K segment */
        /* of conventional memory, but does not adjust lowmem. */
@@ -442,7 +441,7 @@ static void __init reserve_ebda_region(void)
 }
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
-void __init setup_bootmem_allocator(void);
+static void __init setup_bootmem_allocator(void);
 static unsigned long __init setup_memory(void)
 {
        /*
@@ -477,7 +476,7 @@ static unsigned long __init setup_memory(void)
        return max_low_pfn;
 }
 
-void __init zone_sizes_init(void)
+static void __init zone_sizes_init(void)
 {
        unsigned long max_zone_pfns[MAX_NR_ZONES];
        memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
@@ -822,6 +821,10 @@ void __init setup_arch(char **cmdline_p)
 
        max_low_pfn = setup_memory();
 
+#ifdef CONFIG_KVM_CLOCK
+       kvmclock_init();
+#endif
+
 #ifdef CONFIG_VMI
        /*
         * Must be after max_low_pfn is determined, and before kernel
@@ -829,6 +832,7 @@ void __init setup_arch(char **cmdline_p)
         */
        vmi_init();
 #endif
+       kvm_guest_init();
 
        /*
         * NOTE: before this point _nobody_ is allowed to allocate
index c2ec3dcb6b991304633ed138098e974fc9ff3ff5..a94fb959a87a3f35c0eec00bdf696b195b378d30 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/ctype.h>
 #include <linux/uaccess.h>
 #include <linux/init_ohci1394_dma.h>
+#include <linux/kvm_para.h>
 
 #include <asm/mtrr.h>
 #include <asm/uaccess.h>
@@ -116,7 +117,7 @@ extern int root_mountflags;
 
 char __initdata command_line[COMMAND_LINE_SIZE];
 
-struct resource standard_io_resources[] = {
+static struct resource standard_io_resources[] = {
        { .name = "dma1", .start = 0x00, .end = 0x1f,
                .flags = IORESOURCE_BUSY | IORESOURCE_IO },
        { .name = "pic1", .start = 0x20, .end = 0x21,
@@ -190,6 +191,7 @@ contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
        bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
        e820_register_active_regions(0, start_pfn, end_pfn);
        free_bootmem_with_active_regions(0, end_pfn);
+       early_res_to_bootmem(0, end_pfn<<PAGE_SHIFT);
        reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT);
 }
 #endif
@@ -264,6 +266,28 @@ void __attribute__((weak)) __init memory_setup(void)
        machine_specific_memory_setup();
 }
 
+static void __init parse_setup_data(void)
+{
+       struct setup_data *data;
+       unsigned long pa_data;
+
+       if (boot_params.hdr.version < 0x0209)
+               return;
+       pa_data = boot_params.hdr.setup_data;
+       while (pa_data) {
+               data = early_ioremap(pa_data, PAGE_SIZE);
+               switch (data->type) {
+               default:
+                       break;
+               }
+#ifndef CONFIG_DEBUG_BOOT_PARAMS
+               free_early(pa_data, pa_data+sizeof(*data)+data->len);
+#endif
+               pa_data = data->next;
+               early_iounmap(data, PAGE_SIZE);
+       }
+}
+
 /*
  * setup_arch - architecture-specific boot-time initializations
  *
@@ -316,6 +340,8 @@ void __init setup_arch(char **cmdline_p)
        strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
        *cmdline_p = command_line;
 
+       parse_setup_data();
+
        parse_early_param();
 
 #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
@@ -359,6 +385,10 @@ void __init setup_arch(char **cmdline_p)
 
        io_delay_init();
 
+#ifdef CONFIG_KVM_CLOCK
+       kvmclock_init();
+#endif
+
 #ifdef CONFIG_SMP
        /* setup to use the early static init tables during kernel startup */
        x86_cpu_to_apicid_early_ptr = (void *)x86_cpu_to_apicid_init;
@@ -397,8 +427,6 @@ void __init setup_arch(char **cmdline_p)
        contig_initmem_init(0, end_pfn);
 #endif
 
-       early_res_to_bootmem();
-
        dma32_reserve_bootmem();
 
 #ifdef CONFIG_ACPI_SLEEP
@@ -465,6 +493,8 @@ void __init setup_arch(char **cmdline_p)
        init_apic_mappings();
        ioapic_init_mappings();
 
+       kvm_guest_init();
+
        /*
         * We trust e820 completely. No explicit ROM probing in memory.
         */
index f1b117930837cec8c55ff4f1a9ab96a0869274c1..8e05e7f7bd40cc779887c71e91769a22e572f09e 100644 (file)
@@ -413,16 +413,6 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
        regs->ss = __USER_DS;
        regs->cs = __USER_CS;
 
-       /*
-        * Clear TF when entering the signal handler, but
-        * notify any tracer that was single-stepping it.
-        * The tracer may want to single-step inside the
-        * handler too.
-        */
-       regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-
        return 0;
 
 give_sigsegv:
@@ -501,16 +491,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->ss = __USER_DS;
        regs->cs = __USER_CS;
 
-       /*
-        * Clear TF when entering the signal handler, but
-        * notify any tracer that was single-stepping it.
-        * The tracer may want to single-step inside the
-        * handler too.
-        */
-       regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-
        return 0;
 
 give_sigsegv:
@@ -566,6 +546,21 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
        if (ret)
                return ret;
 
+       /*
+        * Clear the direction flag as per the ABI for function entry.
+        */
+       regs->flags &= ~X86_EFLAGS_DF;
+
+       /*
+        * Clear TF when entering the signal handler, but
+        * notify any tracer that was single-stepping it.
+        * The tracer may want to single-step inside the
+        * handler too.
+        */
+       regs->flags &= ~X86_EFLAGS_TF;
+       if (test_thread_flag(TIF_SINGLESTEP))
+               ptrace_notify(SIGTRAP);
+
        spin_lock_irq(&current->sighand->siglock);
        sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
        if (!(ka->sa.sa_flags & SA_NODEFER))
index 827179c5b32a054ee9733b215fda94fbec8f8c48..ccb2a4560c2d91496bdbee9d35ed04d07c9f65bf 100644 (file)
@@ -285,14 +285,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
           even if the handler happens to be interrupting 32-bit code. */
        regs->cs = __USER_CS;
 
-       /* This, by contrast, has nothing to do with segment registers -
-          see include/asm-x86_64/uaccess.h for details. */
-       set_fs(USER_DS);
-
-       regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-
        return 0;
 
 give_sigsegv:
@@ -380,6 +372,28 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
        ret = setup_rt_frame(sig, ka, info, oldset, regs);
 
        if (ret == 0) {
+               /*
+                * This has nothing to do with segment registers,
+                * despite the name.  This magic affects uaccess.h
+                * macros' behavior.  Reset it to the normal setting.
+                */
+               set_fs(USER_DS);
+
+               /*
+                * Clear the direction flag as per the ABI for function entry.
+                */
+               regs->flags &= ~X86_EFLAGS_DF;
+
+               /*
+                * Clear TF when entering the signal handler, but
+                * notify any tracer that was single-stepping it.
+                * The tracer may want to single-step inside the
+                * handler too.
+                */
+               regs->flags &= ~X86_EFLAGS_TF;
+               if (test_thread_flag(TIF_SINGLESTEP))
+                       ptrace_notify(SIGTRAP);
+
                spin_lock_irq(&current->sighand->siglock);
                sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
                if (!(ka->sa.sa_flags & SA_NODEFER))
index 6a925394bc7e646e70cd17a54fd6da0710a11e80..04c662ba18f1dbf217326a9ffe2ade458617ee61 100644 (file)
@@ -184,7 +184,7 @@ static void unmap_cpu_to_node(int cpu)
 u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly =
                                        { [0 ... NR_CPUS-1] = BAD_APICID };
 
-void map_cpu_to_logical_apicid(void)
+static void map_cpu_to_logical_apicid(void)
 {
        int cpu = smp_processor_id();
        int apicid = logical_smp_processor_id();
@@ -197,7 +197,7 @@ void map_cpu_to_logical_apicid(void)
        map_cpu_to_node(cpu, node);
 }
 
-void unmap_cpu_to_logical_apicid(int cpu)
+static void unmap_cpu_to_logical_apicid(int cpu)
 {
        cpu_2_logical_apicid[cpu] = BAD_APICID;
        unmap_cpu_to_node(cpu);
@@ -211,7 +211,7 @@ void unmap_cpu_to_logical_apicid(int cpu)
  * Report back to the Boot Processor.
  * Running on AP.
  */
-void __cpuinit smp_callin(void)
+static void __cpuinit smp_callin(void)
 {
        int cpuid, phys_id;
        unsigned long timeout;
@@ -436,7 +436,7 @@ valid_k7:
 #endif
 }
 
-void __cpuinit smp_checks(void)
+static void __cpuinit smp_checks(void)
 {
        if (smp_b_stepping)
                printk(KERN_WARNING "WARNING: SMP operation may be unreliable"
@@ -565,7 +565,7 @@ void __init smp_alloc_memory(void)
 }
 #endif
 
-void impress_friends(void)
+static void impress_friends(void)
 {
        int cpu;
        unsigned long bogosum = 0;
@@ -1039,8 +1039,8 @@ int __cpuinit native_cpu_up(unsigned int cpu)
 
 #ifdef CONFIG_X86_32
        /* init low mem mapping */
-       clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
-                       min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS));
+       clone_pgd_range(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
+                       min_t(unsigned long, KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY));
        flush_tlb_all();
 #endif
 
@@ -1058,7 +1058,7 @@ int __cpuinit native_cpu_up(unsigned int cpu)
        check_tsc_sync_source(cpu);
        local_irq_restore(flags);
 
-       while (!cpu_isset(cpu, cpu_online_map)) {
+       while (!cpu_online(cpu)) {
                cpu_relax();
                touch_nmi_watchdog();
        }
@@ -1168,7 +1168,7 @@ static void __init smp_cpu_index_default(void)
        int i;
        struct cpuinfo_x86 *c;
 
-       for_each_cpu_mask(i, cpu_possible_map) {
+       for_each_possible_cpu(i) {
                c = &cpu_data(i);
                /* mark all to hotplug */
                c->cpu_index = NR_CPUS;
@@ -1287,7 +1287,7 @@ void cpu_exit_clear(void)
 }
 #  endif /* CONFIG_X86_32 */
 
-void remove_siblinginfo(int cpu)
+static void remove_siblinginfo(int cpu)
 {
        int sibling;
        struct cpuinfo_x86 *c = &cpu_data(cpu);
index 6878a9c2df5d6dbde0a80c268238fc4a072a6dbd..ae751094eba99754b47482aac7bab45d6dd40875 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <asm/io.h>
+#include <asm/bios_ebda.h>
 #include <asm/mach-summit/mach_mpparse.h>
 
 static struct rio_table_hdr *rio_table_hdr __initdata;
@@ -140,8 +141,8 @@ void __init setup_summit(void)
        int                     i, next_wpeg, next_bus = 0;
 
        /* The pointer to the EBDA is stored in the word @ phys 0x40E(40:0E) */
-       ptr = *(unsigned short *)phys_to_virt(0x40Eul);
-       ptr = (unsigned long)phys_to_virt(ptr << 4);
+       ptr = get_bios_ebda();
+       ptr = (unsigned long)phys_to_virt(ptr);
 
        rio_table_hdr = NULL;
        offset = 0x180;
index 1558e513757e4516fac196729a182657977a95f3..a1f07d7932021bf2beb0dc8d1b644272363c29c9 100644 (file)
@@ -191,13 +191,13 @@ void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
        spin_unlock(&f->tlbstate_lock);
 }
 
-int __cpuinit init_smp_flush(void)
+static int __cpuinit init_smp_flush(void)
 {
        int i;
 
-       for_each_cpu_mask(i, cpu_possible_map) {
+       for_each_possible_cpu(i)
                spin_lock_init(&per_cpu(flush_state, i).tlbstate_lock);
-       }
+
        return 0;
 }
 core_initcall(init_smp_flush);
index 64580679861e60371112b9d032d51f6d87c04a96..d8ccc3c6552f60f85bd50de1d4e6c68548261ae7 100644 (file)
@@ -33,7 +33,7 @@
 
 /* We can free up trampoline after bootup if cpu hotplug is not supported. */
 #ifndef CONFIG_HOTPLUG_CPU
-.section ".init.data","aw",@progbits
+.section ".cpuinit.data","aw",@progbits
 #else
 .section .rodata,"a",@progbits
 #endif
index 471e694d6713193baa5a25dac995f177ef34abf2..bde6f63e15d5dcb900afbd34199561f026bea553 100644 (file)
@@ -602,7 +602,7 @@ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
 DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
 DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0, 0)
-DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0, 1)
+DO_ERROR_INFO(32, SIGILL, "iret exception", iret_error, ILL_BADSTK, 0, 1)
 
 void __kprobes do_general_protection(struct pt_regs *regs, long error_code)
 {
index 12affe1f9bce8d7da1a872880bf41e581e3281c7..956f38927aa7c5533cc41fd3c2ba0ea807ccb6dd 100644 (file)
@@ -320,7 +320,7 @@ static void check_zeroed_page(u32 pfn, int type, struct page *page)
         * pdes need to be zeroed.
         */
        if (type & VMI_PAGE_CLONE)
-               limit = USER_PTRS_PER_PGD;
+               limit = KERNEL_PGD_BOUNDARY;
        for (i = 0; i < limit; i++)
                BUG_ON(ptr[i]);
 }
@@ -392,13 +392,13 @@ static void *vmi_kmap_atomic_pte(struct page *page, enum km_type type)
 }
 #endif
 
-static void vmi_allocate_pt(struct mm_struct *mm, u32 pfn)
+static void vmi_allocate_pte(struct mm_struct *mm, u32 pfn)
 {
        vmi_set_page_type(pfn, VMI_PAGE_L1);
        vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0);
 }
 
-static void vmi_allocate_pd(struct mm_struct *mm, u32 pfn)
+static void vmi_allocate_pmd(struct mm_struct *mm, u32 pfn)
 {
        /*
         * This call comes in very early, before mem_map is setup.
@@ -409,20 +409,20 @@ static void vmi_allocate_pd(struct mm_struct *mm, u32 pfn)
        vmi_ops.allocate_page(pfn, VMI_PAGE_L2, 0, 0, 0);
 }
 
-static void vmi_allocate_pd_clone(u32 pfn, u32 clonepfn, u32 start, u32 count)
+static void vmi_allocate_pmd_clone(u32 pfn, u32 clonepfn, u32 start, u32 count)
 {
        vmi_set_page_type(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE);
        vmi_check_page_type(clonepfn, VMI_PAGE_L2);
        vmi_ops.allocate_page(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE, clonepfn, start, count);
 }
 
-static void vmi_release_pt(u32 pfn)
+static void vmi_release_pte(u32 pfn)
 {
        vmi_ops.release_page(pfn, VMI_PAGE_L1);
        vmi_set_page_type(pfn, VMI_PAGE_NORMAL);
 }
 
-static void vmi_release_pd(u32 pfn)
+static void vmi_release_pmd(u32 pfn)
 {
        vmi_ops.release_page(pfn, VMI_PAGE_L2);
        vmi_set_page_type(pfn, VMI_PAGE_NORMAL);
@@ -871,15 +871,15 @@ static inline int __init activate_vmi(void)
 
        vmi_ops.allocate_page = vmi_get_function(VMI_CALL_AllocatePage);
        if (vmi_ops.allocate_page) {
-               pv_mmu_ops.alloc_pt = vmi_allocate_pt;
-               pv_mmu_ops.alloc_pd = vmi_allocate_pd;
-               pv_mmu_ops.alloc_pd_clone = vmi_allocate_pd_clone;
+               pv_mmu_ops.alloc_pte = vmi_allocate_pte;
+               pv_mmu_ops.alloc_pmd = vmi_allocate_pmd;
+               pv_mmu_ops.alloc_pmd_clone = vmi_allocate_pmd_clone;
        }
 
        vmi_ops.release_page = vmi_get_function(VMI_CALL_ReleasePage);
        if (vmi_ops.release_page) {
-               pv_mmu_ops.release_pt = vmi_release_pt;
-               pv_mmu_ops.release_pd = vmi_release_pd;
+               pv_mmu_ops.release_pte = vmi_release_pte;
+               pv_mmu_ops.release_pmd = vmi_release_pmd;
        }
 
        /* Set linear is needed in all cases */
index edff4c9854854429fda22ce2d35f7f08fa64c593..61efa2f7d5645c804bba44bf524661133bc15374 100644 (file)
@@ -216,7 +216,7 @@ vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
        return 0;
 }
 
-long __vsyscall(3) venosys_1(void)
+static long __vsyscall(3) venosys_1(void)
 {
        return -ENOSYS;
 }
index 41962e793c0fe9f122d22517956535875ea1170f..8d45fabc5f3baf556b1da2558a42df183ab09e80 100644 (file)
@@ -19,7 +19,7 @@ if VIRTUALIZATION
 
 config KVM
        tristate "Kernel-based Virtual Machine (KVM) support"
-       depends on HAVE_KVM && EXPERIMENTAL
+       depends on HAVE_KVM
        select PREEMPT_NOTIFIERS
        select ANON_INODES
        ---help---
@@ -50,6 +50,17 @@ config KVM_AMD
          Provides support for KVM on AMD processors equipped with the AMD-V
          (SVM) extensions.
 
+config KVM_TRACE
+       bool "KVM trace support"
+       depends on KVM && MARKERS && SYSFS
+       select RELAY
+       select DEBUG_FS
+       default n
+       ---help---
+         This option allows reading a trace of kvm-related events through
+         relayfs.  Note the ABI is not considered stable and will be
+         modified in future updates.
+
 # OK, it's a little counter-intuitive to do this, but it puts it neatly under
 # the virtualization menu.
 source drivers/lguest/Kconfig
index ffdd0b310784059527a4837ca040400c170db0d2..c97d35c218dbe0ad4827776ff30c20e13d107852 100644 (file)
@@ -3,10 +3,14 @@
 #
 
 common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o)
+ifeq ($(CONFIG_KVM_TRACE),y)
+common-objs += $(addprefix ../../../virt/kvm/, kvm_trace.o)
+endif
 
 EXTRA_CFLAGS += -Ivirt/kvm -Iarch/x86/kvm
 
-kvm-objs := $(common-objs) x86.o mmu.o x86_emulate.o i8259.o irq.o lapic.o
+kvm-objs := $(common-objs) x86.o mmu.o x86_emulate.o i8259.o irq.o lapic.o \
+       i8254.o
 obj-$(CONFIG_KVM) += kvm.o
 kvm-intel-objs = vmx.o
 obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
new file mode 100644 (file)
index 0000000..361e316
--- /dev/null
@@ -0,0 +1,611 @@
+/*
+ * 8253/8254 interval timer emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2006 Intel Corporation
+ * Copyright (c) 2007 Keir Fraser, XenSource Inc
+ * Copyright (c) 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * Authors:
+ *   Sheng Yang <sheng.yang@intel.com>
+ *   Based on QEMU and Xen.
+ */
+
+#include <linux/kvm_host.h>
+
+#include "irq.h"
+#include "i8254.h"
+
+#ifndef CONFIG_X86_64
+#define mod_64(x, y) ((x) - (y) * div64_64(x, y))
+#else
+#define mod_64(x, y) ((x) % (y))
+#endif
+
+#define RW_STATE_LSB 1
+#define RW_STATE_MSB 2
+#define RW_STATE_WORD0 3
+#define RW_STATE_WORD1 4
+
+/* Compute with 96 bit intermediate result: (a*b)/c */
+static u64 muldiv64(u64 a, u32 b, u32 c)
+{
+       union {
+               u64 ll;
+               struct {
+                       u32 low, high;
+               } l;
+       } u, res;
+       u64 rl, rh;
+
+       u.ll = a;
+       rl = (u64)u.l.low * (u64)b;
+       rh = (u64)u.l.high * (u64)b;
+       rh += (rl >> 32);
+       res.l.high = div64_64(rh, c);
+       res.l.low = div64_64(((mod_64(rh, c) << 32) + (rl & 0xffffffff)), c);
+       return res.ll;
+}
+
+static void pit_set_gate(struct kvm *kvm, int channel, u32 val)
+{
+       struct kvm_kpit_channel_state *c =
+               &kvm->arch.vpit->pit_state.channels[channel];
+
+       WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
+
+       switch (c->mode) {
+       default:
+       case 0:
+       case 4:
+               /* XXX: just disable/enable counting */
+               break;
+       case 1:
+       case 2:
+       case 3:
+       case 5:
+               /* Restart counting on rising edge. */
+               if (c->gate < val)
+                       c->count_load_time = ktime_get();
+               break;
+       }
+
+       c->gate = val;
+}
+
+int pit_get_gate(struct kvm *kvm, int channel)
+{
+       WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
+
+       return kvm->arch.vpit->pit_state.channels[channel].gate;
+}
+
+static int pit_get_count(struct kvm *kvm, int channel)
+{
+       struct kvm_kpit_channel_state *c =
+               &kvm->arch.vpit->pit_state.channels[channel];
+       s64 d, t;
+       int counter;
+
+       WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
+
+       t = ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time));
+       d = muldiv64(t, KVM_PIT_FREQ, NSEC_PER_SEC);
+
+       switch (c->mode) {
+       case 0:
+       case 1:
+       case 4:
+       case 5:
+               counter = (c->count - d) & 0xffff;
+               break;
+       case 3:
+               /* XXX: may be incorrect for odd counts */
+               counter = c->count - (mod_64((2 * d), c->count));
+               break;
+       default:
+               counter = c->count - mod_64(d, c->count);
+               break;
+       }
+       return counter;
+}
+
+static int pit_get_out(struct kvm *kvm, int channel)
+{
+       struct kvm_kpit_channel_state *c =
+               &kvm->arch.vpit->pit_state.channels[channel];
+       s64 d, t;
+       int out;
+
+       WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
+
+       t = ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time));
+       d = muldiv64(t, KVM_PIT_FREQ, NSEC_PER_SEC);
+
+       switch (c->mode) {
+       default:
+       case 0:
+               out = (d >= c->count);
+               break;
+       case 1:
+               out = (d < c->count);
+               break;
+       case 2:
+               out = ((mod_64(d, c->count) == 0) && (d != 0));
+               break;
+       case 3:
+               out = (mod_64(d, c->count) < ((c->count + 1) >> 1));
+               break;
+       case 4:
+       case 5:
+               out = (d == c->count);
+               break;
+       }
+
+       return out;
+}
+
+static void pit_latch_count(struct kvm *kvm, int channel)
+{
+       struct kvm_kpit_channel_state *c =
+               &kvm->arch.vpit->pit_state.channels[channel];
+
+       WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
+
+       if (!c->count_latched) {
+               c->latched_count = pit_get_count(kvm, channel);
+               c->count_latched = c->rw_mode;
+       }
+}
+
+static void pit_latch_status(struct kvm *kvm, int channel)
+{
+       struct kvm_kpit_channel_state *c =
+               &kvm->arch.vpit->pit_state.channels[channel];
+
+       WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
+
+       if (!c->status_latched) {
+               /* TODO: Return NULL COUNT (bit 6). */
+               c->status = ((pit_get_out(kvm, channel) << 7) |
+                               (c->rw_mode << 4) |
+                               (c->mode << 1) |
+                               c->bcd);
+               c->status_latched = 1;
+       }
+}
+
+int __pit_timer_fn(struct kvm_kpit_state *ps)
+{
+       struct kvm_vcpu *vcpu0 = ps->pit->kvm->vcpus[0];
+       struct kvm_kpit_timer *pt = &ps->pit_timer;
+
+       atomic_inc(&pt->pending);
+       smp_mb__after_atomic_inc();
+       /* FIXME: handle case where the guest is in guest mode */
+       if (vcpu0 && waitqueue_active(&vcpu0->wq)) {
+               vcpu0->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+               wake_up_interruptible(&vcpu0->wq);
+       }
+
+       pt->timer.expires = ktime_add_ns(pt->timer.expires, pt->period);
+       pt->scheduled = ktime_to_ns(pt->timer.expires);
+
+       return (pt->period == 0 ? 0 : 1);
+}
+
+int pit_has_pending_timer(struct kvm_vcpu *vcpu)
+{
+       struct kvm_pit *pit = vcpu->kvm->arch.vpit;
+
+       if (pit && vcpu->vcpu_id == 0)
+               return atomic_read(&pit->pit_state.pit_timer.pending);
+
+       return 0;
+}
+
+static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
+{
+       struct kvm_kpit_state *ps;
+       int restart_timer = 0;
+
+       ps = container_of(data, struct kvm_kpit_state, pit_timer.timer);
+
+       restart_timer = __pit_timer_fn(ps);
+
+       if (restart_timer)
+               return HRTIMER_RESTART;
+       else
+               return HRTIMER_NORESTART;
+}
+
+static void destroy_pit_timer(struct kvm_kpit_timer *pt)
+{
+       pr_debug("pit: execute del timer!\n");
+       hrtimer_cancel(&pt->timer);
+}
+
+static void create_pit_timer(struct kvm_kpit_timer *pt, u32 val, int is_period)
+{
+       s64 interval;
+
+       interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ);
+
+       pr_debug("pit: create pit timer, interval is %llu nsec\n", interval);
+
+       /* TODO The new value only affected after the retriggered */
+       hrtimer_cancel(&pt->timer);
+       pt->period = (is_period == 0) ? 0 : interval;
+       pt->timer.function = pit_timer_fn;
+       atomic_set(&pt->pending, 0);
+
+       hrtimer_start(&pt->timer, ktime_add_ns(ktime_get(), interval),
+                     HRTIMER_MODE_ABS);
+}
+
+static void pit_load_count(struct kvm *kvm, int channel, u32 val)
+{
+       struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
+
+       WARN_ON(!mutex_is_locked(&ps->lock));
+
+       pr_debug("pit: load_count val is %d, channel is %d\n", val, channel);
+
+       /*
+        * Though spec said the state of 8254 is undefined after power-up,
+        * seems some tricky OS like Windows XP depends on IRQ0 interrupt
+        * when booting up.
+        * So here setting initialize rate for it, and not a specific number
+        */
+       if (val == 0)
+               val = 0x10000;
+
+       ps->channels[channel].count_load_time = ktime_get();
+       ps->channels[channel].count = val;
+
+       if (channel != 0)
+               return;
+
+       /* Two types of timer
+        * mode 1 is one shot, mode 2 is period, otherwise del timer */
+       switch (ps->channels[0].mode) {
+       case 1:
+               create_pit_timer(&ps->pit_timer, val, 0);
+               break;
+       case 2:
+               create_pit_timer(&ps->pit_timer, val, 1);
+               break;
+       default:
+               destroy_pit_timer(&ps->pit_timer);
+       }
+}
+
+void kvm_pit_load_count(struct kvm *kvm, int channel, u32 val)
+{
+       mutex_lock(&kvm->arch.vpit->pit_state.lock);
+       pit_load_count(kvm, channel, val);
+       mutex_unlock(&kvm->arch.vpit->pit_state.lock);
+}
+
+static void pit_ioport_write(struct kvm_io_device *this,
+                            gpa_t addr, int len, const void *data)
+{
+       struct kvm_pit *pit = (struct kvm_pit *)this->private;
+       struct kvm_kpit_state *pit_state = &pit->pit_state;
+       struct kvm *kvm = pit->kvm;
+       int channel, access;
+       struct kvm_kpit_channel_state *s;
+       u32 val = *(u32 *) data;
+
+       val  &= 0xff;
+       addr &= KVM_PIT_CHANNEL_MASK;
+
+       mutex_lock(&pit_state->lock);
+
+       if (val != 0)
+               pr_debug("pit: write addr is 0x%x, len is %d, val is 0x%x\n",
+                         (unsigned int)addr, len, val);
+
+       if (addr == 3) {
+               channel = val >> 6;
+               if (channel == 3) {
+                       /* Read-Back Command. */
+                       for (channel = 0; channel < 3; channel++) {
+                               s = &pit_state->channels[channel];
+                               if (val & (2 << channel)) {
+                                       if (!(val & 0x20))
+                                               pit_latch_count(kvm, channel);
+                                       if (!(val & 0x10))
+                                               pit_latch_status(kvm, channel);
+                               }
+                       }
+               } else {
+                       /* Select Counter <channel>. */
+                       s = &pit_state->channels[channel];
+                       access = (val >> 4) & KVM_PIT_CHANNEL_MASK;
+                       if (access == 0) {
+                               pit_latch_count(kvm, channel);
+                       } else {
+                               s->rw_mode = access;
+                               s->read_state = access;
+                               s->write_state = access;
+                               s->mode = (val >> 1) & 7;
+                               if (s->mode > 5)
+                                       s->mode -= 4;
+                               s->bcd = val & 1;
+                       }
+               }
+       } else {
+               /* Write Count. */
+               s = &pit_state->channels[addr];
+               switch (s->write_state) {
+               default:
+               case RW_STATE_LSB:
+                       pit_load_count(kvm, addr, val);
+                       break;
+               case RW_STATE_MSB:
+                       pit_load_count(kvm, addr, val << 8);
+                       break;
+               case RW_STATE_WORD0:
+                       s->write_latch = val;
+                       s->write_state = RW_STATE_WORD1;
+                       break;
+               case RW_STATE_WORD1:
+                       pit_load_count(kvm, addr, s->write_latch | (val << 8));
+                       s->write_state = RW_STATE_WORD0;
+                       break;
+               }
+       }
+
+       mutex_unlock(&pit_state->lock);
+}
+
+static void pit_ioport_read(struct kvm_io_device *this,
+                           gpa_t addr, int len, void *data)
+{
+       struct kvm_pit *pit = (struct kvm_pit *)this->private;
+       struct kvm_kpit_state *pit_state = &pit->pit_state;
+       struct kvm *kvm = pit->kvm;
+       int ret, count;
+       struct kvm_kpit_channel_state *s;
+
+       addr &= KVM_PIT_CHANNEL_MASK;
+       s = &pit_state->channels[addr];
+
+       mutex_lock(&pit_state->lock);
+
+       if (s->status_latched) {
+               s->status_latched = 0;
+               ret = s->status;
+       } else if (s->count_latched) {
+               switch (s->count_latched) {
+               default:
+               case RW_STATE_LSB:
+                       ret = s->latched_count & 0xff;
+                       s->count_latched = 0;
+                       break;
+               case RW_STATE_MSB:
+                       ret = s->latched_count >> 8;
+                       s->count_latched = 0;
+                       break;
+               case RW_STATE_WORD0:
+                       ret = s->latched_count & 0xff;
+                       s->count_latched = RW_STATE_MSB;
+                       break;
+               }
+       } else {
+               switch (s->read_state) {
+               default:
+               case RW_STATE_LSB:
+                       count = pit_get_count(kvm, addr);
+                       ret = count & 0xff;
+                       break;
+               case RW_STATE_MSB:
+                       count = pit_get_count(kvm, addr);
+                       ret = (count >> 8) & 0xff;
+                       break;
+               case RW_STATE_WORD0:
+                       count = pit_get_count(kvm, addr);
+                       ret = count & 0xff;
+                       s->read_state = RW_STATE_WORD1;
+                       break;
+               case RW_STATE_WORD1:
+                       count = pit_get_count(kvm, addr);
+                       ret = (count >> 8) & 0xff;
+                       s->read_state = RW_STATE_WORD0;
+                       break;
+               }
+       }
+
+       if (len > sizeof(ret))
+               len = sizeof(ret);
+       memcpy(data, (char *)&ret, len);
+
+       mutex_unlock(&pit_state->lock);
+}
+
+static int pit_in_range(struct kvm_io_device *this, gpa_t addr)
+{
+       return ((addr >= KVM_PIT_BASE_ADDRESS) &&
+               (addr < KVM_PIT_BASE_ADDRESS + KVM_PIT_MEM_LENGTH));
+}
+
+static void speaker_ioport_write(struct kvm_io_device *this,
+                                gpa_t addr, int len, const void *data)
+{
+       struct kvm_pit *pit = (struct kvm_pit *)this->private;
+       struct kvm_kpit_state *pit_state = &pit->pit_state;
+       struct kvm *kvm = pit->kvm;
+       u32 val = *(u32 *) data;
+
+       mutex_lock(&pit_state->lock);
+       pit_state->speaker_data_on = (val >> 1) & 1;
+       pit_set_gate(kvm, 2, val & 1);
+       mutex_unlock(&pit_state->lock);
+}
+
+static void speaker_ioport_read(struct kvm_io_device *this,
+                               gpa_t addr, int len, void *data)
+{
+       struct kvm_pit *pit = (struct kvm_pit *)this->private;
+       struct kvm_kpit_state *pit_state = &pit->pit_state;
+       struct kvm *kvm = pit->kvm;
+       unsigned int refresh_clock;
+       int ret;
+
+       /* Refresh clock toggles at about 15us. We approximate as 2^14ns. */
+       refresh_clock = ((unsigned int)ktime_to_ns(ktime_get()) >> 14) & 1;
+
+       mutex_lock(&pit_state->lock);
+       ret = ((pit_state->speaker_data_on << 1) | pit_get_gate(kvm, 2) |
+               (pit_get_out(kvm, 2) << 5) | (refresh_clock << 4));
+       if (len > sizeof(ret))
+               len = sizeof(ret);
+       memcpy(data, (char *)&ret, len);
+       mutex_unlock(&pit_state->lock);
+}
+
+static int speaker_in_range(struct kvm_io_device *this, gpa_t addr)
+{
+       return (addr == KVM_SPEAKER_BASE_ADDRESS);
+}
+
+void kvm_pit_reset(struct kvm_pit *pit)
+{
+       int i;
+       struct kvm_kpit_channel_state *c;
+
+       mutex_lock(&pit->pit_state.lock);
+       for (i = 0; i < 3; i++) {
+               c = &pit->pit_state.channels[i];
+               c->mode = 0xff;
+               c->gate = (i != 2);
+               pit_load_count(pit->kvm, i, 0);
+       }
+       mutex_unlock(&pit->pit_state.lock);
+
+       atomic_set(&pit->pit_state.pit_timer.pending, 0);
+       pit->pit_state.inject_pending = 1;
+}
+
+struct kvm_pit *kvm_create_pit(struct kvm *kvm)
+{
+       struct kvm_pit *pit;
+       struct kvm_kpit_state *pit_state;
+
+       pit = kzalloc(sizeof(struct kvm_pit), GFP_KERNEL);
+       if (!pit)
+               return NULL;
+
+       mutex_init(&pit->pit_state.lock);
+       mutex_lock(&pit->pit_state.lock);
+
+       /* Initialize PIO device */
+       pit->dev.read = pit_ioport_read;
+       pit->dev.write = pit_ioport_write;
+       pit->dev.in_range = pit_in_range;
+       pit->dev.private = pit;
+       kvm_io_bus_register_dev(&kvm->pio_bus, &pit->dev);
+
+       pit->speaker_dev.read = speaker_ioport_read;
+       pit->speaker_dev.write = speaker_ioport_write;
+       pit->speaker_dev.in_range = speaker_in_range;
+       pit->speaker_dev.private = pit;
+       kvm_io_bus_register_dev(&kvm->pio_bus, &pit->speaker_dev);
+
+       kvm->arch.vpit = pit;
+       pit->kvm = kvm;
+
+       pit_state = &pit->pit_state;
+       pit_state->pit = pit;
+       hrtimer_init(&pit_state->pit_timer.timer,
+                    CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+       mutex_unlock(&pit->pit_state.lock);
+
+       kvm_pit_reset(pit);
+
+       return pit;
+}
+
+void kvm_free_pit(struct kvm *kvm)
+{
+       struct hrtimer *timer;
+
+       if (kvm->arch.vpit) {
+               mutex_lock(&kvm->arch.vpit->pit_state.lock);
+               timer = &kvm->arch.vpit->pit_state.pit_timer.timer;
+               hrtimer_cancel(timer);
+               mutex_unlock(&kvm->arch.vpit->pit_state.lock);
+               kfree(kvm->arch.vpit);
+       }
+}
+
+void __inject_pit_timer_intr(struct kvm *kvm)
+{
+       mutex_lock(&kvm->lock);
+       kvm_ioapic_set_irq(kvm->arch.vioapic, 0, 1);
+       kvm_ioapic_set_irq(kvm->arch.vioapic, 0, 0);
+       kvm_pic_set_irq(pic_irqchip(kvm), 0, 1);
+       kvm_pic_set_irq(pic_irqchip(kvm), 0, 0);
+       mutex_unlock(&kvm->lock);
+}
+
+void kvm_inject_pit_timer_irqs(struct kvm_vcpu *vcpu)
+{
+       struct kvm_pit *pit = vcpu->kvm->arch.vpit;
+       struct kvm *kvm = vcpu->kvm;
+       struct kvm_kpit_state *ps;
+
+       if (vcpu && pit) {
+               ps = &pit->pit_state;
+
+               /* Try to inject pending interrupts when:
+                * 1. Pending exists
+                * 2. Last interrupt was accepted or waited for too long time*/
+               if (atomic_read(&ps->pit_timer.pending) &&
+                   (ps->inject_pending ||
+                   (jiffies - ps->last_injected_time
+                               >= KVM_MAX_PIT_INTR_INTERVAL))) {
+                       ps->inject_pending = 0;
+                       __inject_pit_timer_intr(kvm);
+                       ps->last_injected_time = jiffies;
+               }
+       }
+}
+
+void kvm_pit_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
+{
+       struct kvm_arch *arch = &vcpu->kvm->arch;
+       struct kvm_kpit_state *ps;
+
+       if (vcpu && arch->vpit) {
+               ps = &arch->vpit->pit_state;
+               if (atomic_read(&ps->pit_timer.pending) &&
+               (((arch->vpic->pics[0].imr & 1) == 0 &&
+                 arch->vpic->pics[0].irq_base == vec) ||
+                 (arch->vioapic->redirtbl[0].fields.vector == vec &&
+                 arch->vioapic->redirtbl[0].fields.mask != 1))) {
+                       ps->inject_pending = 1;
+                       atomic_dec(&ps->pit_timer.pending);
+                       ps->channels[0].count_load_time = ktime_get();
+               }
+       }
+}
diff --git a/arch/x86/kvm/i8254.h b/arch/x86/kvm/i8254.h
new file mode 100644 (file)
index 0000000..db25c2a
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef __I8254_H
+#define __I8254_H
+
+#include "iodev.h"
+
+struct kvm_kpit_timer {
+       struct hrtimer timer;
+       int irq;
+       s64 period; /* unit: ns */
+       s64 scheduled;
+       ktime_t last_update;
+       atomic_t pending;
+};
+
+struct kvm_kpit_channel_state {
+       u32 count; /* can be 65536 */
+       u16 latched_count;
+       u8 count_latched;
+       u8 status_latched;
+       u8 status;
+       u8 read_state;
+       u8 write_state;
+       u8 write_latch;
+       u8 rw_mode;
+       u8 mode;
+       u8 bcd; /* not supported */
+       u8 gate; /* timer start */
+       ktime_t count_load_time;
+};
+
+struct kvm_kpit_state {
+       struct kvm_kpit_channel_state channels[3];
+       struct kvm_kpit_timer pit_timer;
+       u32    speaker_data_on;
+       struct mutex lock;
+       struct kvm_pit *pit;
+       bool inject_pending; /* if inject pending interrupts */
+       unsigned long last_injected_time;
+};
+
+struct kvm_pit {
+       unsigned long base_addresss;
+       struct kvm_io_device dev;
+       struct kvm_io_device speaker_dev;
+       struct kvm *kvm;
+       struct kvm_kpit_state pit_state;
+};
+
+#define KVM_PIT_BASE_ADDRESS       0x40
+#define KVM_SPEAKER_BASE_ADDRESS    0x61
+#define KVM_PIT_MEM_LENGTH         4
+#define KVM_PIT_FREQ               1193181
+#define KVM_MAX_PIT_INTR_INTERVAL   HZ / 100
+#define KVM_PIT_CHANNEL_MASK       0x3
+
+void kvm_inject_pit_timer_irqs(struct kvm_vcpu *vcpu);
+void kvm_pit_timer_intr_post(struct kvm_vcpu *vcpu, int vec);
+void kvm_pit_load_count(struct kvm *kvm, int channel, u32 val);
+struct kvm_pit *kvm_create_pit(struct kvm *kvm);
+void kvm_free_pit(struct kvm *kvm);
+void kvm_pit_reset(struct kvm_pit *pit);
+
+#endif
index e5714759e97fcee29989eda9a262fef7cd5183fb..ce1f583459b1f4875db0d3eeea72d728aa0a9873 100644 (file)
 #include <linux/kvm_host.h>
 
 #include "irq.h"
+#include "i8254.h"
+
+/*
+ * check if there are pending timer events
+ * to be processed.
+ */
+int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
+{
+       int ret;
+
+       ret = pit_has_pending_timer(vcpu);
+       ret |= apic_has_pending_timer(vcpu);
+
+       return ret;
+}
+EXPORT_SYMBOL(kvm_cpu_has_pending_timer);
 
 /*
  * check if there is pending interrupt without
@@ -66,6 +82,7 @@ EXPORT_SYMBOL_GPL(kvm_cpu_get_interrupt);
 void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu)
 {
        kvm_inject_apic_timer_irqs(vcpu);
+       kvm_inject_pit_timer_irqs(vcpu);
        /* TODO: PIT, RTC etc. */
 }
 EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs);
@@ -73,6 +90,7 @@ EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs);
 void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
 {
        kvm_apic_timer_intr_post(vcpu, vec);
+       kvm_pit_timer_intr_post(vcpu, vec);
        /* TODO: PIT, RTC etc. */
 }
 EXPORT_SYMBOL_GPL(kvm_timer_intr_post);
index fa5ed5d59b5da9fa83529b42e09301f25f97f87a..1802134b836fc352529f59e6fd7b82b81ef28e95 100644 (file)
@@ -85,4 +85,7 @@ void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu);
 void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu);
 void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu);
 
+int pit_has_pending_timer(struct kvm_vcpu *vcpu);
+int apic_has_pending_timer(struct kvm_vcpu *vcpu);
+
 #endif
index ecdfe97e4635393eb0df2ba755ffd0150443e7dd..65ef0fc2c036ab15527e4abb04a9f2b3ca12eb4f 100644 (file)
@@ -39,6 +39,8 @@ struct vcpu_svm {
        unsigned long host_db_regs[NUM_DB_REGS];
        unsigned long host_dr6;
        unsigned long host_dr7;
+
+       u32 *msrpm;
 };
 
 #endif
index 68a6b1511934760e97117080166f78b9a7d5ab72..57ac4e4c556a5a3ca5bc79a8acbd1e35f3f33d9d 100644 (file)
@@ -338,10 +338,10 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
                } else
                        apic_clear_vector(vector, apic->regs + APIC_TMR);
 
-               if (vcpu->arch.mp_state == VCPU_MP_STATE_RUNNABLE)
+               if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
                        kvm_vcpu_kick(vcpu);
-               else if (vcpu->arch.mp_state == VCPU_MP_STATE_HALTED) {
-                       vcpu->arch.mp_state = VCPU_MP_STATE_RUNNABLE;
+               else if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED) {
+                       vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
                        if (waitqueue_active(&vcpu->wq))
                                wake_up_interruptible(&vcpu->wq);
                }
@@ -362,11 +362,11 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
 
        case APIC_DM_INIT:
                if (level) {
-                       if (vcpu->arch.mp_state == VCPU_MP_STATE_RUNNABLE)
+                       if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
                                printk(KERN_DEBUG
                                       "INIT on a runnable vcpu %d\n",
                                       vcpu->vcpu_id);
-                       vcpu->arch.mp_state = VCPU_MP_STATE_INIT_RECEIVED;
+                       vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
                        kvm_vcpu_kick(vcpu);
                } else {
                        printk(KERN_DEBUG
@@ -379,9 +379,9 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
        case APIC_DM_STARTUP:
                printk(KERN_DEBUG "SIPI to vcpu %d vector 0x%02x\n",
                       vcpu->vcpu_id, vector);
-               if (vcpu->arch.mp_state == VCPU_MP_STATE_INIT_RECEIVED) {
+               if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
                        vcpu->arch.sipi_vector = vector;
-                       vcpu->arch.mp_state = VCPU_MP_STATE_SIPI_RECEIVED;
+                       vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED;
                        if (waitqueue_active(&vcpu->wq))
                                wake_up_interruptible(&vcpu->wq);
                }
@@ -658,7 +658,7 @@ static void start_apic_timer(struct kvm_lapic *apic)
        apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
                           PRIx64 ", "
                           "timer initial count 0x%x, period %lldns, "
-                          "expire @ 0x%016" PRIx64 ".\n", __FUNCTION__,
+                          "expire @ 0x%016" PRIx64 ".\n", __func__,
                           APIC_BUS_CYCLE_NS, ktime_to_ns(now),
                           apic_get_reg(apic, APIC_TMICT),
                           apic->timer.period,
@@ -691,7 +691,7 @@ static void apic_mmio_write(struct kvm_io_device *this,
        /* too common printing */
        if (offset != APIC_EOI)
                apic_debug("%s: offset 0x%x with length 0x%x, and value is "
-                          "0x%x\n", __FUNCTION__, offset, len, val);
+                          "0x%x\n", __func__, offset, len, val);
 
        offset &= 0xff0;
 
@@ -822,6 +822,7 @@ void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
        apic_set_tpr(apic, ((cr8 & 0x0f) << 4)
                     | (apic_get_reg(apic, APIC_TASKPRI) & 4));
 }
+EXPORT_SYMBOL_GPL(kvm_lapic_set_tpr);
 
 u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu)
 {
@@ -869,7 +870,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
        struct kvm_lapic *apic;
        int i;
 
-       apic_debug("%s\n", __FUNCTION__);
+       apic_debug("%s\n", __func__);
 
        ASSERT(vcpu);
        apic = vcpu->arch.apic;
@@ -907,7 +908,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
        apic_update_ppr(apic);
 
        apic_debug(KERN_INFO "%s: vcpu=%p, id=%d, base_msr="
-                  "0x%016" PRIx64 ", base_address=0x%0lx.\n", __FUNCTION__,
+                  "0x%016" PRIx64 ", base_address=0x%0lx.\n", __func__,
                   vcpu, kvm_apic_id(apic),
                   vcpu->arch.apic_base, apic->base_address);
 }
@@ -940,7 +941,7 @@ static int __apic_timer_fn(struct kvm_lapic *apic)
 
        atomic_inc(&apic->timer.pending);
        if (waitqueue_active(q)) {
-               apic->vcpu->arch.mp_state = VCPU_MP_STATE_RUNNABLE;
+               apic->vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
                wake_up_interruptible(q);
        }
        if (apic_lvtt_period(apic)) {
@@ -952,6 +953,16 @@ static int __apic_timer_fn(struct kvm_lapic *apic)
        return result;
 }
 
+int apic_has_pending_timer(struct kvm_vcpu *vcpu)
+{
+       struct kvm_lapic *lapic = vcpu->arch.apic;
+
+       if (lapic)
+               return atomic_read(&lapic->timer.pending);
+
+       return 0;
+}
+
 static int __inject_apic_timer_irq(struct kvm_lapic *apic)
 {
        int vector;
index e55af12e11b7aeb523ff0296d7e525d2f7a33a6d..2ad6f5481671997c24c420b31fce7c9d67b31794 100644 (file)
 #include <linux/highmem.h>
 #include <linux/module.h>
 #include <linux/swap.h>
+#include <linux/hugetlb.h>
+#include <linux/compiler.h>
 
 #include <asm/page.h>
 #include <asm/cmpxchg.h>
 #include <asm/io.h>
 
+/*
+ * When setting this variable to true it enables Two-Dimensional-Paging
+ * where the hardware walks 2 page tables:
+ * 1. the guest-virtual to guest-physical
+ * 2. while doing 1. it walks guest-physical to host-physical
+ * If the hardware supports that we don't need to do shadow paging.
+ */
+bool tdp_enabled = false;
+
 #undef MMU_DEBUG
 
 #undef AUDIT
@@ -101,8 +112,6 @@ static int dbg = 1;
 #define PT_FIRST_AVAIL_BITS_SHIFT 9
 #define PT64_SECOND_AVAIL_BITS_SHIFT 52
 
-#define PT_SHADOW_IO_MARK (1ULL << PT_FIRST_AVAIL_BITS_SHIFT)
-
 #define VALID_PAGE(x) ((x) != INVALID_PAGE)
 
 #define PT64_LEVEL_BITS 9
@@ -159,6 +168,13 @@ static int dbg = 1;
 #define ACC_USER_MASK    PT_USER_MASK
 #define ACC_ALL          (ACC_EXEC_MASK | ACC_WRITE_MASK | ACC_USER_MASK)
 
+struct kvm_pv_mmu_op_buffer {
+       void *ptr;
+       unsigned len;
+       unsigned processed;
+       char buf[512] __aligned(sizeof(long));
+};
+
 struct kvm_rmap_desc {
        u64 *shadow_ptes[RMAP_EXT];
        struct kvm_rmap_desc *more;
@@ -200,11 +216,15 @@ static int is_present_pte(unsigned long pte)
 
 static int is_shadow_present_pte(u64 pte)
 {
-       pte &= ~PT_SHADOW_IO_MARK;
        return pte != shadow_trap_nonpresent_pte
                && pte != shadow_notrap_nonpresent_pte;
 }
 
+static int is_large_pte(u64 pte)
+{
+       return pte & PT_PAGE_SIZE_MASK;
+}
+
 static int is_writeble_pte(unsigned long pte)
 {
        return pte & PT_WRITABLE_MASK;
@@ -215,14 +235,14 @@ static int is_dirty_pte(unsigned long pte)
        return pte & PT_DIRTY_MASK;
 }
 
-static int is_io_pte(unsigned long pte)
+static int is_rmap_pte(u64 pte)
 {
-       return pte & PT_SHADOW_IO_MARK;
+       return is_shadow_present_pte(pte);
 }
 
-static int is_rmap_pte(u64 pte)
+static pfn_t spte_to_pfn(u64 pte)
 {
-       return is_shadow_present_pte(pte);
+       return (pte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
 }
 
 static gfn_t pse36_gfn_delta(u32 gpte)
@@ -348,17 +368,101 @@ static void mmu_free_rmap_desc(struct kvm_rmap_desc *rd)
        kfree(rd);
 }
 
+/*
+ * Return the pointer to the largepage write count for a given
+ * gfn, handling slots that are not large page aligned.
+ */
+static int *slot_largepage_idx(gfn_t gfn, struct kvm_memory_slot *slot)
+{
+       unsigned long idx;
+
+       idx = (gfn / KVM_PAGES_PER_HPAGE) -
+             (slot->base_gfn / KVM_PAGES_PER_HPAGE);
+       return &slot->lpage_info[idx].write_count;
+}
+
+static void account_shadowed(struct kvm *kvm, gfn_t gfn)
+{
+       int *write_count;
+
+       write_count = slot_largepage_idx(gfn, gfn_to_memslot(kvm, gfn));
+       *write_count += 1;
+       WARN_ON(*write_count > KVM_PAGES_PER_HPAGE);
+}
+
+static void unaccount_shadowed(struct kvm *kvm, gfn_t gfn)
+{
+       int *write_count;
+
+       write_count = slot_largepage_idx(gfn, gfn_to_memslot(kvm, gfn));
+       *write_count -= 1;
+       WARN_ON(*write_count < 0);
+}
+
+static int has_wrprotected_page(struct kvm *kvm, gfn_t gfn)
+{
+       struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn);
+       int *largepage_idx;
+
+       if (slot) {
+               largepage_idx = slot_largepage_idx(gfn, slot);
+               return *largepage_idx;
+       }
+
+       return 1;
+}
+
+static int host_largepage_backed(struct kvm *kvm, gfn_t gfn)
+{
+       struct vm_area_struct *vma;
+       unsigned long addr;
+
+       addr = gfn_to_hva(kvm, gfn);
+       if (kvm_is_error_hva(addr))
+               return 0;
+
+       vma = find_vma(current->mm, addr);
+       if (vma && is_vm_hugetlb_page(vma))
+               return 1;
+
+       return 0;
+}
+
+static int is_largepage_backed(struct kvm_vcpu *vcpu, gfn_t large_gfn)
+{
+       struct kvm_memory_slot *slot;
+
+       if (has_wrprotected_page(vcpu->kvm, large_gfn))
+               return 0;
+
+       if (!host_largepage_backed(vcpu->kvm, large_gfn))
+               return 0;
+
+       slot = gfn_to_memslot(vcpu->kvm, large_gfn);
+       if (slot && slot->dirty_bitmap)
+               return 0;
+
+       return 1;
+}
+
 /*
  * Take gfn and return the reverse mapping to it.
  * Note: gfn must be unaliased before this function get called
  */
 
-static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn)
+static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn, int lpage)
 {
        struct kvm_memory_slot *slot;
+       unsigned long idx;
 
        slot = gfn_to_memslot(kvm, gfn);
-       return &slot->rmap[gfn - slot->base_gfn];
+       if (!lpage)
+               return &slot->rmap[gfn - slot->base_gfn];
+
+       idx = (gfn / KVM_PAGES_PER_HPAGE) -
+             (slot->base_gfn / KVM_PAGES_PER_HPAGE);
+
+       return &slot->lpage_info[idx].rmap_pde;
 }
 
 /*
@@ -370,7 +474,7 @@ static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn)
  * If rmapp bit zero is one, (then rmap & ~1) points to a struct kvm_rmap_desc
  * containing more mappings.
  */
-static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
+static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
 {
        struct kvm_mmu_page *sp;
        struct kvm_rmap_desc *desc;
@@ -382,7 +486,7 @@ static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
        gfn = unalias_gfn(vcpu->kvm, gfn);
        sp = page_header(__pa(spte));
        sp->gfns[spte - sp->spt] = gfn;
-       rmapp = gfn_to_rmap(vcpu->kvm, gfn);
+       rmapp = gfn_to_rmap(vcpu->kvm, gfn, lpage);
        if (!*rmapp) {
                rmap_printk("rmap_add: %p %llx 0->1\n", spte, *spte);
                *rmapp = (unsigned long)spte;
@@ -435,20 +539,21 @@ static void rmap_remove(struct kvm *kvm, u64 *spte)
        struct kvm_rmap_desc *desc;
        struct kvm_rmap_desc *prev_desc;
        struct kvm_mmu_page *sp;
-       struct page *page;
+       pfn_t pfn;
        unsigned long *rmapp;
        int i;
 
        if (!is_rmap_pte(*spte))
                return;
        sp = page_header(__pa(spte));
-       page = pfn_to_page((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT);
-       mark_page_accessed(page);
+       pfn = spte_to_pfn(*spte);
+       if (*spte & PT_ACCESSED_MASK)
+               kvm_set_pfn_accessed(pfn);
        if (is_writeble_pte(*spte))
-               kvm_release_page_dirty(page);
+               kvm_release_pfn_dirty(pfn);
        else
-               kvm_release_page_clean(page);
-       rmapp = gfn_to_rmap(kvm, sp->gfns[spte - sp->spt]);
+               kvm_release_pfn_clean(pfn);
+       rmapp = gfn_to_rmap(kvm, sp->gfns[spte - sp->spt], is_large_pte(*spte));
        if (!*rmapp) {
                printk(KERN_ERR "rmap_remove: %p %llx 0->BUG\n", spte, *spte);
                BUG();
@@ -514,7 +619,7 @@ static void rmap_write_protect(struct kvm *kvm, u64 gfn)
        int write_protected = 0;
 
        gfn = unalias_gfn(kvm, gfn);
-       rmapp = gfn_to_rmap(kvm, gfn);
+       rmapp = gfn_to_rmap(kvm, gfn, 0);
 
        spte = rmap_next(kvm, rmapp, NULL);
        while (spte) {
@@ -527,8 +632,35 @@ static void rmap_write_protect(struct kvm *kvm, u64 gfn)
                }
                spte = rmap_next(kvm, rmapp, spte);
        }
+       if (write_protected) {
+               pfn_t pfn;
+
+               spte = rmap_next(kvm, rmapp, NULL);
+               pfn = spte_to_pfn(*spte);
+               kvm_set_pfn_dirty(pfn);
+       }
+
+       /* check for huge page mappings */
+       rmapp = gfn_to_rmap(kvm, gfn, 1);
+       spte = rmap_next(kvm, rmapp, NULL);
+       while (spte) {
+               BUG_ON(!spte);
+               BUG_ON(!(*spte & PT_PRESENT_MASK));
+               BUG_ON((*spte & (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK)) != (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK));
+               pgprintk("rmap_write_protect(large): spte %p %llx %lld\n", spte, *spte, gfn);
+               if (is_writeble_pte(*spte)) {
+                       rmap_remove(kvm, spte);
+                       --kvm->stat.lpages;
+                       set_shadow_pte(spte, shadow_trap_nonpresent_pte);
+                       write_protected = 1;
+               }
+               spte = rmap_next(kvm, rmapp, spte);
+       }
+
        if (write_protected)
                kvm_flush_remote_tlbs(kvm);
+
+       account_shadowed(kvm, gfn);
 }
 
 #ifdef MMU_DEBUG
@@ -538,8 +670,8 @@ static int is_empty_shadow_page(u64 *spt)
        u64 *end;
 
        for (pos = spt, end = pos + PAGE_SIZE / sizeof(u64); pos != end; pos++)
-               if ((*pos & ~PT_SHADOW_IO_MARK) != shadow_trap_nonpresent_pte) {
-                       printk(KERN_ERR "%s: %p %llx\n", __FUNCTION__,
+               if (*pos != shadow_trap_nonpresent_pte) {
+                       printk(KERN_ERR "%s: %p %llx\n", __func__,
                               pos, *pos);
                        return 0;
                }
@@ -559,7 +691,7 @@ static void kvm_mmu_free_page(struct kvm *kvm, struct kvm_mmu_page *sp)
 
 static unsigned kvm_page_table_hashfn(gfn_t gfn)
 {
-       return gfn;
+       return gfn & ((1 << KVM_MMU_HASH_SHIFT) - 1);
 }
 
 static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu,
@@ -662,13 +794,14 @@ static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm, gfn_t gfn)
        struct kvm_mmu_page *sp;
        struct hlist_node *node;
 
-       pgprintk("%s: looking for gfn %lx\n", __FUNCTION__, gfn);
-       index = kvm_page_table_hashfn(gfn) % KVM_NUM_MMU_PAGES;
+       pgprintk("%s: looking for gfn %lx\n", __func__, gfn);
+       index = kvm_page_table_hashfn(gfn);
        bucket = &kvm->arch.mmu_page_hash[index];
        hlist_for_each_entry(sp, node, bucket, hash_link)
-               if (sp->gfn == gfn && !sp->role.metaphysical) {
+               if (sp->gfn == gfn && !sp->role.metaphysical
+                   && !sp->role.invalid) {
                        pgprintk("%s: found role %x\n",
-                                __FUNCTION__, sp->role.word);
+                                __func__, sp->role.word);
                        return sp;
                }
        return NULL;
@@ -699,27 +832,27 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
                quadrant &= (1 << ((PT32_PT_BITS - PT64_PT_BITS) * level)) - 1;
                role.quadrant = quadrant;
        }
-       pgprintk("%s: looking gfn %lx role %x\n", __FUNCTION__,
+       pgprintk("%s: looking gfn %lx role %x\n", __func__,
                 gfn, role.word);
-       index = kvm_page_table_hashfn(gfn) % KVM_NUM_MMU_PAGES;
+       index = kvm_page_table_hashfn(gfn);
        bucket = &vcpu->kvm->arch.mmu_page_hash[index];
        hlist_for_each_entry(sp, node, bucket, hash_link)
                if (sp->gfn == gfn && sp->role.word == role.word) {
                        mmu_page_add_parent_pte(vcpu, sp, parent_pte);
-                       pgprintk("%s: found\n", __FUNCTION__);
+                       pgprintk("%s: found\n", __func__);
                        return sp;
                }
        ++vcpu->kvm->stat.mmu_cache_miss;
        sp = kvm_mmu_alloc_page(vcpu, parent_pte);
        if (!sp)
                return sp;
-       pgprintk("%s: adding gfn %lx role %x\n", __FUNCTION__, gfn, role.word);
+       pgprintk("%s: adding gfn %lx role %x\n", __func__, gfn, role.word);
        sp->gfn = gfn;
        sp->role = role;
        hlist_add_head(&sp->hash_link, bucket);
-       vcpu->arch.mmu.prefetch_page(vcpu, sp);
        if (!metaphysical)
                rmap_write_protect(vcpu->kvm, gfn);
+       vcpu->arch.mmu.prefetch_page(vcpu, sp);
        return sp;
 }
 
@@ -745,11 +878,17 @@ static void kvm_mmu_page_unlink_children(struct kvm *kvm,
        for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
                ent = pt[i];
 
+               if (is_shadow_present_pte(ent)) {
+                       if (!is_large_pte(ent)) {
+                               ent &= PT64_BASE_ADDR_MASK;
+                               mmu_page_remove_parent_pte(page_header(ent),
+                                                          &pt[i]);
+                       } else {
+                               --kvm->stat.lpages;
+                               rmap_remove(kvm, &pt[i]);
+                       }
+               }
                pt[i] = shadow_trap_nonpresent_pte;
-               if (!is_shadow_present_pte(ent))
-                       continue;
-               ent &= PT64_BASE_ADDR_MASK;
-               mmu_page_remove_parent_pte(page_header(ent), &pt[i]);
        }
        kvm_flush_remote_tlbs(kvm);
 }
@@ -789,10 +928,15 @@ static void kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp)
        }
        kvm_mmu_page_unlink_children(kvm, sp);
        if (!sp->root_count) {
+               if (!sp->role.metaphysical)
+                       unaccount_shadowed(kvm, sp->gfn);
                hlist_del(&sp->hash_link);
                kvm_mmu_free_page(kvm, sp);
-       } else
+       } else {
                list_move(&sp->link, &kvm->arch.active_mmu_pages);
+               sp->role.invalid = 1;
+               kvm_reload_remote_mmus(kvm);
+       }
        kvm_mmu_reset_last_pte_updated(kvm);
 }
 
@@ -838,13 +982,13 @@ static int kvm_mmu_unprotect_page(struct kvm *kvm, gfn_t gfn)
        struct hlist_node *node, *n;
        int r;
 
-       pgprintk("%s: looking for gfn %lx\n", __FUNCTION__, gfn);
+       pgprintk("%s: looking for gfn %lx\n", __func__, gfn);
        r = 0;
-       index = kvm_page_table_hashfn(gfn) % KVM_NUM_MMU_PAGES;
+       index = kvm_page_table_hashfn(gfn);
        bucket = &kvm->arch.mmu_page_hash[index];
        hlist_for_each_entry_safe(sp, node, n, bucket, hash_link)
                if (sp->gfn == gfn && !sp->role.metaphysical) {
-                       pgprintk("%s: gfn %lx role %x\n", __FUNCTION__, gfn,
+                       pgprintk("%s: gfn %lx role %x\n", __func__, gfn,
                                 sp->role.word);
                        kvm_mmu_zap_page(kvm, sp);
                        r = 1;
@@ -857,7 +1001,7 @@ static void mmu_unshadow(struct kvm *kvm, gfn_t gfn)
        struct kvm_mmu_page *sp;
 
        while ((sp = kvm_mmu_lookup_page(kvm, gfn)) != NULL) {
-               pgprintk("%s: zap %lx %x\n", __FUNCTION__, gfn, sp->role.word);
+               pgprintk("%s: zap %lx %x\n", __func__, gfn, sp->role.word);
                kvm_mmu_zap_page(kvm, sp);
        }
 }
@@ -889,26 +1033,39 @@ struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva)
 static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
                         unsigned pt_access, unsigned pte_access,
                         int user_fault, int write_fault, int dirty,
-                        int *ptwrite, gfn_t gfn, struct page *page)
+                        int *ptwrite, int largepage, gfn_t gfn,
+                        pfn_t pfn, bool speculative)
 {
        u64 spte;
        int was_rmapped = 0;
        int was_writeble = is_writeble_pte(*shadow_pte);
-       hfn_t host_pfn = (*shadow_pte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
 
        pgprintk("%s: spte %llx access %x write_fault %d"
                 " user_fault %d gfn %lx\n",
-                __FUNCTION__, *shadow_pte, pt_access,
+                __func__, *shadow_pte, pt_access,
                 write_fault, user_fault, gfn);
 
        if (is_rmap_pte(*shadow_pte)) {
-               if (host_pfn != page_to_pfn(page)) {
+               /*
+                * If we overwrite a PTE page pointer with a 2MB PMD, unlink
+                * the parent of the now unreachable PTE.
+                */
+               if (largepage && !is_large_pte(*shadow_pte)) {
+                       struct kvm_mmu_page *child;
+                       u64 pte = *shadow_pte;
+
+                       child = page_header(pte & PT64_BASE_ADDR_MASK);
+                       mmu_page_remove_parent_pte(child, shadow_pte);
+               } else if (pfn != spte_to_pfn(*shadow_pte)) {
                        pgprintk("hfn old %lx new %lx\n",
-                                host_pfn, page_to_pfn(page));
+                                spte_to_pfn(*shadow_pte), pfn);
                        rmap_remove(vcpu->kvm, shadow_pte);
+               } else {
+                       if (largepage)
+                               was_rmapped = is_large_pte(*shadow_pte);
+                       else
+                               was_rmapped = 1;
                }
-               else
-                       was_rmapped = 1;
        }
 
        /*
@@ -917,6 +1074,8 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
         * demand paging).
         */
        spte = PT_PRESENT_MASK | PT_DIRTY_MASK;
+       if (!speculative)
+               pte_access |= PT_ACCESSED_MASK;
        if (!dirty)
                pte_access &= ~ACC_WRITE_MASK;
        if (!(pte_access & ACC_EXEC_MASK))
@@ -925,15 +1084,10 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
        spte |= PT_PRESENT_MASK;
        if (pte_access & ACC_USER_MASK)
                spte |= PT_USER_MASK;
+       if (largepage)
+               spte |= PT_PAGE_SIZE_MASK;
 
-       if (is_error_page(page)) {
-               set_shadow_pte(shadow_pte,
-                              shadow_trap_nonpresent_pte | PT_SHADOW_IO_MARK);
-               kvm_release_page_clean(page);
-               return;
-       }
-
-       spte |= page_to_phys(page);
+       spte |= (u64)pfn << PAGE_SHIFT;
 
        if ((pte_access & ACC_WRITE_MASK)
            || (write_fault && !is_write_protection(vcpu) && !user_fault)) {
@@ -946,9 +1100,10 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
                }
 
                shadow = kvm_mmu_lookup_page(vcpu->kvm, gfn);
-               if (shadow) {
+               if (shadow ||
+                  (largepage && has_wrprotected_page(vcpu->kvm, gfn))) {
                        pgprintk("%s: found shadow page for %lx, marking ro\n",
-                                __FUNCTION__, gfn);
+                                __func__, gfn);
                        pte_access &= ~ACC_WRITE_MASK;
                        if (is_writeble_pte(spte)) {
                                spte &= ~PT_WRITABLE_MASK;
@@ -964,18 +1119,25 @@ unshadowed:
        if (pte_access & ACC_WRITE_MASK)
                mark_page_dirty(vcpu->kvm, gfn);
 
-       pgprintk("%s: setting spte %llx\n", __FUNCTION__, spte);
+       pgprintk("%s: setting spte %llx\n", __func__, spte);
+       pgprintk("instantiating %s PTE (%s) at %d (%llx) addr %llx\n",
+                (spte&PT_PAGE_SIZE_MASK)? "2MB" : "4kB",
+                (spte&PT_WRITABLE_MASK)?"RW":"R", gfn, spte, shadow_pte);
        set_shadow_pte(shadow_pte, spte);
+       if (!was_rmapped && (spte & PT_PAGE_SIZE_MASK)
+           && (spte & PT_PRESENT_MASK))
+               ++vcpu->kvm->stat.lpages;
+
        page_header_update_slot(vcpu->kvm, shadow_pte, gfn);
        if (!was_rmapped) {
-               rmap_add(vcpu, shadow_pte, gfn);
+               rmap_add(vcpu, shadow_pte, gfn, largepage);
                if (!is_rmap_pte(*shadow_pte))
-                       kvm_release_page_clean(page);
+                       kvm_release_pfn_clean(pfn);
        } else {
                if (was_writeble)
-                       kvm_release_page_dirty(page);
+                       kvm_release_pfn_dirty(pfn);
                else
-                       kvm_release_page_clean(page);
+                       kvm_release_pfn_clean(pfn);
        }
        if (!ptwrite || !*ptwrite)
                vcpu->arch.last_pte_updated = shadow_pte;
@@ -985,10 +1147,10 @@ static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
 {
 }
 
-static int __nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write,
-                          gfn_t gfn, struct page *page)
+static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
+                          int largepage, gfn_t gfn, pfn_t pfn,
+                          int level)
 {
-       int level = PT32E_ROOT_LEVEL;
        hpa_t table_addr = vcpu->arch.mmu.root_hpa;
        int pt_write = 0;
 
@@ -1001,8 +1163,14 @@ static int __nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write,
 
                if (level == 1) {
                        mmu_set_spte(vcpu, &table[index], ACC_ALL, ACC_ALL,
-                                    0, write, 1, &pt_write, gfn, page);
-                       return pt_write || is_io_pte(table[index]);
+                                    0, write, 1, &pt_write, 0, gfn, pfn, false);
+                       return pt_write;
+               }
+
+               if (largepage && level == 2) {
+                       mmu_set_spte(vcpu, &table[index], ACC_ALL, ACC_ALL,
+                                    0, write, 1, &pt_write, 1, gfn, pfn, false);
+                       return pt_write;
                }
 
                if (table[index] == shadow_trap_nonpresent_pte) {
@@ -1016,7 +1184,7 @@ static int __nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write,
                                                     1, ACC_ALL, &table[index]);
                        if (!new_table) {
                                pgprintk("nonpaging_map: ENOMEM\n");
-                               kvm_release_page_clean(page);
+                               kvm_release_pfn_clean(pfn);
                                return -ENOMEM;
                        }
 
@@ -1030,21 +1198,30 @@ static int __nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write,
 static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn)
 {
        int r;
-
-       struct page *page;
-
-       down_read(&vcpu->kvm->slots_lock);
+       int largepage = 0;
+       pfn_t pfn;
 
        down_read(&current->mm->mmap_sem);
-       page = gfn_to_page(vcpu->kvm, gfn);
+       if (is_largepage_backed(vcpu, gfn & ~(KVM_PAGES_PER_HPAGE-1))) {
+               gfn &= ~(KVM_PAGES_PER_HPAGE-1);
+               largepage = 1;
+       }
+
+       pfn = gfn_to_pfn(vcpu->kvm, gfn);
        up_read(&current->mm->mmap_sem);
 
+       /* mmio */
+       if (is_error_pfn(pfn)) {
+               kvm_release_pfn_clean(pfn);
+               return 1;
+       }
+
        spin_lock(&vcpu->kvm->mmu_lock);
        kvm_mmu_free_some_pages(vcpu);
-       r = __nonpaging_map(vcpu, v, write, gfn, page);
+       r = __direct_map(vcpu, v, write, largepage, gfn, pfn,
+                        PT32E_ROOT_LEVEL);
        spin_unlock(&vcpu->kvm->mmu_lock);
 
-       up_read(&vcpu->kvm->slots_lock);
 
        return r;
 }
@@ -1073,6 +1250,8 @@ static void mmu_free_roots(struct kvm_vcpu *vcpu)
 
                sp = page_header(root);
                --sp->root_count;
+               if (!sp->root_count && sp->role.invalid)
+                       kvm_mmu_zap_page(vcpu->kvm, sp);
                vcpu->arch.mmu.root_hpa = INVALID_PAGE;
                spin_unlock(&vcpu->kvm->mmu_lock);
                return;
@@ -1085,6 +1264,8 @@ static void mmu_free_roots(struct kvm_vcpu *vcpu)
                        root &= PT64_BASE_ADDR_MASK;
                        sp = page_header(root);
                        --sp->root_count;
+                       if (!sp->root_count && sp->role.invalid)
+                               kvm_mmu_zap_page(vcpu->kvm, sp);
                }
                vcpu->arch.mmu.pae_root[i] = INVALID_PAGE;
        }
@@ -1097,6 +1278,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
        int i;
        gfn_t root_gfn;
        struct kvm_mmu_page *sp;
+       int metaphysical = 0;
 
        root_gfn = vcpu->arch.cr3 >> PAGE_SHIFT;
 
@@ -1105,14 +1287,20 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
                hpa_t root = vcpu->arch.mmu.root_hpa;
 
                ASSERT(!VALID_PAGE(root));
+               if (tdp_enabled)
+                       metaphysical = 1;
                sp = kvm_mmu_get_page(vcpu, root_gfn, 0,
-                                     PT64_ROOT_LEVEL, 0, ACC_ALL, NULL);
+                                     PT64_ROOT_LEVEL, metaphysical,
+                                     ACC_ALL, NULL);
                root = __pa(sp->spt);
                ++sp->root_count;
                vcpu->arch.mmu.root_hpa = root;
                return;
        }
 #endif
+       metaphysical = !is_paging(vcpu);
+       if (tdp_enabled)
+               metaphysical = 1;
        for (i = 0; i < 4; ++i) {
                hpa_t root = vcpu->arch.mmu.pae_root[i];
 
@@ -1126,7 +1314,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
                } else if (vcpu->arch.mmu.root_level == 0)
                        root_gfn = 0;
                sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30,
-                                     PT32_ROOT_LEVEL, !is_paging(vcpu),
+                                     PT32_ROOT_LEVEL, metaphysical,
                                      ACC_ALL, NULL);
                root = __pa(sp->spt);
                ++sp->root_count;
@@ -1146,7 +1334,7 @@ static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
        gfn_t gfn;
        int r;
 
-       pgprintk("%s: gva %lx error %x\n", __FUNCTION__, gva, error_code);
+       pgprintk("%s: gva %lx error %x\n", __func__, gva, error_code);
        r = mmu_topup_memory_caches(vcpu);
        if (r)
                return r;
@@ -1160,6 +1348,41 @@ static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
                             error_code & PFERR_WRITE_MASK, gfn);
 }
 
+static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa,
+                               u32 error_code)
+{
+       pfn_t pfn;
+       int r;
+       int largepage = 0;
+       gfn_t gfn = gpa >> PAGE_SHIFT;
+
+       ASSERT(vcpu);
+       ASSERT(VALID_PAGE(vcpu->arch.mmu.root_hpa));
+
+       r = mmu_topup_memory_caches(vcpu);
+       if (r)
+               return r;
+
+       down_read(&current->mm->mmap_sem);
+       if (is_largepage_backed(vcpu, gfn & ~(KVM_PAGES_PER_HPAGE-1))) {
+               gfn &= ~(KVM_PAGES_PER_HPAGE-1);
+               largepage = 1;
+       }
+       pfn = gfn_to_pfn(vcpu->kvm, gfn);
+       up_read(&current->mm->mmap_sem);
+       if (is_error_pfn(pfn)) {
+               kvm_release_pfn_clean(pfn);
+               return 1;
+       }
+       spin_lock(&vcpu->kvm->mmu_lock);
+       kvm_mmu_free_some_pages(vcpu);
+       r = __direct_map(vcpu, gpa, error_code & PFERR_WRITE_MASK,
+                        largepage, gfn, pfn, TDP_ROOT_LEVEL);
+       spin_unlock(&vcpu->kvm->mmu_lock);
+
+       return r;
+}
+
 static void nonpaging_free(struct kvm_vcpu *vcpu)
 {
        mmu_free_roots(vcpu);
@@ -1188,7 +1411,7 @@ void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu)
 
 static void paging_new_cr3(struct kvm_vcpu *vcpu)
 {
-       pgprintk("%s: cr3 %lx\n", __FUNCTION__, vcpu->arch.cr3);
+       pgprintk("%s: cr3 %lx\n", __func__, vcpu->arch.cr3);
        mmu_free_roots(vcpu);
 }
 
@@ -1253,7 +1476,35 @@ static int paging32E_init_context(struct kvm_vcpu *vcpu)
        return paging64_init_context_common(vcpu, PT32E_ROOT_LEVEL);
 }
 
-static int init_kvm_mmu(struct kvm_vcpu *vcpu)
+static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
+{
+       struct kvm_mmu *context = &vcpu->arch.mmu;
+
+       context->new_cr3 = nonpaging_new_cr3;
+       context->page_fault = tdp_page_fault;
+       context->free = nonpaging_free;
+       context->prefetch_page = nonpaging_prefetch_page;
+       context->shadow_root_level = TDP_ROOT_LEVEL;
+       context->root_hpa = INVALID_PAGE;
+
+       if (!is_paging(vcpu)) {
+               context->gva_to_gpa = nonpaging_gva_to_gpa;
+               context->root_level = 0;
+       } else if (is_long_mode(vcpu)) {
+               context->gva_to_gpa = paging64_gva_to_gpa;
+               context->root_level = PT64_ROOT_LEVEL;
+       } else if (is_pae(vcpu)) {
+               context->gva_to_gpa = paging64_gva_to_gpa;
+               context->root_level = PT32E_ROOT_LEVEL;
+       } else {
+               context->gva_to_gpa = paging32_gva_to_gpa;
+               context->root_level = PT32_ROOT_LEVEL;
+       }
+
+       return 0;
+}
+
+static int init_kvm_softmmu(struct kvm_vcpu *vcpu)
 {
        ASSERT(vcpu);
        ASSERT(!VALID_PAGE(vcpu->arch.mmu.root_hpa));
@@ -1268,6 +1519,16 @@ static int init_kvm_mmu(struct kvm_vcpu *vcpu)
                return paging32_init_context(vcpu);
 }
 
+static int init_kvm_mmu(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.update_pte.pfn = bad_pfn;
+
+       if (tdp_enabled)
+               return init_kvm_tdp_mmu(vcpu);
+       else
+               return init_kvm_softmmu(vcpu);
+}
+
 static void destroy_kvm_mmu(struct kvm_vcpu *vcpu)
 {
        ASSERT(vcpu);
@@ -1316,7 +1577,8 @@ static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,
 
        pte = *spte;
        if (is_shadow_present_pte(pte)) {
-               if (sp->role.level == PT_PAGE_TABLE_LEVEL)
+               if (sp->role.level == PT_PAGE_TABLE_LEVEL ||
+                   is_large_pte(pte))
                        rmap_remove(vcpu->kvm, spte);
                else {
                        child = page_header(pte & PT64_BASE_ADDR_MASK);
@@ -1324,24 +1586,26 @@ static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,
                }
        }
        set_shadow_pte(spte, shadow_trap_nonpresent_pte);
+       if (is_large_pte(pte))
+               --vcpu->kvm->stat.lpages;
 }
 
 static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu,
                                  struct kvm_mmu_page *sp,
                                  u64 *spte,
-                                 const void *new, int bytes,
-                                 int offset_in_pte)
+                                 const void *new)
 {
-       if (sp->role.level != PT_PAGE_TABLE_LEVEL) {
+       if ((sp->role.level != PT_PAGE_TABLE_LEVEL)
+           && !vcpu->arch.update_pte.largepage) {
                ++vcpu->kvm->stat.mmu_pde_zapped;
                return;
        }
 
        ++vcpu->kvm->stat.mmu_pte_updated;
        if (sp->role.glevels == PT32_ROOT_LEVEL)
-               paging32_update_pte(vcpu, sp, spte, new, bytes, offset_in_pte);
+               paging32_update_pte(vcpu, sp, spte, new);
        else
-               paging64_update_pte(vcpu, sp, spte, new, bytes, offset_in_pte);
+               paging64_update_pte(vcpu, sp, spte, new);
 }
 
 static bool need_remote_flush(u64 old, u64 new)
@@ -1378,7 +1642,9 @@ static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
        gfn_t gfn;
        int r;
        u64 gpte = 0;
-       struct page *page;
+       pfn_t pfn;
+
+       vcpu->arch.update_pte.largepage = 0;
 
        if (bytes != 4 && bytes != 8)
                return;
@@ -1408,11 +1674,19 @@ static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
        gfn = (gpte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
 
        down_read(&current->mm->mmap_sem);
-       page = gfn_to_page(vcpu->kvm, gfn);
+       if (is_large_pte(gpte) && is_largepage_backed(vcpu, gfn)) {
+               gfn &= ~(KVM_PAGES_PER_HPAGE-1);
+               vcpu->arch.update_pte.largepage = 1;
+       }
+       pfn = gfn_to_pfn(vcpu->kvm, gfn);
        up_read(&current->mm->mmap_sem);
 
+       if (is_error_pfn(pfn)) {
+               kvm_release_pfn_clean(pfn);
+               return;
+       }
        vcpu->arch.update_pte.gfn = gfn;
-       vcpu->arch.update_pte.page = page;
+       vcpu->arch.update_pte.pfn = pfn;
 }
 
 void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
@@ -1423,7 +1697,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
        struct hlist_node *node, *n;
        struct hlist_head *bucket;
        unsigned index;
-       u64 entry;
+       u64 entry, gentry;
        u64 *spte;
        unsigned offset = offset_in_page(gpa);
        unsigned pte_size;
@@ -1433,8 +1707,9 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
        int level;
        int flooded = 0;
        int npte;
+       int r;
 
-       pgprintk("%s: gpa %llx bytes %d\n", __FUNCTION__, gpa, bytes);
+       pgprintk("%s: gpa %llx bytes %d\n", __func__, gpa, bytes);
        mmu_guess_page_from_pte_write(vcpu, gpa, new, bytes);
        spin_lock(&vcpu->kvm->mmu_lock);
        kvm_mmu_free_some_pages(vcpu);
@@ -1450,7 +1725,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
                vcpu->arch.last_pt_write_count = 1;
                vcpu->arch.last_pte_updated = NULL;
        }
-       index = kvm_page_table_hashfn(gfn) % KVM_NUM_MMU_PAGES;
+       index = kvm_page_table_hashfn(gfn);
        bucket = &vcpu->kvm->arch.mmu_page_hash[index];
        hlist_for_each_entry_safe(sp, node, n, bucket, hash_link) {
                if (sp->gfn != gfn || sp->role.metaphysical)
@@ -1496,20 +1771,29 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
                                continue;
                }
                spte = &sp->spt[page_offset / sizeof(*spte)];
+               if ((gpa & (pte_size - 1)) || (bytes < pte_size)) {
+                       gentry = 0;
+                       r = kvm_read_guest_atomic(vcpu->kvm,
+                                                 gpa & ~(u64)(pte_size - 1),
+                                                 &gentry, pte_size);
+                       new = (const void *)&gentry;
+                       if (r < 0)
+                               new = NULL;
+               }
                while (npte--) {
                        entry = *spte;
                        mmu_pte_write_zap_pte(vcpu, sp, spte);
-                       mmu_pte_write_new_pte(vcpu, sp, spte, new, bytes,
-                                             page_offset & (pte_size - 1));
+                       if (new)
+                               mmu_pte_write_new_pte(vcpu, sp, spte, new);
                        mmu_pte_write_flush_tlb(vcpu, entry, *spte);
                        ++spte;
                }
        }
        kvm_mmu_audit(vcpu, "post pte write");
        spin_unlock(&vcpu->kvm->mmu_lock);
-       if (vcpu->arch.update_pte.page) {
-               kvm_release_page_clean(vcpu->arch.update_pte.page);
-               vcpu->arch.update_pte.page = NULL;
+       if (!is_error_pfn(vcpu->arch.update_pte.pfn)) {
+               kvm_release_pfn_clean(vcpu->arch.update_pte.pfn);
+               vcpu->arch.update_pte.pfn = bad_pfn;
        }
 }
 
@@ -1518,9 +1802,7 @@ int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva)
        gpa_t gpa;
        int r;
 
-       down_read(&vcpu->kvm->slots_lock);
        gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, gva);
-       up_read(&vcpu->kvm->slots_lock);
 
        spin_lock(&vcpu->kvm->mmu_lock);
        r = kvm_mmu_unprotect_page(vcpu->kvm, gpa >> PAGE_SHIFT);
@@ -1577,6 +1859,12 @@ out:
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_page_fault);
 
+void kvm_enable_tdp(void)
+{
+       tdp_enabled = true;
+}
+EXPORT_SYMBOL_GPL(kvm_enable_tdp);
+
 static void free_mmu_pages(struct kvm_vcpu *vcpu)
 {
        struct kvm_mmu_page *sp;
@@ -1677,7 +1965,53 @@ void kvm_mmu_zap_all(struct kvm *kvm)
        kvm_flush_remote_tlbs(kvm);
 }
 
-void kvm_mmu_module_exit(void)
+void kvm_mmu_remove_one_alloc_mmu_page(struct kvm *kvm)
+{
+       struct kvm_mmu_page *page;
+
+       page = container_of(kvm->arch.active_mmu_pages.prev,
+                           struct kvm_mmu_page, link);
+       kvm_mmu_zap_page(kvm, page);
+}
+
+static int mmu_shrink(int nr_to_scan, gfp_t gfp_mask)
+{
+       struct kvm *kvm;
+       struct kvm *kvm_freed = NULL;
+       int cache_count = 0;
+
+       spin_lock(&kvm_lock);
+
+       list_for_each_entry(kvm, &vm_list, vm_list) {
+               int npages;
+
+               spin_lock(&kvm->mmu_lock);
+               npages = kvm->arch.n_alloc_mmu_pages -
+                        kvm->arch.n_free_mmu_pages;
+               cache_count += npages;
+               if (!kvm_freed && nr_to_scan > 0 && npages > 0) {
+                       kvm_mmu_remove_one_alloc_mmu_page(kvm);
+                       cache_count--;
+                       kvm_freed = kvm;
+               }
+               nr_to_scan--;
+
+               spin_unlock(&kvm->mmu_lock);
+       }
+       if (kvm_freed)
+               list_move_tail(&kvm_freed->vm_list, &vm_list);
+
+       spin_unlock(&kvm_lock);
+
+       return cache_count;
+}
+
+static struct shrinker mmu_shrinker = {
+       .shrink = mmu_shrink,
+       .seeks = DEFAULT_SEEKS * 10,
+};
+
+void mmu_destroy_caches(void)
 {
        if (pte_chain_cache)
                kmem_cache_destroy(pte_chain_cache);
@@ -1687,6 +2021,12 @@ void kvm_mmu_module_exit(void)
                kmem_cache_destroy(mmu_page_header_cache);
 }
 
+void kvm_mmu_module_exit(void)
+{
+       mmu_destroy_caches();
+       unregister_shrinker(&mmu_shrinker);
+}
+
 int kvm_mmu_module_init(void)
 {
        pte_chain_cache = kmem_cache_create("kvm_pte_chain",
@@ -1706,10 +2046,12 @@ int kvm_mmu_module_init(void)
        if (!mmu_page_header_cache)
                goto nomem;
 
+       register_shrinker(&mmu_shrinker);
+
        return 0;
 
 nomem:
-       kvm_mmu_module_exit();
+       mmu_destroy_caches();
        return -ENOMEM;
 }
 
@@ -1732,6 +2074,127 @@ unsigned int kvm_mmu_calculate_mmu_pages(struct kvm *kvm)
        return nr_mmu_pages;
 }
 
+static void *pv_mmu_peek_buffer(struct kvm_pv_mmu_op_buffer *buffer,
+                               unsigned len)
+{
+       if (len > buffer->len)
+               return NULL;
+       return buffer->ptr;
+}
+
+static void *pv_mmu_read_buffer(struct kvm_pv_mmu_op_buffer *buffer,
+                               unsigned len)
+{
+       void *ret;
+
+       ret = pv_mmu_peek_buffer(buffer, len);
+       if (!ret)
+               return ret;
+       buffer->ptr += len;
+       buffer->len -= len;
+       buffer->processed += len;
+       return ret;
+}
+
+static int kvm_pv_mmu_write(struct kvm_vcpu *vcpu,
+                            gpa_t addr, gpa_t value)
+{
+       int bytes = 8;
+       int r;
+
+       if (!is_long_mode(vcpu) && !is_pae(vcpu))
+               bytes = 4;
+
+       r = mmu_topup_memory_caches(vcpu);
+       if (r)
+               return r;
+
+       if (!emulator_write_phys(vcpu, addr, &value, bytes))
+               return -EFAULT;
+
+       return 1;
+}
+
+static int kvm_pv_mmu_flush_tlb(struct kvm_vcpu *vcpu)
+{
+       kvm_x86_ops->tlb_flush(vcpu);
+       return 1;
+}
+
+static int kvm_pv_mmu_release_pt(struct kvm_vcpu *vcpu, gpa_t addr)
+{
+       spin_lock(&vcpu->kvm->mmu_lock);
+       mmu_unshadow(vcpu->kvm, addr >> PAGE_SHIFT);
+       spin_unlock(&vcpu->kvm->mmu_lock);
+       return 1;
+}
+
+static int kvm_pv_mmu_op_one(struct kvm_vcpu *vcpu,
+                            struct kvm_pv_mmu_op_buffer *buffer)
+{
+       struct kvm_mmu_op_header *header;
+
+       header = pv_mmu_peek_buffer(buffer, sizeof *header);
+       if (!header)
+               return 0;
+       switch (header->op) {
+       case KVM_MMU_OP_WRITE_PTE: {
+               struct kvm_mmu_op_write_pte *wpte;
+
+               wpte = pv_mmu_read_buffer(buffer, sizeof *wpte);
+               if (!wpte)
+                       return 0;
+               return kvm_pv_mmu_write(vcpu, wpte->pte_phys,
+                                       wpte->pte_val);
+       }
+       case KVM_MMU_OP_FLUSH_TLB: {
+               struct kvm_mmu_op_flush_tlb *ftlb;
+
+               ftlb = pv_mmu_read_buffer(buffer, sizeof *ftlb);
+               if (!ftlb)
+                       return 0;
+               return kvm_pv_mmu_flush_tlb(vcpu);
+       }
+       case KVM_MMU_OP_RELEASE_PT: {
+               struct kvm_mmu_op_release_pt *rpt;
+
+               rpt = pv_mmu_read_buffer(buffer, sizeof *rpt);
+               if (!rpt)
+                       return 0;
+               return kvm_pv_mmu_release_pt(vcpu, rpt->pt_phys);
+       }
+       default: return 0;
+       }
+}
+
+int kvm_pv_mmu_op(struct kvm_vcpu *vcpu, unsigned long bytes,
+                 gpa_t addr, unsigned long *ret)
+{
+       int r;
+       struct kvm_pv_mmu_op_buffer buffer;
+
+       buffer.ptr = buffer.buf;
+       buffer.len = min_t(unsigned long, bytes, sizeof buffer.buf);
+       buffer.processed = 0;
+
+       r = kvm_read_guest(vcpu->kvm, addr, buffer.buf, buffer.len);
+       if (r)
+               goto out;
+
+       while (buffer.len) {
+               r = kvm_pv_mmu_op_one(vcpu, &buffer);
+               if (r < 0)
+                       goto out;
+               if (r == 0)
+                       break;
+       }
+
+       r = 1;
+out:
+       *ret = buffer.processed;
+       return r;
+}
+
 #ifdef AUDIT
 
 static const char *audit_msg;
@@ -1768,8 +2231,7 @@ static void audit_mappings_page(struct kvm_vcpu *vcpu, u64 page_pte,
                        audit_mappings_page(vcpu, ent, va, level - 1);
                } else {
                        gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, va);
-                       struct page *page = gpa_to_page(vcpu, gpa);
-                       hpa_t hpa = page_to_phys(page);
+                       hpa_t hpa = (hpa_t)gpa_to_pfn(vcpu, gpa) << PAGE_SHIFT;
 
                        if (is_shadow_present_pte(ent)
                            && (ent & PT64_BASE_ADDR_MASK) != hpa)
@@ -1782,7 +2244,7 @@ static void audit_mappings_page(struct kvm_vcpu *vcpu, u64 page_pte,
                                 && !is_error_hpa(hpa))
                                printk(KERN_ERR "audit: (%s) notrap shadow,"
                                       " valid guest gva %lx\n", audit_msg, va);
-                       kvm_release_page_clean(page);
+                       kvm_release_pfn_clean(pfn);
 
                }
        }
@@ -1867,7 +2329,7 @@ static void audit_rmap(struct kvm_vcpu *vcpu)
 
        if (n_rmap != n_actual)
                printk(KERN_ERR "%s: (%s) rmap %d actual %d\n",
-                      __FUNCTION__, audit_msg, n_rmap, n_actual);
+                      __func__, audit_msg, n_rmap, n_actual);
 }
 
 static void audit_write_protection(struct kvm_vcpu *vcpu)
@@ -1887,7 +2349,7 @@ static void audit_write_protection(struct kvm_vcpu *vcpu)
                if (*rmapp)
                        printk(KERN_ERR "%s: (%s) shadow page has writable"
                               " mappings: gfn %lx role %x\n",
-                              __FUNCTION__, audit_msg, sp->gfn,
+                              __func__, audit_msg, sp->gfn,
                               sp->role.word);
        }
 }
index 1fce19ec7a2380c61c79ef0f50e71e4c39d2af66..e64e9f56a65eb04889cb2c5912c9fda9d36d96f1 100644 (file)
@@ -3,6 +3,12 @@
 
 #include <linux/kvm_host.h>
 
+#ifdef CONFIG_X86_64
+#define TDP_ROOT_LEVEL PT64_ROOT_LEVEL
+#else
+#define TDP_ROOT_LEVEL PT32E_ROOT_LEVEL
+#endif
+
 static inline void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
 {
        if (unlikely(vcpu->kvm->arch.n_free_mmu_pages < KVM_MIN_FREE_MMU_PAGES))
index ecc0856268c47c8c7a5c5773ac0d239d37dbc58e..156fe10288ae330c6d9ac2d3e0b857a9d6c853b5 100644 (file)
@@ -130,7 +130,7 @@ static int FNAME(walk_addr)(struct guest_walker *walker,
        unsigned index, pt_access, pte_access;
        gpa_t pte_gpa;
 
-       pgprintk("%s: addr %lx\n", __FUNCTION__, addr);
+       pgprintk("%s: addr %lx\n", __func__, addr);
 walk:
        walker->level = vcpu->arch.mmu.root_level;
        pte = vcpu->arch.cr3;
@@ -155,7 +155,7 @@ walk:
                pte_gpa += index * sizeof(pt_element_t);
                walker->table_gfn[walker->level - 1] = table_gfn;
                walker->pte_gpa[walker->level - 1] = pte_gpa;
-               pgprintk("%s: table_gfn[%d] %lx\n", __FUNCTION__,
+               pgprintk("%s: table_gfn[%d] %lx\n", __func__,
                         walker->level - 1, table_gfn);
 
                kvm_read_guest(vcpu->kvm, pte_gpa, &pte, sizeof(pte));
@@ -222,7 +222,7 @@ walk:
        walker->pt_access = pt_access;
        walker->pte_access = pte_access;
        pgprintk("%s: pte %llx pte_access %x pt_access %x\n",
-                __FUNCTION__, (u64)pte, pt_access, pte_access);
+                __func__, (u64)pte, pt_access, pte_access);
        return 1;
 
 not_present:
@@ -243,31 +243,30 @@ err:
 }
 
 static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
-                             u64 *spte, const void *pte, int bytes,
-                             int offset_in_pte)
+                             u64 *spte, const void *pte)
 {
        pt_element_t gpte;
        unsigned pte_access;
-       struct page *npage;
+       pfn_t pfn;
+       int largepage = vcpu->arch.update_pte.largepage;
 
        gpte = *(const pt_element_t *)pte;
        if (~gpte & (PT_PRESENT_MASK | PT_ACCESSED_MASK)) {
-               if (!offset_in_pte && !is_present_pte(gpte))
+               if (!is_present_pte(gpte))
                        set_shadow_pte(spte, shadow_notrap_nonpresent_pte);
                return;
        }
-       if (bytes < sizeof(pt_element_t))
-               return;
-       pgprintk("%s: gpte %llx spte %p\n", __FUNCTION__, (u64)gpte, spte);
+       pgprintk("%s: gpte %llx spte %p\n", __func__, (u64)gpte, spte);
        pte_access = page->role.access & FNAME(gpte_access)(vcpu, gpte);
        if (gpte_to_gfn(gpte) != vcpu->arch.update_pte.gfn)
                return;
-       npage = vcpu->arch.update_pte.page;
-       if (!npage)
+       pfn = vcpu->arch.update_pte.pfn;
+       if (is_error_pfn(pfn))
                return;
-       get_page(npage);
+       kvm_get_pfn(pfn);
        mmu_set_spte(vcpu, spte, page->role.access, pte_access, 0, 0,
-                    gpte & PT_DIRTY_MASK, NULL, gpte_to_gfn(gpte), npage);
+                    gpte & PT_DIRTY_MASK, NULL, largepage, gpte_to_gfn(gpte),
+                    pfn, true);
 }
 
 /*
@@ -275,8 +274,8 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
  */
 static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
                         struct guest_walker *walker,
-                        int user_fault, int write_fault, int *ptwrite,
-                        struct page *page)
+                        int user_fault, int write_fault, int largepage,
+                        int *ptwrite, pfn_t pfn)
 {
        hpa_t shadow_addr;
        int level;
@@ -304,11 +303,19 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
                shadow_ent = ((u64 *)__va(shadow_addr)) + index;
                if (level == PT_PAGE_TABLE_LEVEL)
                        break;
-               if (is_shadow_present_pte(*shadow_ent)) {
+
+               if (largepage && level == PT_DIRECTORY_LEVEL)
+                       break;
+
+               if (is_shadow_present_pte(*shadow_ent)
+                   && !is_large_pte(*shadow_ent)) {
                        shadow_addr = *shadow_ent & PT64_BASE_ADDR_MASK;
                        continue;
                }
 
+               if (is_large_pte(*shadow_ent))
+                       rmap_remove(vcpu->kvm, shadow_ent);
+
                if (level - 1 == PT_PAGE_TABLE_LEVEL
                    && walker->level == PT_DIRECTORY_LEVEL) {
                        metaphysical = 1;
@@ -329,7 +336,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
                                                  walker->pte_gpa[level - 2],
                                                  &curr_pte, sizeof(curr_pte));
                        if (r || curr_pte != walker->ptes[level - 2]) {
-                               kvm_release_page_clean(page);
+                               kvm_release_pfn_clean(pfn);
                                return NULL;
                        }
                }
@@ -342,7 +349,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
        mmu_set_spte(vcpu, shadow_ent, access, walker->pte_access & access,
                     user_fault, write_fault,
                     walker->ptes[walker->level-1] & PT_DIRTY_MASK,
-                    ptwrite, walker->gfn, page);
+                    ptwrite, largepage, walker->gfn, pfn, false);
 
        return shadow_ent;
 }
@@ -371,16 +378,16 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
        u64 *shadow_pte;
        int write_pt = 0;
        int r;
-       struct page *page;
+       pfn_t pfn;
+       int largepage = 0;
 
-       pgprintk("%s: addr %lx err %x\n", __FUNCTION__, addr, error_code);
+       pgprintk("%s: addr %lx err %x\n", __func__, addr, error_code);
        kvm_mmu_audit(vcpu, "pre page fault");
 
        r = mmu_topup_memory_caches(vcpu);
        if (r)
                return r;
 
-       down_read(&vcpu->kvm->slots_lock);
        /*
         * Look up the shadow pte for the faulting address.
         */
@@ -391,40 +398,45 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
         * The page is not mapped by the guest.  Let the guest handle it.
         */
        if (!r) {
-               pgprintk("%s: guest page fault\n", __FUNCTION__);
+               pgprintk("%s: guest page fault\n", __func__);
                inject_page_fault(vcpu, addr, walker.error_code);
                vcpu->arch.last_pt_write_count = 0; /* reset fork detector */
-               up_read(&vcpu->kvm->slots_lock);
                return 0;
        }
 
        down_read(&current->mm->mmap_sem);
-       page = gfn_to_page(vcpu->kvm, walker.gfn);
+       if (walker.level == PT_DIRECTORY_LEVEL) {
+               gfn_t large_gfn;
+               large_gfn = walker.gfn & ~(KVM_PAGES_PER_HPAGE-1);
+               if (is_largepage_backed(vcpu, large_gfn)) {
+                       walker.gfn = large_gfn;
+                       largepage = 1;
+               }
+       }
+       pfn = gfn_to_pfn(vcpu->kvm, walker.gfn);
        up_read(&current->mm->mmap_sem);
 
+       /* mmio */
+       if (is_error_pfn(pfn)) {
+               pgprintk("gfn %x is mmio\n", walker.gfn);
+               kvm_release_pfn_clean(pfn);
+               return 1;
+       }
+
        spin_lock(&vcpu->kvm->mmu_lock);
        kvm_mmu_free_some_pages(vcpu);
        shadow_pte = FNAME(fetch)(vcpu, addr, &walker, user_fault, write_fault,
-                                 &write_pt, page);
-       pgprintk("%s: shadow pte %p %llx ptwrite %d\n", __FUNCTION__,
+                                 largepage, &write_pt, pfn);
+
+       pgprintk("%s: shadow pte %p %llx ptwrite %d\n", __func__,
                 shadow_pte, *shadow_pte, write_pt);
 
        if (!write_pt)
                vcpu->arch.last_pt_write_count = 0; /* reset fork detector */
 
-       /*
-        * mmio: emulate if accessible, otherwise its a guest fault.
-        */
-       if (shadow_pte && is_io_pte(*shadow_pte)) {
-               spin_unlock(&vcpu->kvm->mmu_lock);
-               up_read(&vcpu->kvm->slots_lock);
-               return 1;
-       }
-
        ++vcpu->stat.pf_fixed;
        kvm_mmu_audit(vcpu, "post page fault (fixed)");
        spin_unlock(&vcpu->kvm->mmu_lock);
-       up_read(&vcpu->kvm->slots_lock);
 
        return write_pt;
 }
diff --git a/arch/x86/kvm/segment_descriptor.h b/arch/x86/kvm/segment_descriptor.h
deleted file mode 100644 (file)
index 56fc4c8..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef __SEGMENT_DESCRIPTOR_H
-#define __SEGMENT_DESCRIPTOR_H
-
-struct segment_descriptor {
-       u16 limit_low;
-       u16 base_low;
-       u8  base_mid;
-       u8  type : 4;
-       u8  system : 1;
-       u8  dpl : 2;
-       u8  present : 1;
-       u8  limit_high : 4;
-       u8  avl : 1;
-       u8  long_mode : 1;
-       u8  default_op : 1;
-       u8  granularity : 1;
-       u8  base_high;
-} __attribute__((packed));
-
-#ifdef CONFIG_X86_64
-/* LDT or TSS descriptor in the GDT. 16 bytes. */
-struct segment_descriptor_64 {
-       struct segment_descriptor s;
-       u32 base_higher;
-       u32 pad_zero;
-};
-
-#endif
-#endif
index 1a582f1090e895aaa19634aa21d02ccf6c1584f0..89e0be2c10d0ee02153fd6f72df1ebd6e31f6e7b 100644 (file)
@@ -47,6 +47,18 @@ MODULE_LICENSE("GPL");
 #define SVM_FEATURE_LBRV (1 << 1)
 #define SVM_DEATURE_SVML (1 << 2)
 
+#define DEBUGCTL_RESERVED_BITS (~(0x3fULL))
+
+/* enable NPT for AMD64 and X86 with PAE */
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
+static bool npt_enabled = true;
+#else
+static bool npt_enabled = false;
+#endif
+static int npt = 1;
+
+module_param(npt, int, S_IRUGO);
+
 static void kvm_reput_irq(struct vcpu_svm *svm);
 
 static inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu)
@@ -54,8 +66,7 @@ static inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu)
        return container_of(vcpu, struct vcpu_svm, vcpu);
 }
 
-unsigned long iopm_base;
-unsigned long msrpm_base;
+static unsigned long iopm_base;
 
 struct kvm_ldttss_desc {
        u16 limit0;
@@ -182,7 +193,7 @@ static inline void flush_guest_tlb(struct kvm_vcpu *vcpu)
 
 static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer)
 {
-       if (!(efer & EFER_LMA))
+       if (!npt_enabled && !(efer & EFER_LMA))
                efer &= ~EFER_LME;
 
        to_svm(vcpu)->vmcb->save.efer = efer | MSR_EFER_SVME_MASK;
@@ -219,12 +230,12 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
        struct vcpu_svm *svm = to_svm(vcpu);
 
        if (!svm->next_rip) {
-               printk(KERN_DEBUG "%s: NOP\n", __FUNCTION__);
+               printk(KERN_DEBUG "%s: NOP\n", __func__);
                return;
        }
        if (svm->next_rip - svm->vmcb->save.rip > MAX_INST_SIZE)
                printk(KERN_ERR "%s: ip 0x%llx next 0x%llx\n",
-                      __FUNCTION__,
+                      __func__,
                       svm->vmcb->save.rip,
                       svm->next_rip);
 
@@ -279,11 +290,7 @@ static void svm_hardware_enable(void *garbage)
 
        struct svm_cpu_data *svm_data;
        uint64_t efer;
-#ifdef CONFIG_X86_64
-       struct desc_ptr gdt_descr;
-#else
        struct desc_ptr gdt_descr;
-#endif
        struct desc_struct *gdt;
        int me = raw_smp_processor_id();
 
@@ -302,7 +309,6 @@ static void svm_hardware_enable(void *garbage)
        svm_data->asid_generation = 1;
        svm_data->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1;
        svm_data->next_asid = svm_data->max_asid + 1;
-       svm_features = cpuid_edx(SVM_CPUID_FUNC);
 
        asm volatile ("sgdt %0" : "=m"(gdt_descr));
        gdt = (struct desc_struct *)gdt_descr.address;
@@ -361,12 +367,51 @@ static void set_msr_interception(u32 *msrpm, unsigned msr,
        BUG();
 }
 
+static void svm_vcpu_init_msrpm(u32 *msrpm)
+{
+       memset(msrpm, 0xff, PAGE_SIZE * (1 << MSRPM_ALLOC_ORDER));
+
+#ifdef CONFIG_X86_64
+       set_msr_interception(msrpm, MSR_GS_BASE, 1, 1);
+       set_msr_interception(msrpm, MSR_FS_BASE, 1, 1);
+       set_msr_interception(msrpm, MSR_KERNEL_GS_BASE, 1, 1);
+       set_msr_interception(msrpm, MSR_LSTAR, 1, 1);
+       set_msr_interception(msrpm, MSR_CSTAR, 1, 1);
+       set_msr_interception(msrpm, MSR_SYSCALL_MASK, 1, 1);
+#endif
+       set_msr_interception(msrpm, MSR_K6_STAR, 1, 1);
+       set_msr_interception(msrpm, MSR_IA32_SYSENTER_CS, 1, 1);
+       set_msr_interception(msrpm, MSR_IA32_SYSENTER_ESP, 1, 1);
+       set_msr_interception(msrpm, MSR_IA32_SYSENTER_EIP, 1, 1);
+}
+
+static void svm_enable_lbrv(struct vcpu_svm *svm)
+{
+       u32 *msrpm = svm->msrpm;
+
+       svm->vmcb->control.lbr_ctl = 1;
+       set_msr_interception(msrpm, MSR_IA32_LASTBRANCHFROMIP, 1, 1);
+       set_msr_interception(msrpm, MSR_IA32_LASTBRANCHTOIP, 1, 1);
+       set_msr_interception(msrpm, MSR_IA32_LASTINTFROMIP, 1, 1);
+       set_msr_interception(msrpm, MSR_IA32_LASTINTTOIP, 1, 1);
+}
+
+static void svm_disable_lbrv(struct vcpu_svm *svm)
+{
+       u32 *msrpm = svm->msrpm;
+
+       svm->vmcb->control.lbr_ctl = 0;
+       set_msr_interception(msrpm, MSR_IA32_LASTBRANCHFROMIP, 0, 0);
+       set_msr_interception(msrpm, MSR_IA32_LASTBRANCHTOIP, 0, 0);
+       set_msr_interception(msrpm, MSR_IA32_LASTINTFROMIP, 0, 0);
+       set_msr_interception(msrpm, MSR_IA32_LASTINTTOIP, 0, 0);
+}
+
 static __init int svm_hardware_setup(void)
 {
        int cpu;
        struct page *iopm_pages;
-       struct page *msrpm_pages;
-       void *iopm_va, *msrpm_va;
+       void *iopm_va;
        int r;
 
        iopm_pages = alloc_pages(GFP_KERNEL, IOPM_ALLOC_ORDER);
@@ -379,41 +424,33 @@ static __init int svm_hardware_setup(void)
        clear_bit(0x80, iopm_va); /* allow direct access to PC debug port */
        iopm_base = page_to_pfn(iopm_pages) << PAGE_SHIFT;
 
+       if (boot_cpu_has(X86_FEATURE_NX))
+               kvm_enable_efer_bits(EFER_NX);
 
-       msrpm_pages = alloc_pages(GFP_KERNEL, MSRPM_ALLOC_ORDER);
+       for_each_online_cpu(cpu) {
+               r = svm_cpu_init(cpu);
+               if (r)
+                       goto err;
+       }
 
-       r = -ENOMEM;
-       if (!msrpm_pages)
-               goto err_1;
+       svm_features = cpuid_edx(SVM_CPUID_FUNC);
 
-       msrpm_va = page_address(msrpm_pages);
-       memset(msrpm_va, 0xff, PAGE_SIZE * (1 << MSRPM_ALLOC_ORDER));
-       msrpm_base = page_to_pfn(msrpm_pages) << PAGE_SHIFT;
+       if (!svm_has(SVM_FEATURE_NPT))
+               npt_enabled = false;
 
-#ifdef CONFIG_X86_64
-       set_msr_interception(msrpm_va, MSR_GS_BASE, 1, 1);
-       set_msr_interception(msrpm_va, MSR_FS_BASE, 1, 1);
-       set_msr_interception(msrpm_va, MSR_KERNEL_GS_BASE, 1, 1);
-       set_msr_interception(msrpm_va, MSR_LSTAR, 1, 1);
-       set_msr_interception(msrpm_va, MSR_CSTAR, 1, 1);
-       set_msr_interception(msrpm_va, MSR_SYSCALL_MASK, 1, 1);
-#endif
-       set_msr_interception(msrpm_va, MSR_K6_STAR, 1, 1);
-       set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_CS, 1, 1);
-       set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_ESP, 1, 1);
-       set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_EIP, 1, 1);
+       if (npt_enabled && !npt) {
+               printk(KERN_INFO "kvm: Nested Paging disabled\n");
+               npt_enabled = false;
+       }
 
-       for_each_online_cpu(cpu) {
-               r = svm_cpu_init(cpu);
-               if (r)
-                       goto err_2;
+       if (npt_enabled) {
+               printk(KERN_INFO "kvm: Nested Paging enabled\n");
+               kvm_enable_tdp();
        }
+
        return 0;
 
-err_2:
-       __free_pages(msrpm_pages, MSRPM_ALLOC_ORDER);
-       msrpm_base = 0;
-err_1:
+err:
        __free_pages(iopm_pages, IOPM_ALLOC_ORDER);
        iopm_base = 0;
        return r;
@@ -421,9 +458,8 @@ err_1:
 
 static __exit void svm_hardware_unsetup(void)
 {
-       __free_pages(pfn_to_page(msrpm_base >> PAGE_SHIFT), MSRPM_ALLOC_ORDER);
        __free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT), IOPM_ALLOC_ORDER);
-       iopm_base = msrpm_base = 0;
+       iopm_base = 0;
 }
 
 static void init_seg(struct vmcb_seg *seg)
@@ -443,15 +479,14 @@ static void init_sys_seg(struct vmcb_seg *seg, uint32_t type)
        seg->base = 0;
 }
 
-static void init_vmcb(struct vmcb *vmcb)
+static void init_vmcb(struct vcpu_svm *svm)
 {
-       struct vmcb_control_area *control = &vmcb->control;
-       struct vmcb_save_area *save = &vmcb->save;
+       struct vmcb_control_area *control = &svm->vmcb->control;
+       struct vmcb_save_area *save = &svm->vmcb->save;
 
        control->intercept_cr_read =    INTERCEPT_CR0_MASK |
                                        INTERCEPT_CR3_MASK |
-                                       INTERCEPT_CR4_MASK |
-                                       INTERCEPT_CR8_MASK;
+                                       INTERCEPT_CR4_MASK;
 
        control->intercept_cr_write =   INTERCEPT_CR0_MASK |
                                        INTERCEPT_CR3_MASK |
@@ -471,23 +506,13 @@ static void init_vmcb(struct vmcb *vmcb)
                                        INTERCEPT_DR7_MASK;
 
        control->intercept_exceptions = (1 << PF_VECTOR) |
-                                       (1 << UD_VECTOR);
+                                       (1 << UD_VECTOR) |
+                                       (1 << MC_VECTOR);
 
 
        control->intercept =    (1ULL << INTERCEPT_INTR) |
                                (1ULL << INTERCEPT_NMI) |
                                (1ULL << INTERCEPT_SMI) |
-               /*
-                * selective cr0 intercept bug?
-                *      0:   0f 22 d8                mov    %eax,%cr3
-                *      3:   0f 20 c0                mov    %cr0,%eax
-                *      6:   0d 00 00 00 80          or     $0x80000000,%eax
-                *      b:   0f 22 c0                mov    %eax,%cr0
-                * set cr3 ->interception
-                * get cr0 ->interception
-                * set cr0 -> no interception
-                */
-               /*              (1ULL << INTERCEPT_SELECTIVE_CR0) | */
                                (1ULL << INTERCEPT_CPUID) |
                                (1ULL << INTERCEPT_INVD) |
                                (1ULL << INTERCEPT_HLT) |
@@ -508,7 +533,7 @@ static void init_vmcb(struct vmcb *vmcb)
                                (1ULL << INTERCEPT_MWAIT);
 
        control->iopm_base_pa = iopm_base;
-       control->msrpm_base_pa = msrpm_base;
+       control->msrpm_base_pa = __pa(svm->msrpm);
        control->tsc_offset = 0;
        control->int_ctl = V_INTR_MASKING_MASK;
 
@@ -550,13 +575,30 @@ static void init_vmcb(struct vmcb *vmcb)
        save->cr0 = 0x00000010 | X86_CR0_PG | X86_CR0_WP;
        save->cr4 = X86_CR4_PAE;
        /* rdx = ?? */
+
+       if (npt_enabled) {
+               /* Setup VMCB for Nested Paging */
+               control->nested_ctl = 1;
+               control->intercept &= ~(1ULL << INTERCEPT_TASK_SWITCH);
+               control->intercept_exceptions &= ~(1 << PF_VECTOR);
+               control->intercept_cr_read &= ~(INTERCEPT_CR0_MASK|
+                                               INTERCEPT_CR3_MASK);
+               control->intercept_cr_write &= ~(INTERCEPT_CR0_MASK|
+                                                INTERCEPT_CR3_MASK);
+               save->g_pat = 0x0007040600070406ULL;
+               /* enable caching because the QEMU Bios doesn't enable it */
+               save->cr0 = X86_CR0_ET;
+               save->cr3 = 0;
+               save->cr4 = 0;
+       }
+       force_new_asid(&svm->vcpu);
 }
 
 static int svm_vcpu_reset(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
 
-       init_vmcb(svm->vmcb);
+       init_vmcb(svm);
 
        if (vcpu->vcpu_id != 0) {
                svm->vmcb->save.rip = 0;
@@ -571,6 +613,7 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
 {
        struct vcpu_svm *svm;
        struct page *page;
+       struct page *msrpm_pages;
        int err;
 
        svm = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
@@ -589,12 +632,19 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
                goto uninit;
        }
 
+       err = -ENOMEM;
+       msrpm_pages = alloc_pages(GFP_KERNEL, MSRPM_ALLOC_ORDER);
+       if (!msrpm_pages)
+               goto uninit;
+       svm->msrpm = page_address(msrpm_pages);
+       svm_vcpu_init_msrpm(svm->msrpm);
+
        svm->vmcb = page_address(page);
        clear_page(svm->vmcb);
        svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT;
        svm->asid_generation = 0;
        memset(svm->db_regs, 0, sizeof(svm->db_regs));
-       init_vmcb(svm->vmcb);
+       init_vmcb(svm);
 
        fx_init(&svm->vcpu);
        svm->vcpu.fpu_active = 1;
@@ -617,6 +667,7 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu)
        struct vcpu_svm *svm = to_svm(vcpu);
 
        __free_page(pfn_to_page(svm->vmcb_pa >> PAGE_SHIFT));
+       __free_pages(virt_to_page(svm->msrpm), MSRPM_ALLOC_ORDER);
        kvm_vcpu_uninit(vcpu);
        kmem_cache_free(kvm_vcpu_cache, svm);
 }
@@ -731,6 +782,13 @@ static void svm_get_segment(struct kvm_vcpu *vcpu,
        var->unusable = !var->present;
 }
 
+static int svm_get_cpl(struct kvm_vcpu *vcpu)
+{
+       struct vmcb_save_area *save = &to_svm(vcpu)->vmcb->save;
+
+       return save->cpl;
+}
+
 static void svm_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
@@ -784,6 +842,9 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
                }
        }
 #endif
+       if (npt_enabled)
+               goto set;
+
        if ((vcpu->arch.cr0 & X86_CR0_TS) && !(cr0 & X86_CR0_TS)) {
                svm->vmcb->control.intercept_exceptions &= ~(1 << NM_VECTOR);
                vcpu->fpu_active = 1;
@@ -791,18 +852,29 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 
        vcpu->arch.cr0 = cr0;
        cr0 |= X86_CR0_PG | X86_CR0_WP;
-       cr0 &= ~(X86_CR0_CD | X86_CR0_NW);
        if (!vcpu->fpu_active) {
                svm->vmcb->control.intercept_exceptions |= (1 << NM_VECTOR);
                cr0 |= X86_CR0_TS;
        }
+set:
+       /*
+        * re-enable caching here because the QEMU bios
+        * does not do it - this results in some delay at
+        * reboot
+        */
+       cr0 &= ~(X86_CR0_CD | X86_CR0_NW);
        svm->vmcb->save.cr0 = cr0;
 }
 
 static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
-       vcpu->arch.cr4 = cr4;
-       to_svm(vcpu)->vmcb->save.cr4 = cr4 | X86_CR4_PAE;
+       unsigned long host_cr4_mce = read_cr4() & X86_CR4_MCE;
+
+       vcpu->arch.cr4 = cr4;
+       if (!npt_enabled)
+               cr4 |= X86_CR4_PAE;
+       cr4 |= host_cr4_mce;
+       to_svm(vcpu)->vmcb->save.cr4 = cr4;
 }
 
 static void svm_set_segment(struct kvm_vcpu *vcpu,
@@ -833,13 +905,6 @@ static void svm_set_segment(struct kvm_vcpu *vcpu,
 
 }
 
-/* FIXME:
-
-       svm(vcpu)->vmcb->control.int_ctl &= ~V_TPR_MASK;
-       svm(vcpu)->vmcb->control.int_ctl |= (sregs->cr8 & V_TPR_MASK);
-
-*/
-
 static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg)
 {
        return -EOPNOTSUPP;
@@ -920,7 +985,7 @@ static void svm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long value,
        }
        default:
                printk(KERN_DEBUG "%s: unexpected dr %u\n",
-                      __FUNCTION__, dr);
+                      __func__, dr);
                *exception = UD_VECTOR;
                return;
        }
@@ -962,6 +1027,19 @@ static int nm_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
        return 1;
 }
 
+static int mc_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
+{
+       /*
+        * On an #MC intercept the MCE handler is not called automatically in
+        * the host. So do it by hand here.
+        */
+       asm volatile (
+               "int $0x12\n");
+       /* not sure if we ever come back to this point */
+
+       return 1;
+}
+
 static int shutdown_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
 {
        /*
@@ -969,7 +1047,7 @@ static int shutdown_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
         * so reinitialize it.
         */
        clear_page(svm->vmcb);
-       init_vmcb(svm->vmcb);
+       init_vmcb(svm);
 
        kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
        return 0;
@@ -1033,9 +1111,18 @@ static int invalid_op_interception(struct vcpu_svm *svm,
 static int task_switch_interception(struct vcpu_svm *svm,
                                    struct kvm_run *kvm_run)
 {
-       pr_unimpl(&svm->vcpu, "%s: task switch is unsupported\n", __FUNCTION__);
-       kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
-       return 0;
+       u16 tss_selector;
+
+       tss_selector = (u16)svm->vmcb->control.exit_info_1;
+       if (svm->vmcb->control.exit_info_2 &
+           (1ULL << SVM_EXITINFOSHIFT_TS_REASON_IRET))
+               return kvm_task_switch(&svm->vcpu, tss_selector,
+                                      TASK_SWITCH_IRET);
+       if (svm->vmcb->control.exit_info_2 &
+           (1ULL << SVM_EXITINFOSHIFT_TS_REASON_JMP))
+               return kvm_task_switch(&svm->vcpu, tss_selector,
+                                      TASK_SWITCH_JMP);
+       return kvm_task_switch(&svm->vcpu, tss_selector, TASK_SWITCH_CALL);
 }
 
 static int cpuid_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
@@ -1049,7 +1136,7 @@ static int emulate_on_interception(struct vcpu_svm *svm,
                                   struct kvm_run *kvm_run)
 {
        if (emulate_instruction(&svm->vcpu, NULL, 0, 0, 0) != EMULATE_DONE)
-               pr_unimpl(&svm->vcpu, "%s: failed\n", __FUNCTION__);
+               pr_unimpl(&svm->vcpu, "%s: failed\n", __func__);
        return 1;
 }
 
@@ -1179,8 +1266,19 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)
                svm->vmcb->save.sysenter_esp = data;
                break;
        case MSR_IA32_DEBUGCTLMSR:
-               pr_unimpl(vcpu, "%s: MSR_IA32_DEBUGCTLMSR 0x%llx, nop\n",
-                               __FUNCTION__, data);
+               if (!svm_has(SVM_FEATURE_LBRV)) {
+                       pr_unimpl(vcpu, "%s: MSR_IA32_DEBUGCTL 0x%llx, nop\n",
+                                       __func__, data);
+                       break;
+               }
+               if (data & DEBUGCTL_RESERVED_BITS)
+                       return 1;
+
+               svm->vmcb->save.dbgctl = data;
+               if (data & (1ULL<<0))
+                       svm_enable_lbrv(svm);
+               else
+                       svm_disable_lbrv(svm);
                break;
        case MSR_K7_EVNTSEL0:
        case MSR_K7_EVNTSEL1:
@@ -1265,6 +1363,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm,
        [SVM_EXIT_EXCP_BASE + UD_VECTOR]        = ud_interception,
        [SVM_EXIT_EXCP_BASE + PF_VECTOR]        = pf_interception,
        [SVM_EXIT_EXCP_BASE + NM_VECTOR]        = nm_interception,
+       [SVM_EXIT_EXCP_BASE + MC_VECTOR]        = mc_interception,
        [SVM_EXIT_INTR]                         = nop_on_interception,
        [SVM_EXIT_NMI]                          = nop_on_interception,
        [SVM_EXIT_SMI]                          = nop_on_interception,
@@ -1290,14 +1389,34 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm,
        [SVM_EXIT_WBINVD]                       = emulate_on_interception,
        [SVM_EXIT_MONITOR]                      = invalid_op_interception,
        [SVM_EXIT_MWAIT]                        = invalid_op_interception,
+       [SVM_EXIT_NPF]                          = pf_interception,
 };
 
-
 static int handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
        u32 exit_code = svm->vmcb->control.exit_code;
 
+       if (npt_enabled) {
+               int mmu_reload = 0;
+               if ((vcpu->arch.cr0 ^ svm->vmcb->save.cr0) & X86_CR0_PG) {
+                       svm_set_cr0(vcpu, svm->vmcb->save.cr0);
+                       mmu_reload = 1;
+               }
+               vcpu->arch.cr0 = svm->vmcb->save.cr0;
+               vcpu->arch.cr3 = svm->vmcb->save.cr3;
+               if (is_paging(vcpu) && is_pae(vcpu) && !is_long_mode(vcpu)) {
+                       if (!load_pdptrs(vcpu, vcpu->arch.cr3)) {
+                               kvm_inject_gp(vcpu, 0);
+                               return 1;
+                       }
+               }
+               if (mmu_reload) {
+                       kvm_mmu_reset_context(vcpu);
+                       kvm_mmu_load(vcpu);
+               }
+       }
+
        kvm_reput_irq(svm);
 
        if (svm->vmcb->control.exit_code == SVM_EXIT_ERR) {
@@ -1308,10 +1427,11 @@ static int handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        }
 
        if (is_external_interrupt(svm->vmcb->control.exit_int_info) &&
-           exit_code != SVM_EXIT_EXCP_BASE + PF_VECTOR)
+           exit_code != SVM_EXIT_EXCP_BASE + PF_VECTOR &&
+           exit_code != SVM_EXIT_NPF)
                printk(KERN_ERR "%s: unexpected exit_ini_info 0x%x "
                       "exit_code 0x%x\n",
-                      __FUNCTION__, svm->vmcb->control.exit_int_info,
+                      __func__, svm->vmcb->control.exit_int_info,
                       exit_code);
 
        if (exit_code >= ARRAY_SIZE(svm_exit_handlers)
@@ -1364,6 +1484,27 @@ static void svm_set_irq(struct kvm_vcpu *vcpu, int irq)
        svm_inject_irq(svm, irq);
 }
 
+static void update_cr8_intercept(struct kvm_vcpu *vcpu)
+{
+       struct vcpu_svm *svm = to_svm(vcpu);
+       struct vmcb *vmcb = svm->vmcb;
+       int max_irr, tpr;
+
+       if (!irqchip_in_kernel(vcpu->kvm) || vcpu->arch.apic->vapic_addr)
+               return;
+
+       vmcb->control.intercept_cr_write &= ~INTERCEPT_CR8_MASK;
+
+       max_irr = kvm_lapic_find_highest_irr(vcpu);
+       if (max_irr == -1)
+               return;
+
+       tpr = kvm_lapic_get_cr8(vcpu) << 4;
+
+       if (tpr >= (max_irr & 0xf0))
+               vmcb->control.intercept_cr_write |= INTERCEPT_CR8_MASK;
+}
+
 static void svm_intr_assist(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
@@ -1376,14 +1517,14 @@ static void svm_intr_assist(struct kvm_vcpu *vcpu)
                              SVM_EVTINJ_VEC_MASK;
                vmcb->control.exit_int_info = 0;
                svm_inject_irq(svm, intr_vector);
-               return;
+               goto out;
        }
 
        if (vmcb->control.int_ctl & V_IRQ_MASK)
-               return;
+               goto out;
 
        if (!kvm_cpu_has_interrupt(vcpu))
-               return;
+               goto out;
 
        if (!(vmcb->save.rflags & X86_EFLAGS_IF) ||
            (vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) ||
@@ -1391,12 +1532,14 @@ static void svm_intr_assist(struct kvm_vcpu *vcpu)
                /* unable to deliver irq, set pending irq */
                vmcb->control.intercept |= (1ULL << INTERCEPT_VINTR);
                svm_inject_irq(svm, 0x0);
-               return;
+               goto out;
        }
        /* Okay, we can deliver the interrupt: grab it and update PIC state. */
        intr_vector = kvm_cpu_get_interrupt(vcpu);
        svm_inject_irq(svm, intr_vector);
        kvm_timer_intr_post(vcpu, intr_vector);
+out:
+       update_cr8_intercept(vcpu);
 }
 
 static void kvm_reput_irq(struct vcpu_svm *svm)
@@ -1482,6 +1625,29 @@ static void svm_prepare_guest_switch(struct kvm_vcpu *vcpu)
 {
 }
 
+static inline void sync_cr8_to_lapic(struct kvm_vcpu *vcpu)
+{
+       struct vcpu_svm *svm = to_svm(vcpu);
+
+       if (!(svm->vmcb->control.intercept_cr_write & INTERCEPT_CR8_MASK)) {
+               int cr8 = svm->vmcb->control.int_ctl & V_TPR_MASK;
+               kvm_lapic_set_tpr(vcpu, cr8);
+       }
+}
+
+static inline void sync_lapic_to_cr8(struct kvm_vcpu *vcpu)
+{
+       struct vcpu_svm *svm = to_svm(vcpu);
+       u64 cr8;
+
+       if (!irqchip_in_kernel(vcpu->kvm))
+               return;
+
+       cr8 = kvm_get_cr8(vcpu);
+       svm->vmcb->control.int_ctl &= ~V_TPR_MASK;
+       svm->vmcb->control.int_ctl |= cr8 & V_TPR_MASK;
+}
+
 static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
@@ -1491,6 +1657,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
        pre_svm_run(svm);
 
+       sync_lapic_to_cr8(vcpu);
+
        save_host_msrs(vcpu);
        fs_selector = read_fs();
        gs_selector = read_gs();
@@ -1499,6 +1667,9 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        svm->host_dr6 = read_dr6();
        svm->host_dr7 = read_dr7();
        svm->vmcb->save.cr2 = vcpu->arch.cr2;
+       /* required for live migration with NPT */
+       if (npt_enabled)
+               svm->vmcb->save.cr3 = vcpu->arch.cr3;
 
        if (svm->vmcb->save.dr7 & 0xff) {
                write_dr7(0);
@@ -1635,6 +1806,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
        stgi();
 
+       sync_cr8_to_lapic(vcpu);
+
        svm->next_rip = 0;
 }
 
@@ -1642,6 +1815,12 @@ static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
 
+       if (npt_enabled) {
+               svm->vmcb->control.nested_cr3 = root;
+               force_new_asid(vcpu);
+               return;
+       }
+
        svm->vmcb->save.cr3 = root;
        force_new_asid(vcpu);
 
@@ -1709,6 +1888,7 @@ static struct kvm_x86_ops svm_x86_ops = {
        .get_segment_base = svm_get_segment_base,
        .get_segment = svm_get_segment,
        .set_segment = svm_set_segment,
+       .get_cpl = svm_get_cpl,
        .get_cs_db_l_bits = kvm_get_cs_db_l_bits,
        .decache_cr4_guest_bits = svm_decache_cr4_guest_bits,
        .set_cr0 = svm_set_cr0,
index 5fd50491b55505fd1f02a033c3f244e134efdf5b..1b8afa78e869449f3c66bfa7c31929b429d9513a 100644 (file)
@@ -238,6 +238,9 @@ struct __attribute__ ((__packed__)) vmcb {
 #define SVM_EXITINTINFO_VALID SVM_EVTINJ_VALID
 #define SVM_EXITINTINFO_VALID_ERR SVM_EVTINJ_VALID_ERR
 
+#define SVM_EXITINFOSHIFT_TS_REASON_IRET 36
+#define SVM_EXITINFOSHIFT_TS_REASON_JMP 38
+
 #define        SVM_EXIT_READ_CR0       0x000
 #define        SVM_EXIT_READ_CR3       0x003
 #define        SVM_EXIT_READ_CR4       0x004
diff --git a/arch/x86/kvm/tss.h b/arch/x86/kvm/tss.h
new file mode 100644 (file)
index 0000000..622aa10
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef __TSS_SEGMENT_H
+#define __TSS_SEGMENT_H
+
+struct tss_segment_32 {
+       u32 prev_task_link;
+       u32 esp0;
+       u32 ss0;
+       u32 esp1;
+       u32 ss1;
+       u32 esp2;
+       u32 ss2;
+       u32 cr3;
+       u32 eip;
+       u32 eflags;
+       u32 eax;
+       u32 ecx;
+       u32 edx;
+       u32 ebx;
+       u32 esp;
+       u32 ebp;
+       u32 esi;
+       u32 edi;
+       u32 es;
+       u32 cs;
+       u32 ss;
+       u32 ds;
+       u32 fs;
+       u32 gs;
+       u32 ldt_selector;
+       u16 t;
+       u16 io_map;
+};
+
+struct tss_segment_16 {
+       u16 prev_task_link;
+       u16 sp0;
+       u16 ss0;
+       u16 sp1;
+       u16 ss1;
+       u16 sp2;
+       u16 ss2;
+       u16 ip;
+       u16 flag;
+       u16 ax;
+       u16 cx;
+       u16 dx;
+       u16 bx;
+       u16 sp;
+       u16 bp;
+       u16 si;
+       u16 di;
+       u16 es;
+       u16 cs;
+       u16 ss;
+       u16 ds;
+       u16 ldt;
+};
+
+#endif
index 8e1462880d1f1dec6d6162124db057ae5f687868..8e5d6645b90d11e08c6f71153e722a004c570457 100644 (file)
@@ -17,7 +17,6 @@
 
 #include "irq.h"
 #include "vmx.h"
-#include "segment_descriptor.h"
 #include "mmu.h"
 
 #include <linux/kvm_host.h>
@@ -37,6 +36,12 @@ MODULE_LICENSE("GPL");
 static int bypass_guest_pf = 1;
 module_param(bypass_guest_pf, bool, 0);
 
+static int enable_vpid = 1;
+module_param(enable_vpid, bool, 0);
+
+static int flexpriority_enabled = 1;
+module_param(flexpriority_enabled, bool, 0);
+
 struct vmcs {
        u32 revision_id;
        u32 abort;
@@ -71,6 +76,7 @@ struct vcpu_vmx {
                        unsigned rip;
                } irq;
        } rmode;
+       int vpid;
 };
 
 static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
@@ -85,6 +91,10 @@ static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
 
 static struct page *vmx_io_bitmap_a;
 static struct page *vmx_io_bitmap_b;
+static struct page *vmx_msr_bitmap;
+
+static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS);
+static DEFINE_SPINLOCK(vmx_vpid_lock);
 
 static struct vmcs_config {
        int size;
@@ -176,6 +186,11 @@ static inline int is_external_interrupt(u32 intr_info)
                == (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
 }
 
+static inline int cpu_has_vmx_msr_bitmap(void)
+{
+       return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS);
+}
+
 static inline int cpu_has_vmx_tpr_shadow(void)
 {
        return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW);
@@ -194,8 +209,9 @@ static inline int cpu_has_secondary_exec_ctrls(void)
 
 static inline bool cpu_has_vmx_virtualize_apic_accesses(void)
 {
-       return (vmcs_config.cpu_based_2nd_exec_ctrl &
-               SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
+       return flexpriority_enabled
+               && (vmcs_config.cpu_based_2nd_exec_ctrl &
+                   SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
 }
 
 static inline int vm_need_virtualize_apic_accesses(struct kvm *kvm)
@@ -204,6 +220,12 @@ static inline int vm_need_virtualize_apic_accesses(struct kvm *kvm)
                (irqchip_in_kernel(kvm)));
 }
 
+static inline int cpu_has_vmx_vpid(void)
+{
+       return (vmcs_config.cpu_based_2nd_exec_ctrl &
+               SECONDARY_EXEC_ENABLE_VPID);
+}
+
 static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
 {
        int i;
@@ -214,6 +236,20 @@ static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
        return -1;
 }
 
+static inline void __invvpid(int ext, u16 vpid, gva_t gva)
+{
+    struct {
+       u64 vpid : 16;
+       u64 rsvd : 48;
+       u64 gva;
+    } operand = { vpid, 0, gva };
+
+    asm volatile (ASM_VMX_INVVPID
+                 /* CF==1 or ZF==1 --> rc = -1 */
+                 "; ja 1f ; ud2 ; 1:"
+                 : : "a"(&operand), "c"(ext) : "cc", "memory");
+}
+
 static struct kvm_msr_entry *find_msr_entry(struct vcpu_vmx *vmx, u32 msr)
 {
        int i;
@@ -257,6 +293,14 @@ static void vcpu_clear(struct vcpu_vmx *vmx)
        vmx->launched = 0;
 }
 
+static inline void vpid_sync_vcpu_all(struct vcpu_vmx *vmx)
+{
+       if (vmx->vpid == 0)
+               return;
+
+       __invvpid(VMX_VPID_EXTENT_SINGLE_CONTEXT, vmx->vpid, 0);
+}
+
 static unsigned long vmcs_readl(unsigned long field)
 {
        unsigned long value;
@@ -353,7 +397,7 @@ static void reload_tss(void)
         * VT restores TR but not its size.  Useless.
         */
        struct descriptor_table gdt;
-       struct segment_descriptor *descs;
+       struct desc_struct *descs;
 
        get_gdt(&gdt);
        descs = (void *)gdt.base;
@@ -485,11 +529,12 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        u64 phys_addr = __pa(vmx->vmcs);
-       u64 tsc_this, delta;
+       u64 tsc_this, delta, new_offset;
 
        if (vcpu->cpu != cpu) {
                vcpu_clear(vmx);
                kvm_migrate_apic_timer(vcpu);
+               vpid_sync_vcpu_all(vmx);
        }
 
        if (per_cpu(current_vmcs, cpu) != vmx->vmcs) {
@@ -524,8 +569,11 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
                 * Make sure the time stamp counter is monotonous.
                 */
                rdtscll(tsc_this);
-               delta = vcpu->arch.host_tsc - tsc_this;
-               vmcs_write64(TSC_OFFSET, vmcs_read64(TSC_OFFSET) + delta);
+               if (tsc_this < vcpu->arch.host_tsc) {
+                       delta = vcpu->arch.host_tsc - tsc_this;
+                       new_offset = vmcs_read64(TSC_OFFSET) + delta;
+                       vmcs_write64(TSC_OFFSET, new_offset);
+               }
        }
 }
 
@@ -596,7 +644,7 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
 {
        vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
                     nr | INTR_TYPE_EXCEPTION
-                    | (has_error_code ? INTR_INFO_DELIEVER_CODE_MASK : 0)
+                    | (has_error_code ? INTR_INFO_DELIVER_CODE_MASK : 0)
                     | INTR_INFO_VALID_MASK);
        if (has_error_code)
                vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
@@ -959,6 +1007,7 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
              CPU_BASED_MOV_DR_EXITING |
              CPU_BASED_USE_TSC_OFFSETING;
        opt = CPU_BASED_TPR_SHADOW |
+             CPU_BASED_USE_MSR_BITMAPS |
              CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
        if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS,
                                &_cpu_based_exec_control) < 0)
@@ -971,7 +1020,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
        if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) {
                min = 0;
                opt = SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
-                       SECONDARY_EXEC_WBINVD_EXITING;
+                       SECONDARY_EXEC_WBINVD_EXITING |
+                       SECONDARY_EXEC_ENABLE_VPID;
                if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS2,
                                        &_cpu_based_2nd_exec_control) < 0)
                        return -EIO;
@@ -1080,6 +1130,10 @@ static __init int hardware_setup(void)
 {
        if (setup_vmcs_config(&vmcs_config) < 0)
                return -EIO;
+
+       if (boot_cpu_has(X86_FEATURE_NX))
+               kvm_enable_efer_bits(EFER_NX);
+
        return alloc_kvm_area();
 }
 
@@ -1214,7 +1268,7 @@ static void enter_lmode(struct kvm_vcpu *vcpu)
        guest_tr_ar = vmcs_read32(GUEST_TR_AR_BYTES);
        if ((guest_tr_ar & AR_TYPE_MASK) != AR_TYPE_BUSY_64_TSS) {
                printk(KERN_DEBUG "%s: tss fixup for long mode. \n",
-                      __FUNCTION__);
+                      __func__);
                vmcs_write32(GUEST_TR_AR_BYTES,
                             (guest_tr_ar & ~AR_TYPE_MASK)
                             | AR_TYPE_BUSY_64_TSS);
@@ -1239,6 +1293,11 @@ static void exit_lmode(struct kvm_vcpu *vcpu)
 
 #endif
 
+static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
+{
+       vpid_sync_vcpu_all(to_vmx(vcpu));
+}
+
 static void vmx_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
 {
        vcpu->arch.cr4 &= KVM_GUEST_CR4_MASK;
@@ -1275,6 +1334,7 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 
 static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 {
+       vmx_flush_tlb(vcpu);
        vmcs_writel(GUEST_CR3, cr3);
        if (vcpu->arch.cr0 & X86_CR0_PE)
                vmx_fpu_deactivate(vcpu);
@@ -1288,14 +1348,14 @@ static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
        vcpu->arch.cr4 = cr4;
 }
 
-#ifdef CONFIG_X86_64
-
 static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        struct kvm_msr_entry *msr = find_msr_entry(vmx, MSR_EFER);
 
        vcpu->arch.shadow_efer = efer;
+       if (!msr)
+               return;
        if (efer & EFER_LMA) {
                vmcs_write32(VM_ENTRY_CONTROLS,
                                     vmcs_read32(VM_ENTRY_CONTROLS) |
@@ -1312,8 +1372,6 @@ static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
        setup_msrs(vmx);
 }
 
-#endif
-
 static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)
 {
        struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
@@ -1344,6 +1402,20 @@ static void vmx_get_segment(struct kvm_vcpu *vcpu,
        var->unusable = (ar >> 16) & 1;
 }
 
+static int vmx_get_cpl(struct kvm_vcpu *vcpu)
+{
+       struct kvm_segment kvm_seg;
+
+       if (!(vcpu->arch.cr0 & X86_CR0_PE)) /* if real mode */
+               return 0;
+
+       if (vmx_get_rflags(vcpu) & X86_EFLAGS_VM) /* if virtual 8086 */
+               return 3;
+
+       vmx_get_segment(vcpu, &kvm_seg, VCPU_SREG_CS);
+       return kvm_seg.selector & 3;
+}
+
 static u32 vmx_segment_access_rights(struct kvm_segment *var)
 {
        u32 ar;
@@ -1433,7 +1505,6 @@ static int init_rmode_tss(struct kvm *kvm)
        int ret = 0;
        int r;
 
-       down_read(&kvm->slots_lock);
        r = kvm_clear_guest_page(kvm, fn, 0, PAGE_SIZE);
        if (r < 0)
                goto out;
@@ -1456,7 +1527,6 @@ static int init_rmode_tss(struct kvm *kvm)
 
        ret = 1;
 out:
-       up_read(&kvm->slots_lock);
        return ret;
 }
 
@@ -1494,6 +1564,46 @@ out:
        return r;
 }
 
+static void allocate_vpid(struct vcpu_vmx *vmx)
+{
+       int vpid;
+
+       vmx->vpid = 0;
+       if (!enable_vpid || !cpu_has_vmx_vpid())
+               return;
+       spin_lock(&vmx_vpid_lock);
+       vpid = find_first_zero_bit(vmx_vpid_bitmap, VMX_NR_VPIDS);
+       if (vpid < VMX_NR_VPIDS) {
+               vmx->vpid = vpid;
+               __set_bit(vpid, vmx_vpid_bitmap);
+       }
+       spin_unlock(&vmx_vpid_lock);
+}
+
+void vmx_disable_intercept_for_msr(struct page *msr_bitmap, u32 msr)
+{
+       void *va;
+
+       if (!cpu_has_vmx_msr_bitmap())
+               return;
+
+       /*
+        * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals
+        * have the write-low and read-high bitmap offsets the wrong way round.
+        * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff.
+        */
+       va = kmap(msr_bitmap);
+       if (msr <= 0x1fff) {
+               __clear_bit(msr, va + 0x000); /* read-low */
+               __clear_bit(msr, va + 0x800); /* write-low */
+       } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
+               msr &= 0x1fff;
+               __clear_bit(msr, va + 0x400); /* read-high */
+               __clear_bit(msr, va + 0xc00); /* write-high */
+       }
+       kunmap(msr_bitmap);
+}
+
 /*
  * Sets up the vmcs for emulated real mode.
  */
@@ -1511,6 +1621,9 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
        vmcs_write64(IO_BITMAP_A, page_to_phys(vmx_io_bitmap_a));
        vmcs_write64(IO_BITMAP_B, page_to_phys(vmx_io_bitmap_b));
 
+       if (cpu_has_vmx_msr_bitmap())
+               vmcs_write64(MSR_BITMAP, page_to_phys(vmx_msr_bitmap));
+
        vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
 
        /* Control */
@@ -1532,6 +1645,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
                if (!vm_need_virtualize_apic_accesses(vmx->vcpu.kvm))
                        exec_control &=
                                ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+               if (vmx->vpid == 0)
+                       exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
                vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
        }
 
@@ -1613,6 +1728,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
        u64 msr;
        int ret;
 
+       down_read(&vcpu->kvm->slots_lock);
        if (!init_rmode_tss(vmx->vcpu.kvm)) {
                ret = -ENOMEM;
                goto out;
@@ -1621,7 +1737,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
        vmx->vcpu.arch.rmode.active = 0;
 
        vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val();
-       set_cr8(&vmx->vcpu, 0);
+       kvm_set_cr8(&vmx->vcpu, 0);
        msr = 0xfee00000 | MSR_IA32_APICBASE_ENABLE;
        if (vmx->vcpu.vcpu_id == 0)
                msr |= MSR_IA32_APICBASE_BSP;
@@ -1704,18 +1820,22 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
                vmcs_write64(APIC_ACCESS_ADDR,
                             page_to_phys(vmx->vcpu.kvm->arch.apic_access_page));
 
+       if (vmx->vpid != 0)
+               vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
+
        vmx->vcpu.arch.cr0 = 0x60000010;
        vmx_set_cr0(&vmx->vcpu, vmx->vcpu.arch.cr0); /* enter rmode */
        vmx_set_cr4(&vmx->vcpu, 0);
-#ifdef CONFIG_X86_64
        vmx_set_efer(&vmx->vcpu, 0);
-#endif
        vmx_fpu_activate(&vmx->vcpu);
        update_exception_bitmap(&vmx->vcpu);
 
-       return 0;
+       vpid_sync_vcpu_all(vmx);
+
+       ret = 0;
 
 out:
+       up_read(&vcpu->kvm->slots_lock);
        return ret;
 }
 
@@ -1723,6 +1843,8 @@ static void vmx_inject_irq(struct kvm_vcpu *vcpu, int irq)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
 
+       KVMTRACE_1D(INJ_VIRQ, vcpu, (u32)irq, handler);
+
        if (vcpu->arch.rmode.active) {
                vmx->rmode.irq.pending = true;
                vmx->rmode.irq.vector = irq;
@@ -1844,7 +1966,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        if ((vect_info & VECTORING_INFO_VALID_MASK) &&
                                                !is_page_fault(intr_info))
                printk(KERN_ERR "%s: unexpected, vectoring info 0x%x "
-                      "intr info 0x%x\n", __FUNCTION__, vect_info, intr_info);
+                      "intr info 0x%x\n", __func__, vect_info, intr_info);
 
        if (!irqchip_in_kernel(vcpu->kvm) && is_external_interrupt(vect_info)) {
                int irq = vect_info & VECTORING_INFO_VECTOR_MASK;
@@ -1869,10 +1991,12 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
        error_code = 0;
        rip = vmcs_readl(GUEST_RIP);
-       if (intr_info & INTR_INFO_DELIEVER_CODE_MASK)
+       if (intr_info & INTR_INFO_DELIVER_CODE_MASK)
                error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
        if (is_page_fault(intr_info)) {
                cr2 = vmcs_readl(EXIT_QUALIFICATION);
+               KVMTRACE_3D(PAGE_FAULT, vcpu, error_code, (u32)cr2,
+                           (u32)((u64)cr2 >> 32), handler);
                return kvm_mmu_page_fault(vcpu, cr2, error_code);
        }
 
@@ -1901,6 +2025,7 @@ static int handle_external_interrupt(struct kvm_vcpu *vcpu,
                                     struct kvm_run *kvm_run)
 {
        ++vcpu->stat.irq_exits;
+       KVMTRACE_1D(INTR, vcpu, vmcs_read32(VM_EXIT_INTR_INFO), handler);
        return 1;
 }
 
@@ -1958,25 +2083,27 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        reg = (exit_qualification >> 8) & 15;
        switch ((exit_qualification >> 4) & 3) {
        case 0: /* mov to cr */
+               KVMTRACE_3D(CR_WRITE, vcpu, (u32)cr, (u32)vcpu->arch.regs[reg],
+                           (u32)((u64)vcpu->arch.regs[reg] >> 32), handler);
                switch (cr) {
                case 0:
                        vcpu_load_rsp_rip(vcpu);
-                       set_cr0(vcpu, vcpu->arch.regs[reg]);
+                       kvm_set_cr0(vcpu, vcpu->arch.regs[reg]);
                        skip_emulated_instruction(vcpu);
                        return 1;
                case 3:
                        vcpu_load_rsp_rip(vcpu);
-                       set_cr3(vcpu, vcpu->arch.regs[reg]);
+                       kvm_set_cr3(vcpu, vcpu->arch.regs[reg]);
                        skip_emulated_instruction(vcpu);
                        return 1;
                case 4:
                        vcpu_load_rsp_rip(vcpu);
-                       set_cr4(vcpu, vcpu->arch.regs[reg]);
+                       kvm_set_cr4(vcpu, vcpu->arch.regs[reg]);
                        skip_emulated_instruction(vcpu);
                        return 1;
                case 8:
                        vcpu_load_rsp_rip(vcpu);
-                       set_cr8(vcpu, vcpu->arch.regs[reg]);
+                       kvm_set_cr8(vcpu, vcpu->arch.regs[reg]);
                        skip_emulated_instruction(vcpu);
                        if (irqchip_in_kernel(vcpu->kvm))
                                return 1;
@@ -1990,6 +2117,7 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                vcpu->arch.cr0 &= ~X86_CR0_TS;
                vmcs_writel(CR0_READ_SHADOW, vcpu->arch.cr0);
                vmx_fpu_activate(vcpu);
+               KVMTRACE_0D(CLTS, vcpu, handler);
                skip_emulated_instruction(vcpu);
                return 1;
        case 1: /*mov from cr*/
@@ -1998,18 +2126,24 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                        vcpu_load_rsp_rip(vcpu);
                        vcpu->arch.regs[reg] = vcpu->arch.cr3;
                        vcpu_put_rsp_rip(vcpu);
+                       KVMTRACE_3D(CR_READ, vcpu, (u32)cr,
+                                   (u32)vcpu->arch.regs[reg],
+                                   (u32)((u64)vcpu->arch.regs[reg] >> 32),
+                                   handler);
                        skip_emulated_instruction(vcpu);
                        return 1;
                case 8:
                        vcpu_load_rsp_rip(vcpu);
-                       vcpu->arch.regs[reg] = get_cr8(vcpu);
+                       vcpu->arch.regs[reg] = kvm_get_cr8(vcpu);
                        vcpu_put_rsp_rip(vcpu);
+                       KVMTRACE_2D(CR_READ, vcpu, (u32)cr,
+                                   (u32)vcpu->arch.regs[reg], handler);
                        skip_emulated_instruction(vcpu);
                        return 1;
                }
                break;
        case 3: /* lmsw */
-               lmsw(vcpu, (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f);
+               kvm_lmsw(vcpu, (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f);
 
                skip_emulated_instruction(vcpu);
                return 1;
@@ -2049,6 +2183,7 @@ static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                        val = 0;
                }
                vcpu->arch.regs[reg] = val;
+               KVMTRACE_2D(DR_READ, vcpu, (u32)dr, (u32)val, handler);
        } else {
                /* mov to dr */
        }
@@ -2073,6 +2208,9 @@ static int handle_rdmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                return 1;
        }
 
+       KVMTRACE_3D(MSR_READ, vcpu, ecx, (u32)data, (u32)(data >> 32),
+                   handler);
+
        /* FIXME: handling of bits 32:63 of rax, rdx */
        vcpu->arch.regs[VCPU_REGS_RAX] = data & -1u;
        vcpu->arch.regs[VCPU_REGS_RDX] = (data >> 32) & -1u;
@@ -2086,6 +2224,9 @@ static int handle_wrmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        u64 data = (vcpu->arch.regs[VCPU_REGS_RAX] & -1u)
                | ((u64)(vcpu->arch.regs[VCPU_REGS_RDX] & -1u) << 32);
 
+       KVMTRACE_3D(MSR_WRITE, vcpu, ecx, (u32)data, (u32)(data >> 32),
+                   handler);
+
        if (vmx_set_msr(vcpu, ecx, data) != 0) {
                kvm_inject_gp(vcpu, 0);
                return 1;
@@ -2110,6 +2251,9 @@ static int handle_interrupt_window(struct kvm_vcpu *vcpu,
        cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
        cpu_based_vm_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
        vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
+
+       KVMTRACE_0D(PEND_INTR, vcpu, handler);
+
        /*
         * If the user space waits to inject interrupts, exit as soon as
         * possible
@@ -2152,6 +2296,8 @@ static int handle_apic_access(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
        offset = exit_qualification & 0xffful;
 
+       KVMTRACE_1D(APIC_ACCESS, vcpu, (u32)offset, handler);
+
        er = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
 
        if (er !=  EMULATE_DONE) {
@@ -2163,6 +2309,20 @@ static int handle_apic_access(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        return 1;
 }
 
+static int handle_task_switch(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       unsigned long exit_qualification;
+       u16 tss_selector;
+       int reason;
+
+       exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+       reason = (u32)exit_qualification >> 30;
+       tss_selector = exit_qualification;
+
+       return kvm_task_switch(vcpu, tss_selector, reason);
+}
+
 /*
  * The exit handlers return 1 if the exit was handled fully and guest execution
  * may resume.  Otherwise they set the kvm_run parameter to indicate what needs
@@ -2185,6 +2345,7 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu,
        [EXIT_REASON_TPR_BELOW_THRESHOLD]     = handle_tpr_below_threshold,
        [EXIT_REASON_APIC_ACCESS]             = handle_apic_access,
        [EXIT_REASON_WBINVD]                  = handle_wbinvd,
+       [EXIT_REASON_TASK_SWITCH]             = handle_task_switch,
 };
 
 static const int kvm_vmx_max_exit_handlers =
@@ -2200,6 +2361,9 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        u32 vectoring_info = vmx->idt_vectoring_info;
 
+       KVMTRACE_3D(VMEXIT, vcpu, exit_reason, (u32)vmcs_readl(GUEST_RIP),
+                   (u32)((u64)vmcs_readl(GUEST_RIP) >> 32), entryexit);
+
        if (unlikely(vmx->fail)) {
                kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
                kvm_run->fail_entry.hardware_entry_failure_reason
@@ -2210,7 +2374,7 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        if ((vectoring_info & VECTORING_INFO_VALID_MASK) &&
                                exit_reason != EXIT_REASON_EXCEPTION_NMI)
                printk(KERN_WARNING "%s: unexpected, valid vectoring info and "
-                      "exit reason is 0x%x\n", __FUNCTION__, exit_reason);
+                      "exit reason is 0x%x\n", __func__, exit_reason);
        if (exit_reason < kvm_vmx_max_exit_handlers
            && kvm_vmx_exit_handlers[exit_reason])
                return kvm_vmx_exit_handlers[exit_reason](vcpu, kvm_run);
@@ -2221,10 +2385,6 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        return 0;
 }
 
-static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
-{
-}
-
 static void update_tpr_threshold(struct kvm_vcpu *vcpu)
 {
        int max_irr, tpr;
@@ -2285,11 +2445,13 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu)
                        return;
                }
 
+               KVMTRACE_1D(REDELIVER_EVT, vcpu, idtv_info_field, handler);
+
                vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field);
                vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
                                vmcs_read32(VM_EXIT_INSTRUCTION_LEN));
 
-               if (unlikely(idtv_info_field & INTR_INFO_DELIEVER_CODE_MASK))
+               if (unlikely(idtv_info_field & INTR_INFO_DELIVER_CODE_MASK))
                        vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE,
                                vmcs_read32(IDT_VECTORING_ERROR_CODE));
                if (unlikely(has_ext_irq))
@@ -2470,8 +2632,10 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
 
        /* We need to handle NMIs before interrupts are enabled */
-       if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) /* nmi */
+       if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { /* nmi */
+               KVMTRACE_0D(NMI, vcpu, handler);
                asm("int $2");
+       }
 }
 
 static void vmx_free_vmcs(struct kvm_vcpu *vcpu)
@@ -2489,6 +2653,10 @@ static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
 
+       spin_lock(&vmx_vpid_lock);
+       if (vmx->vpid != 0)
+               __clear_bit(vmx->vpid, vmx_vpid_bitmap);
+       spin_unlock(&vmx_vpid_lock);
        vmx_free_vmcs(vcpu);
        kfree(vmx->host_msrs);
        kfree(vmx->guest_msrs);
@@ -2505,6 +2673,8 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
        if (!vmx)
                return ERR_PTR(-ENOMEM);
 
+       allocate_vpid(vmx);
+
        err = kvm_vcpu_init(&vmx->vcpu, kvm, id);
        if (err)
                goto free_vcpu;
@@ -2591,14 +2761,13 @@ static struct kvm_x86_ops vmx_x86_ops = {
        .get_segment_base = vmx_get_segment_base,
        .get_segment = vmx_get_segment,
        .set_segment = vmx_set_segment,
+       .get_cpl = vmx_get_cpl,
        .get_cs_db_l_bits = vmx_get_cs_db_l_bits,
        .decache_cr4_guest_bits = vmx_decache_cr4_guest_bits,
        .set_cr0 = vmx_set_cr0,
        .set_cr3 = vmx_set_cr3,
        .set_cr4 = vmx_set_cr4,
-#ifdef CONFIG_X86_64
        .set_efer = vmx_set_efer,
-#endif
        .get_idt = vmx_get_idt,
        .set_idt = vmx_set_idt,
        .get_gdt = vmx_get_gdt,
@@ -2626,7 +2795,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
 
 static int __init vmx_init(void)
 {
-       void *iova;
+       void *va;
        int r;
 
        vmx_io_bitmap_a = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
@@ -2639,28 +2808,48 @@ static int __init vmx_init(void)
                goto out;
        }
 
+       vmx_msr_bitmap = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
+       if (!vmx_msr_bitmap) {
+               r = -ENOMEM;
+               goto out1;
+       }
+
        /*
         * Allow direct access to the PC debug port (it is often used for I/O
         * delays, but the vmexits simply slow things down).
         */
-       iova = kmap(vmx_io_bitmap_a);
-       memset(iova, 0xff, PAGE_SIZE);
-       clear_bit(0x80, iova);
+       va = kmap(vmx_io_bitmap_a);
+       memset(va, 0xff, PAGE_SIZE);
+       clear_bit(0x80, va);
        kunmap(vmx_io_bitmap_a);
 
-       iova = kmap(vmx_io_bitmap_b);
-       memset(iova, 0xff, PAGE_SIZE);
+       va = kmap(vmx_io_bitmap_b);
+       memset(va, 0xff, PAGE_SIZE);
        kunmap(vmx_io_bitmap_b);
 
+       va = kmap(vmx_msr_bitmap);
+       memset(va, 0xff, PAGE_SIZE);
+       kunmap(vmx_msr_bitmap);
+
+       set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
+
        r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), THIS_MODULE);
        if (r)
-               goto out1;
+               goto out2;
+
+       vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_FS_BASE);
+       vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_GS_BASE);
+       vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_CS);
+       vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_ESP);
+       vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_EIP);
 
        if (bypass_guest_pf)
                kvm_mmu_set_nonpresent_ptes(~0xffeull, 0ull);
 
        return 0;
 
+out2:
+       __free_page(vmx_msr_bitmap);
 out1:
        __free_page(vmx_io_bitmap_b);
 out:
@@ -2670,6 +2859,7 @@ out:
 
 static void __exit vmx_exit(void)
 {
+       __free_page(vmx_msr_bitmap);
        __free_page(vmx_io_bitmap_b);
        __free_page(vmx_io_bitmap_a);
 
index d52ae8d7303de2586351d80662fd385366331ec5..5dff4606b988591d4e0e82f6247945a829f7f977 100644 (file)
@@ -49,6 +49,7 @@
  * Definitions of Secondary Processor-Based VM-Execution Controls.
  */
 #define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
+#define SECONDARY_EXEC_ENABLE_VPID              0x00000020
 #define SECONDARY_EXEC_WBINVD_EXITING          0x00000040
 
 
@@ -65,6 +66,7 @@
 
 /* VMCS Encodings */
 enum vmcs_field {
+       VIRTUAL_PROCESSOR_ID            = 0x00000000,
        GUEST_ES_SELECTOR               = 0x00000800,
        GUEST_CS_SELECTOR               = 0x00000802,
        GUEST_SS_SELECTOR               = 0x00000804,
@@ -231,12 +233,12 @@ enum vmcs_field {
  */
 #define INTR_INFO_VECTOR_MASK           0xff            /* 7:0 */
 #define INTR_INFO_INTR_TYPE_MASK        0x700           /* 10:8 */
-#define INTR_INFO_DELIEVER_CODE_MASK    0x800           /* 11 */
+#define INTR_INFO_DELIVER_CODE_MASK     0x800           /* 11 */
 #define INTR_INFO_VALID_MASK            0x80000000      /* 31 */
 
 #define VECTORING_INFO_VECTOR_MASK             INTR_INFO_VECTOR_MASK
 #define VECTORING_INFO_TYPE_MASK               INTR_INFO_INTR_TYPE_MASK
-#define VECTORING_INFO_DELIEVER_CODE_MASK      INTR_INFO_DELIEVER_CODE_MASK
+#define VECTORING_INFO_DELIVER_CODE_MASK       INTR_INFO_DELIVER_CODE_MASK
 #define VECTORING_INFO_VALID_MASK              INTR_INFO_VALID_MASK
 
 #define INTR_TYPE_EXT_INTR              (0 << 8) /* external interrupt */
@@ -321,4 +323,8 @@ enum vmcs_field {
 
 #define APIC_ACCESS_PAGE_PRIVATE_MEMSLOT       9
 
+#define VMX_NR_VPIDS                           (1 << 16)
+#define VMX_VPID_EXTENT_SINGLE_CONTEXT         1
+#define VMX_VPID_EXTENT_ALL_CONTEXT            2
+
 #endif
index 6b01552bd1f1cb91c64af4fdf9f3124e734d4d19..0ce556372a4d1df614499224a634f4967afc8eb3 100644 (file)
  */
 
 #include <linux/kvm_host.h>
-#include "segment_descriptor.h"
 #include "irq.h"
 #include "mmu.h"
+#include "i8254.h"
+#include "tss.h"
 
+#include <linux/clocksource.h>
 #include <linux/kvm.h>
 #include <linux/fs.h>
 #include <linux/vmalloc.h>
@@ -28,6 +30,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/msr.h>
+#include <asm/desc.h>
 
 #define MAX_IO_MSRS 256
 #define CR0_RESERVED_BITS                                              \
                          | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE))
 
 #define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR)
-#define EFER_RESERVED_BITS 0xfffffffffffff2fe
+/* EFER defaults:
+ * - enable syscall per default because its emulated by KVM
+ * - enable LME and LMA per default on 64 bit KVM
+ */
+#ifdef CONFIG_X86_64
+static u64 __read_mostly efer_reserved_bits = 0xfffffffffffffafeULL;
+#else
+static u64 __read_mostly efer_reserved_bits = 0xfffffffffffffffeULL;
+#endif
 
 #define VM_STAT(x) offsetof(struct kvm, stat.x), KVM_STAT_VM
 #define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
@@ -63,6 +74,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "irq_window", VCPU_STAT(irq_window_exits) },
        { "halt_exits", VCPU_STAT(halt_exits) },
        { "halt_wakeup", VCPU_STAT(halt_wakeup) },
+       { "hypercalls", VCPU_STAT(hypercalls) },
        { "request_irq", VCPU_STAT(request_irq_exits) },
        { "irq_exits", VCPU_STAT(irq_exits) },
        { "host_state_reload", VCPU_STAT(host_state_reload) },
@@ -78,6 +90,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "mmu_recycled", VM_STAT(mmu_recycled) },
        { "mmu_cache_miss", VM_STAT(mmu_cache_miss) },
        { "remote_tlb_flush", VM_STAT(remote_tlb_flush) },
+       { "largepages", VM_STAT(lpages) },
        { NULL }
 };
 
@@ -85,7 +98,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 unsigned long segment_base(u16 selector)
 {
        struct descriptor_table gdt;
-       struct segment_descriptor *d;
+       struct desc_struct *d;
        unsigned long table_base;
        unsigned long v;
 
@@ -101,13 +114,12 @@ unsigned long segment_base(u16 selector)
                asm("sldt %0" : "=g"(ldt_selector));
                table_base = segment_base(ldt_selector);
        }
-       d = (struct segment_descriptor *)(table_base + (selector & ~7));
-       v = d->base_low | ((unsigned long)d->base_mid << 16) |
-               ((unsigned long)d->base_high << 24);
+       d = (struct desc_struct *)(table_base + (selector & ~7));
+       v = d->base0 | ((unsigned long)d->base1 << 16) |
+               ((unsigned long)d->base2 << 24);
 #ifdef CONFIG_X86_64
-       if (d->system == 0 && (d->type == 2 || d->type == 9 || d->type == 11))
-               v |= ((unsigned long) \
-                     ((struct segment_descriptor_64 *)d)->base_higher) << 32;
+       if (d->s == 0 && (d->type == 2 || d->type == 9 || d->type == 11))
+               v |= ((unsigned long)((struct ldttss_desc64 *)d)->base3) << 32;
 #endif
        return v;
 }
@@ -145,11 +157,16 @@ void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long addr,
                           u32 error_code)
 {
        ++vcpu->stat.pf_guest;
-       if (vcpu->arch.exception.pending && vcpu->arch.exception.nr == PF_VECTOR) {
-               printk(KERN_DEBUG "kvm: inject_page_fault:"
-                      " double fault 0x%lx\n", addr);
-               vcpu->arch.exception.nr = DF_VECTOR;
-               vcpu->arch.exception.error_code = 0;
+       if (vcpu->arch.exception.pending) {
+               if (vcpu->arch.exception.nr == PF_VECTOR) {
+                       printk(KERN_DEBUG "kvm: inject_page_fault:"
+                                       " double fault 0x%lx\n", addr);
+                       vcpu->arch.exception.nr = DF_VECTOR;
+                       vcpu->arch.exception.error_code = 0;
+               } else if (vcpu->arch.exception.nr == DF_VECTOR) {
+                       /* triple fault -> shutdown */
+                       set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests);
+               }
                return;
        }
        vcpu->arch.cr2 = addr;
@@ -184,7 +201,6 @@ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3)
        int ret;
        u64 pdpte[ARRAY_SIZE(vcpu->arch.pdptrs)];
 
-       down_read(&vcpu->kvm->slots_lock);
        ret = kvm_read_guest_page(vcpu->kvm, pdpt_gfn, pdpte,
                                  offset * sizeof(u64), sizeof(pdpte));
        if (ret < 0) {
@@ -201,10 +217,10 @@ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3)
 
        memcpy(vcpu->arch.pdptrs, pdpte, sizeof(vcpu->arch.pdptrs));
 out:
-       up_read(&vcpu->kvm->slots_lock);
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(load_pdptrs);
 
 static bool pdptrs_changed(struct kvm_vcpu *vcpu)
 {
@@ -215,18 +231,16 @@ static bool pdptrs_changed(struct kvm_vcpu *vcpu)
        if (is_long_mode(vcpu) || !is_pae(vcpu))
                return false;
 
-       down_read(&vcpu->kvm->slots_lock);
        r = kvm_read_guest(vcpu->kvm, vcpu->arch.cr3 & ~31u, pdpte, sizeof(pdpte));
        if (r < 0)
                goto out;
        changed = memcmp(pdpte, vcpu->arch.pdptrs, sizeof(pdpte)) != 0;
 out:
-       up_read(&vcpu->kvm->slots_lock);
 
        return changed;
 }
 
-void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 {
        if (cr0 & CR0_RESERVED_BITS) {
                printk(KERN_DEBUG "set_cr0: 0x%lx #GP, reserved bits 0x%lx\n",
@@ -284,15 +298,18 @@ void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
        kvm_mmu_reset_context(vcpu);
        return;
 }
-EXPORT_SYMBOL_GPL(set_cr0);
+EXPORT_SYMBOL_GPL(kvm_set_cr0);
 
-void lmsw(struct kvm_vcpu *vcpu, unsigned long msw)
+void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw)
 {
-       set_cr0(vcpu, (vcpu->arch.cr0 & ~0x0ful) | (msw & 0x0f));
+       kvm_set_cr0(vcpu, (vcpu->arch.cr0 & ~0x0ful) | (msw & 0x0f));
+       KVMTRACE_1D(LMSW, vcpu,
+                   (u32)((vcpu->arch.cr0 & ~0x0ful) | (msw & 0x0f)),
+                   handler);
 }
-EXPORT_SYMBOL_GPL(lmsw);
+EXPORT_SYMBOL_GPL(kvm_lmsw);
 
-void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+void kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
        if (cr4 & CR4_RESERVED_BITS) {
                printk(KERN_DEBUG "set_cr4: #GP, reserved bits\n");
@@ -323,9 +340,9 @@ void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
        vcpu->arch.cr4 = cr4;
        kvm_mmu_reset_context(vcpu);
 }
-EXPORT_SYMBOL_GPL(set_cr4);
+EXPORT_SYMBOL_GPL(kvm_set_cr4);
 
-void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
+void kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 {
        if (cr3 == vcpu->arch.cr3 && !pdptrs_changed(vcpu)) {
                kvm_mmu_flush_tlb(vcpu);
@@ -359,7 +376,6 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
                 */
        }
 
-       down_read(&vcpu->kvm->slots_lock);
        /*
         * Does the new cr3 value map to physical memory? (Note, we
         * catch an invalid cr3 even in real-mode, because it would
@@ -375,11 +391,10 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
                vcpu->arch.cr3 = cr3;
                vcpu->arch.mmu.new_cr3(vcpu);
        }
-       up_read(&vcpu->kvm->slots_lock);
 }
-EXPORT_SYMBOL_GPL(set_cr3);
+EXPORT_SYMBOL_GPL(kvm_set_cr3);
 
-void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
+void kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
 {
        if (cr8 & CR8_RESERVED_BITS) {
                printk(KERN_DEBUG "set_cr8: #GP, reserved bits 0x%lx\n", cr8);
@@ -391,16 +406,16 @@ void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
        else
                vcpu->arch.cr8 = cr8;
 }
-EXPORT_SYMBOL_GPL(set_cr8);
+EXPORT_SYMBOL_GPL(kvm_set_cr8);
 
-unsigned long get_cr8(struct kvm_vcpu *vcpu)
+unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu)
 {
        if (irqchip_in_kernel(vcpu->kvm))
                return kvm_lapic_get_cr8(vcpu);
        else
                return vcpu->arch.cr8;
 }
-EXPORT_SYMBOL_GPL(get_cr8);
+EXPORT_SYMBOL_GPL(kvm_get_cr8);
 
 /*
  * List of msr numbers which we expose to userspace through KVM_GET_MSRS
@@ -415,7 +430,8 @@ static u32 msrs_to_save[] = {
 #ifdef CONFIG_X86_64
        MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR,
 #endif
-       MSR_IA32_TIME_STAMP_COUNTER,
+       MSR_IA32_TIME_STAMP_COUNTER, MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK,
+       MSR_IA32_PERF_STATUS,
 };
 
 static unsigned num_msrs_to_save;
@@ -424,11 +440,9 @@ static u32 emulated_msrs[] = {
        MSR_IA32_MISC_ENABLE,
 };
 
-#ifdef CONFIG_X86_64
-
 static void set_efer(struct kvm_vcpu *vcpu, u64 efer)
 {
-       if (efer & EFER_RESERVED_BITS) {
+       if (efer & efer_reserved_bits) {
                printk(KERN_DEBUG "set_efer: 0x%llx #GP, reserved bits\n",
                       efer);
                kvm_inject_gp(vcpu, 0);
@@ -450,7 +464,12 @@ static void set_efer(struct kvm_vcpu *vcpu, u64 efer)
        vcpu->arch.shadow_efer = efer;
 }
 
-#endif
+void kvm_enable_efer_bits(u64 mask)
+{
+       efer_reserved_bits &= ~mask;
+}
+EXPORT_SYMBOL_GPL(kvm_enable_efer_bits);
+
 
 /*
  * Writes msr value into into the appropriate "register".
@@ -470,26 +489,86 @@ static int do_set_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
        return kvm_set_msr(vcpu, index, *data);
 }
 
+static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock)
+{
+       static int version;
+       struct kvm_wall_clock wc;
+       struct timespec wc_ts;
+
+       if (!wall_clock)
+               return;
+
+       version++;
+
+       kvm_write_guest(kvm, wall_clock, &version, sizeof(version));
+
+       wc_ts = current_kernel_time();
+       wc.wc_sec = wc_ts.tv_sec;
+       wc.wc_nsec = wc_ts.tv_nsec;
+       wc.wc_version = version;
+
+       kvm_write_guest(kvm, wall_clock, &wc, sizeof(wc));
+
+       version++;
+       kvm_write_guest(kvm, wall_clock, &version, sizeof(version));
+}
+
+static void kvm_write_guest_time(struct kvm_vcpu *v)
+{
+       struct timespec ts;
+       unsigned long flags;
+       struct kvm_vcpu_arch *vcpu = &v->arch;
+       void *shared_kaddr;
+
+       if ((!vcpu->time_page))
+               return;
+
+       /* Keep irq disabled to prevent changes to the clock */
+       local_irq_save(flags);
+       kvm_get_msr(v, MSR_IA32_TIME_STAMP_COUNTER,
+                         &vcpu->hv_clock.tsc_timestamp);
+       ktime_get_ts(&ts);
+       local_irq_restore(flags);
+
+       /* With all the info we got, fill in the values */
+
+       vcpu->hv_clock.system_time = ts.tv_nsec +
+                                    (NSEC_PER_SEC * (u64)ts.tv_sec);
+       /*
+        * The interface expects us to write an even number signaling that the
+        * update is finished. Since the guest won't see the intermediate
+        * state, we just write "2" at the end
+        */
+       vcpu->hv_clock.version = 2;
+
+       shared_kaddr = kmap_atomic(vcpu->time_page, KM_USER0);
+
+       memcpy(shared_kaddr + vcpu->time_offset, &vcpu->hv_clock,
+               sizeof(vcpu->hv_clock));
+
+       kunmap_atomic(shared_kaddr, KM_USER0);
+
+       mark_page_dirty(v->kvm, vcpu->time >> PAGE_SHIFT);
+}
+
 
 int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 {
        switch (msr) {
-#ifdef CONFIG_X86_64
        case MSR_EFER:
                set_efer(vcpu, data);
                break;
-#endif
        case MSR_IA32_MC0_STATUS:
                pr_unimpl(vcpu, "%s: MSR_IA32_MC0_STATUS 0x%llx, nop\n",
-                      __FUNCTION__, data);
+                      __func__, data);
                break;
        case MSR_IA32_MCG_STATUS:
                pr_unimpl(vcpu, "%s: MSR_IA32_MCG_STATUS 0x%llx, nop\n",
-                       __FUNCTION__, data);
+                       __func__, data);
                break;
        case MSR_IA32_MCG_CTL:
                pr_unimpl(vcpu, "%s: MSR_IA32_MCG_CTL 0x%llx, nop\n",
-                       __FUNCTION__, data);
+                       __func__, data);
                break;
        case MSR_IA32_UCODE_REV:
        case MSR_IA32_UCODE_WRITE:
@@ -501,6 +580,42 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
        case MSR_IA32_MISC_ENABLE:
                vcpu->arch.ia32_misc_enable_msr = data;
                break;
+       case MSR_KVM_WALL_CLOCK:
+               vcpu->kvm->arch.wall_clock = data;
+               kvm_write_wall_clock(vcpu->kvm, data);
+               break;
+       case MSR_KVM_SYSTEM_TIME: {
+               if (vcpu->arch.time_page) {
+                       kvm_release_page_dirty(vcpu->arch.time_page);
+                       vcpu->arch.time_page = NULL;
+               }
+
+               vcpu->arch.time = data;
+
+               /* we verify if the enable bit is set... */
+               if (!(data & 1))
+                       break;
+
+               /* ...but clean it before doing the actual write */
+               vcpu->arch.time_offset = data & ~(PAGE_MASK | 1);
+
+               vcpu->arch.hv_clock.tsc_to_system_mul =
+                                       clocksource_khz2mult(tsc_khz, 22);
+               vcpu->arch.hv_clock.tsc_shift = 22;
+
+               down_read(&current->mm->mmap_sem);
+               vcpu->arch.time_page =
+                               gfn_to_page(vcpu->kvm, data >> PAGE_SHIFT);
+               up_read(&current->mm->mmap_sem);
+
+               if (is_error_page(vcpu->arch.time_page)) {
+                       kvm_release_page_clean(vcpu->arch.time_page);
+                       vcpu->arch.time_page = NULL;
+               }
+
+               kvm_write_guest_time(vcpu);
+               break;
+       }
        default:
                pr_unimpl(vcpu, "unhandled wrmsr: 0x%x data %llx\n", msr, data);
                return 1;
@@ -540,7 +655,6 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
        case MSR_IA32_MC0_MISC+12:
        case MSR_IA32_MC0_MISC+16:
        case MSR_IA32_UCODE_REV:
-       case MSR_IA32_PERF_STATUS:
        case MSR_IA32_EBL_CR_POWERON:
                /* MTRR registers */
        case 0xfe:
@@ -556,11 +670,21 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
        case MSR_IA32_MISC_ENABLE:
                data = vcpu->arch.ia32_misc_enable_msr;
                break;
-#ifdef CONFIG_X86_64
+       case MSR_IA32_PERF_STATUS:
+               /* TSC increment by tick */
+               data = 1000ULL;
+               /* CPU multiplier */
+               data |= (((uint64_t)4ULL) << 40);
+               break;
        case MSR_EFER:
                data = vcpu->arch.shadow_efer;
                break;
-#endif
+       case MSR_KVM_WALL_CLOCK:
+               data = vcpu->kvm->arch.wall_clock;
+               break;
+       case MSR_KVM_SYSTEM_TIME:
+               data = vcpu->arch.time;
+               break;
        default:
                pr_unimpl(vcpu, "unhandled rdmsr: 0x%x\n", msr);
                return 1;
@@ -584,9 +708,11 @@ static int __msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs *msrs,
 
        vcpu_load(vcpu);
 
+       down_read(&vcpu->kvm->slots_lock);
        for (i = 0; i < msrs->nmsrs; ++i)
                if (do_msr(vcpu, entries[i].index, &entries[i].data))
                        break;
+       up_read(&vcpu->kvm->slots_lock);
 
        vcpu_put(vcpu);
 
@@ -688,11 +814,24 @@ int kvm_dev_ioctl_check_extension(long ext)
        case KVM_CAP_USER_MEMORY:
        case KVM_CAP_SET_TSS_ADDR:
        case KVM_CAP_EXT_CPUID:
+       case KVM_CAP_CLOCKSOURCE:
+       case KVM_CAP_PIT:
+       case KVM_CAP_NOP_IO_DELAY:
+       case KVM_CAP_MP_STATE:
                r = 1;
                break;
        case KVM_CAP_VAPIC:
                r = !kvm_x86_ops->cpu_has_accelerated_tpr();
                break;
+       case KVM_CAP_NR_VCPUS:
+               r = KVM_MAX_VCPUS;
+               break;
+       case KVM_CAP_NR_MEMSLOTS:
+               r = KVM_MEMORY_SLOTS;
+               break;
+       case KVM_CAP_PV_MMU:
+               r = !tdp_enabled;
+               break;
        default:
                r = 0;
                break;
@@ -763,6 +902,7 @@ out:
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
        kvm_x86_ops->vcpu_load(vcpu, cpu);
+       kvm_write_guest_time(vcpu);
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -958,32 +1098,32 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
        }
        /* function 4 and 0xb have additional index. */
        case 4: {
-               int index, cache_type;
+               int i, cache_type;
 
                entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
                /* read more entries until cache_type is zero */
-               for (index = 1; *nent < maxnent; ++index) {
-                       cache_type = entry[index - 1].eax & 0x1f;
+               for (i = 1; *nent < maxnent; ++i) {
+                       cache_type = entry[i - 1].eax & 0x1f;
                        if (!cache_type)
                                break;
-                       do_cpuid_1_ent(&entry[index], function, index);
-                       entry[index].flags |=
+                       do_cpuid_1_ent(&entry[i], function, i);
+                       entry[i].flags |=
                               KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
                        ++*nent;
                }
                break;
        }
        case 0xb: {
-               int index, level_type;
+               int i, level_type;
 
                entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
                /* read more entries until level_type is zero */
-               for (index = 1; *nent < maxnent; ++index) {
-                       level_type = entry[index - 1].ecx & 0xff;
+               for (i = 1; *nent < maxnent; ++i) {
+                       level_type = entry[i - 1].ecx & 0xff;
                        if (!level_type)
                                break;
-                       do_cpuid_1_ent(&entry[index], function, index);
-                       entry[index].flags |=
+                       do_cpuid_1_ent(&entry[i], function, i);
+                       entry[i].flags |=
                               KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
                        ++*nent;
                }
@@ -1365,6 +1505,23 @@ static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, struct kvm_irqchip *chip)
        return r;
 }
 
+static int kvm_vm_ioctl_get_pit(struct kvm *kvm, struct kvm_pit_state *ps)
+{
+       int r = 0;
+
+       memcpy(ps, &kvm->arch.vpit->pit_state, sizeof(struct kvm_pit_state));
+       return r;
+}
+
+static int kvm_vm_ioctl_set_pit(struct kvm *kvm, struct kvm_pit_state *ps)
+{
+       int r = 0;
+
+       memcpy(&kvm->arch.vpit->pit_state, ps, sizeof(struct kvm_pit_state));
+       kvm_pit_load_count(kvm, 0, ps->channels[0].count);
+       return r;
+}
+
 /*
  * Get (and clear) the dirty memory log for a memory slot.
  */
@@ -1457,6 +1614,12 @@ long kvm_arch_vm_ioctl(struct file *filp,
                } else
                        goto out;
                break;
+       case KVM_CREATE_PIT:
+               r = -ENOMEM;
+               kvm->arch.vpit = kvm_create_pit(kvm);
+               if (kvm->arch.vpit)
+                       r = 0;
+               break;
        case KVM_IRQ_LINE: {
                struct kvm_irq_level irq_event;
 
@@ -1512,6 +1675,37 @@ long kvm_arch_vm_ioctl(struct file *filp,
                r = 0;
                break;
        }
+       case KVM_GET_PIT: {
+               struct kvm_pit_state ps;
+               r = -EFAULT;
+               if (copy_from_user(&ps, argp, sizeof ps))
+                       goto out;
+               r = -ENXIO;
+               if (!kvm->arch.vpit)
+                       goto out;
+               r = kvm_vm_ioctl_get_pit(kvm, &ps);
+               if (r)
+                       goto out;
+               r = -EFAULT;
+               if (copy_to_user(argp, &ps, sizeof ps))
+                       goto out;
+               r = 0;
+               break;
+       }
+       case KVM_SET_PIT: {
+               struct kvm_pit_state ps;
+               r = -EFAULT;
+               if (copy_from_user(&ps, argp, sizeof ps))
+                       goto out;
+               r = -ENXIO;
+               if (!kvm->arch.vpit)
+                       goto out;
+               r = kvm_vm_ioctl_set_pit(kvm, &ps);
+               if (r)
+                       goto out;
+               r = 0;
+               break;
+       }
        default:
                ;
        }
@@ -1570,7 +1764,6 @@ int emulator_read_std(unsigned long addr,
        void *data = val;
        int r = X86EMUL_CONTINUE;
 
-       down_read(&vcpu->kvm->slots_lock);
        while (bytes) {
                gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
                unsigned offset = addr & (PAGE_SIZE-1);
@@ -1592,7 +1785,6 @@ int emulator_read_std(unsigned long addr,
                addr += tocopy;
        }
 out:
-       up_read(&vcpu->kvm->slots_lock);
        return r;
 }
 EXPORT_SYMBOL_GPL(emulator_read_std);
@@ -1611,9 +1803,7 @@ static int emulator_read_emulated(unsigned long addr,
                return X86EMUL_CONTINUE;
        }
 
-       down_read(&vcpu->kvm->slots_lock);
        gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
-       up_read(&vcpu->kvm->slots_lock);
 
        /* For APIC access vmexit */
        if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
@@ -1646,19 +1836,15 @@ mmio:
        return X86EMUL_UNHANDLEABLE;
 }
 
-static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
-                              const void *val, int bytes)
+int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
+                         const void *val, int bytes)
 {
        int ret;
 
-       down_read(&vcpu->kvm->slots_lock);
        ret = kvm_write_guest(vcpu->kvm, gpa, val, bytes);
-       if (ret < 0) {
-               up_read(&vcpu->kvm->slots_lock);
+       if (ret < 0)
                return 0;
-       }
        kvm_mmu_pte_write(vcpu, gpa, val, bytes);
-       up_read(&vcpu->kvm->slots_lock);
        return 1;
 }
 
@@ -1670,9 +1856,7 @@ static int emulator_write_emulated_onepage(unsigned long addr,
        struct kvm_io_device *mmio_dev;
        gpa_t                 gpa;
 
-       down_read(&vcpu->kvm->slots_lock);
        gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
-       up_read(&vcpu->kvm->slots_lock);
 
        if (gpa == UNMAPPED_GVA) {
                kvm_inject_page_fault(vcpu, addr, 2);
@@ -1749,7 +1933,6 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
                char *kaddr;
                u64 val;
 
-               down_read(&vcpu->kvm->slots_lock);
                gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
 
                if (gpa == UNMAPPED_GVA ||
@@ -1769,9 +1952,8 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
                set_64bit((u64 *)(kaddr + offset_in_page(gpa)), val);
                kunmap_atomic(kaddr, KM_USER0);
                kvm_release_page_dirty(page);
-       emul_write:
-               up_read(&vcpu->kvm->slots_lock);
        }
+emul_write:
 #endif
 
        return emulator_write_emulated(addr, new, bytes, vcpu);
@@ -1802,7 +1984,7 @@ int emulator_get_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long *dest)
                *dest = kvm_x86_ops->get_dr(vcpu, dr);
                return X86EMUL_CONTINUE;
        default:
-               pr_unimpl(vcpu, "%s: unexpected dr %u\n", __FUNCTION__, dr);
+               pr_unimpl(vcpu, "%s: unexpected dr %u\n", __func__, dr);
                return X86EMUL_UNHANDLEABLE;
        }
 }
@@ -1840,7 +2022,7 @@ void kvm_report_emulation_failure(struct kvm_vcpu *vcpu, const char *context)
 }
 EXPORT_SYMBOL_GPL(kvm_report_emulation_failure);
 
-struct x86_emulate_ops emulate_ops = {
+static struct x86_emulate_ops emulate_ops = {
        .read_std            = emulator_read_std,
        .read_emulated       = emulator_read_emulated,
        .write_emulated      = emulator_write_emulated,
@@ -2091,6 +2273,13 @@ int kvm_emulate_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
        vcpu->arch.pio.guest_page_offset = 0;
        vcpu->arch.pio.rep = 0;
 
+       if (vcpu->run->io.direction == KVM_EXIT_IO_IN)
+               KVMTRACE_2D(IO_READ, vcpu, vcpu->run->io.port, (u32)size,
+                           handler);
+       else
+               KVMTRACE_2D(IO_WRITE, vcpu, vcpu->run->io.port, (u32)size,
+                           handler);
+
        kvm_x86_ops->cache_regs(vcpu);
        memcpy(vcpu->arch.pio_data, &vcpu->arch.regs[VCPU_REGS_RAX], 4);
        kvm_x86_ops->decache_regs(vcpu);
@@ -2129,6 +2318,13 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
        vcpu->arch.pio.guest_page_offset = offset_in_page(address);
        vcpu->arch.pio.rep = rep;
 
+       if (vcpu->run->io.direction == KVM_EXIT_IO_IN)
+               KVMTRACE_2D(IO_READ, vcpu, vcpu->run->io.port, (u32)size,
+                           handler);
+       else
+               KVMTRACE_2D(IO_WRITE, vcpu, vcpu->run->io.port, (u32)size,
+                           handler);
+
        if (!count) {
                kvm_x86_ops->skip_emulated_instruction(vcpu);
                return 1;
@@ -2163,10 +2359,8 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
                kvm_x86_ops->skip_emulated_instruction(vcpu);
 
        for (i = 0; i < nr_pages; ++i) {
-               down_read(&vcpu->kvm->slots_lock);
                page = gva_to_page(vcpu, address + i * PAGE_SIZE);
                vcpu->arch.pio.guest_pages[i] = page;
-               up_read(&vcpu->kvm->slots_lock);
                if (!page) {
                        kvm_inject_gp(vcpu, 0);
                        free_pio_guest_pages(vcpu);
@@ -2238,10 +2432,13 @@ void kvm_arch_exit(void)
 int kvm_emulate_halt(struct kvm_vcpu *vcpu)
 {
        ++vcpu->stat.halt_exits;
+       KVMTRACE_0D(HLT, vcpu, handler);
        if (irqchip_in_kernel(vcpu->kvm)) {
-               vcpu->arch.mp_state = VCPU_MP_STATE_HALTED;
+               vcpu->arch.mp_state = KVM_MP_STATE_HALTED;
+               up_read(&vcpu->kvm->slots_lock);
                kvm_vcpu_block(vcpu);
-               if (vcpu->arch.mp_state != VCPU_MP_STATE_RUNNABLE)
+               down_read(&vcpu->kvm->slots_lock);
+               if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
                        return -EINTR;
                return 1;
        } else {
@@ -2251,9 +2448,19 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu)
 }
 EXPORT_SYMBOL_GPL(kvm_emulate_halt);
 
+static inline gpa_t hc_gpa(struct kvm_vcpu *vcpu, unsigned long a0,
+                          unsigned long a1)
+{
+       if (is_long_mode(vcpu))
+               return a0;
+       else
+               return a0 | ((gpa_t)a1 << 32);
+}
+
 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
 {
        unsigned long nr, a0, a1, a2, a3, ret;
+       int r = 1;
 
        kvm_x86_ops->cache_regs(vcpu);
 
@@ -2263,6 +2470,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
        a2 = vcpu->arch.regs[VCPU_REGS_RDX];
        a3 = vcpu->arch.regs[VCPU_REGS_RSI];
 
+       KVMTRACE_1D(VMMCALL, vcpu, (u32)nr, handler);
+
        if (!is_long_mode(vcpu)) {
                nr &= 0xFFFFFFFF;
                a0 &= 0xFFFFFFFF;
@@ -2275,13 +2484,17 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
        case KVM_HC_VAPIC_POLL_IRQ:
                ret = 0;
                break;
+       case KVM_HC_MMU_OP:
+               r = kvm_pv_mmu_op(vcpu, a0, hc_gpa(vcpu, a1, a2), &ret);
+               break;
        default:
                ret = -KVM_ENOSYS;
                break;
        }
        vcpu->arch.regs[VCPU_REGS_RAX] = ret;
        kvm_x86_ops->decache_regs(vcpu);
-       return 0;
+       ++vcpu->stat.hypercalls;
+       return r;
 }
 EXPORT_SYMBOL_GPL(kvm_emulate_hypercall);
 
@@ -2329,7 +2542,7 @@ void realmode_lidt(struct kvm_vcpu *vcpu, u16 limit, unsigned long base)
 void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw,
                   unsigned long *rflags)
 {
-       lmsw(vcpu, msw);
+       kvm_lmsw(vcpu, msw);
        *rflags = kvm_x86_ops->get_rflags(vcpu);
 }
 
@@ -2346,9 +2559,9 @@ unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr)
        case 4:
                return vcpu->arch.cr4;
        case 8:
-               return get_cr8(vcpu);
+               return kvm_get_cr8(vcpu);
        default:
-               vcpu_printf(vcpu, "%s: unexpected cr %u\n", __FUNCTION__, cr);
+               vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr);
                return 0;
        }
 }
@@ -2358,23 +2571,23 @@ void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long val,
 {
        switch (cr) {
        case 0:
-               set_cr0(vcpu, mk_cr_64(vcpu->arch.cr0, val));
+               kvm_set_cr0(vcpu, mk_cr_64(vcpu->arch.cr0, val));
                *rflags = kvm_x86_ops->get_rflags(vcpu);
                break;
        case 2:
                vcpu->arch.cr2 = val;
                break;
        case 3:
-               set_cr3(vcpu, val);
+               kvm_set_cr3(vcpu, val);
                break;
        case 4:
-               set_cr4(vcpu, mk_cr_64(vcpu->arch.cr4, val));
+               kvm_set_cr4(vcpu, mk_cr_64(vcpu->arch.cr4, val));
                break;
        case 8:
-               set_cr8(vcpu, val & 0xfUL);
+               kvm_set_cr8(vcpu, val & 0xfUL);
                break;
        default:
-               vcpu_printf(vcpu, "%s: unexpected cr %u\n", __FUNCTION__, cr);
+               vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr);
        }
 }
 
@@ -2447,6 +2660,11 @@ void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
        }
        kvm_x86_ops->decache_regs(vcpu);
        kvm_x86_ops->skip_emulated_instruction(vcpu);
+       KVMTRACE_5D(CPUID, vcpu, function,
+                   (u32)vcpu->arch.regs[VCPU_REGS_RAX],
+                   (u32)vcpu->arch.regs[VCPU_REGS_RBX],
+                   (u32)vcpu->arch.regs[VCPU_REGS_RCX],
+                   (u32)vcpu->arch.regs[VCPU_REGS_RDX], handler);
 }
 EXPORT_SYMBOL_GPL(kvm_emulate_cpuid);
 
@@ -2469,7 +2687,7 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu,
                              struct kvm_run *kvm_run)
 {
        kvm_run->if_flag = (kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_IF) != 0;
-       kvm_run->cr8 = get_cr8(vcpu);
+       kvm_run->cr8 = kvm_get_cr8(vcpu);
        kvm_run->apic_base = kvm_get_apic_base(vcpu);
        if (irqchip_in_kernel(vcpu->kvm))
                kvm_run->ready_for_interrupt_injection = 1;
@@ -2509,16 +2727,17 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        int r;
 
-       if (unlikely(vcpu->arch.mp_state == VCPU_MP_STATE_SIPI_RECEIVED)) {
+       if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED)) {
                pr_debug("vcpu %d received sipi with vector # %x\n",
                       vcpu->vcpu_id, vcpu->arch.sipi_vector);
                kvm_lapic_reset(vcpu);
                r = kvm_x86_ops->vcpu_reset(vcpu);
                if (r)
                        return r;
-               vcpu->arch.mp_state = VCPU_MP_STATE_RUNNABLE;
+               vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
        }
 
+       down_read(&vcpu->kvm->slots_lock);
        vapic_enter(vcpu);
 
 preempted:
@@ -2526,6 +2745,10 @@ preempted:
                kvm_x86_ops->guest_debug_pre(vcpu);
 
 again:
+       if (vcpu->requests)
+               if (test_and_clear_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
+                       kvm_mmu_unload(vcpu);
+
        r = kvm_mmu_reload(vcpu);
        if (unlikely(r))
                goto out;
@@ -2539,6 +2762,11 @@ again:
                        r = 0;
                        goto out;
                }
+               if (test_and_clear_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests)) {
+                       kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
+                       r = 0;
+                       goto out;
+               }
        }
 
        kvm_inject_pending_timer_irqs(vcpu);
@@ -2557,6 +2785,14 @@ again:
                goto out;
        }
 
+       if (vcpu->requests)
+               if (test_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests)) {
+                       local_irq_enable();
+                       preempt_enable();
+                       r = 1;
+                       goto out;
+               }
+
        if (signal_pending(current)) {
                local_irq_enable();
                preempt_enable();
@@ -2566,6 +2802,13 @@ again:
                goto out;
        }
 
+       vcpu->guest_mode = 1;
+       /*
+        * Make sure that guest_mode assignment won't happen after
+        * testing the pending IRQ vector bitmap.
+        */
+       smp_wmb();
+
        if (vcpu->arch.exception.pending)
                __queue_exception(vcpu);
        else if (irqchip_in_kernel(vcpu->kvm))
@@ -2575,13 +2818,15 @@ again:
 
        kvm_lapic_sync_to_vapic(vcpu);
 
-       vcpu->guest_mode = 1;
+       up_read(&vcpu->kvm->slots_lock);
+
        kvm_guest_enter();
 
        if (vcpu->requests)
                if (test_and_clear_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests))
                        kvm_x86_ops->tlb_flush(vcpu);
 
+       KVMTRACE_0D(VMENTRY, vcpu, entryexit);
        kvm_x86_ops->run(vcpu, kvm_run);
 
        vcpu->guest_mode = 0;
@@ -2601,6 +2846,8 @@ again:
 
        preempt_enable();
 
+       down_read(&vcpu->kvm->slots_lock);
+
        /*
         * Profile KVM exit RIPs:
         */
@@ -2628,14 +2875,18 @@ again:
        }
 
 out:
+       up_read(&vcpu->kvm->slots_lock);
        if (r > 0) {
                kvm_resched(vcpu);
+               down_read(&vcpu->kvm->slots_lock);
                goto preempted;
        }
 
        post_kvm_run_save(vcpu, kvm_run);
 
+       down_read(&vcpu->kvm->slots_lock);
        vapic_exit(vcpu);
+       up_read(&vcpu->kvm->slots_lock);
 
        return r;
 }
@@ -2647,7 +2898,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
        vcpu_load(vcpu);
 
-       if (unlikely(vcpu->arch.mp_state == VCPU_MP_STATE_UNINITIALIZED)) {
+       if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)) {
                kvm_vcpu_block(vcpu);
                vcpu_put(vcpu);
                return -EAGAIN;
@@ -2658,7 +2909,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
        /* re-sync apic's tpr */
        if (!irqchip_in_kernel(vcpu->kvm))
-               set_cr8(vcpu, kvm_run->cr8);
+               kvm_set_cr8(vcpu, kvm_run->cr8);
 
        if (vcpu->arch.pio.cur_count) {
                r = complete_pio(vcpu);
@@ -2670,9 +2921,12 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8);
                vcpu->mmio_read_completed = 1;
                vcpu->mmio_needed = 0;
+
+               down_read(&vcpu->kvm->slots_lock);
                r = emulate_instruction(vcpu, kvm_run,
                                        vcpu->arch.mmio_fault_cr2, 0,
                                        EMULTYPE_NO_DECODE);
+               up_read(&vcpu->kvm->slots_lock);
                if (r == EMULATE_DO_MMIO) {
                        /*
                         * Read-modify-write.  Back to userspace.
@@ -2773,7 +3027,7 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 static void get_segment(struct kvm_vcpu *vcpu,
                        struct kvm_segment *var, int seg)
 {
-       return kvm_x86_ops->get_segment(vcpu, var, seg);
+       kvm_x86_ops->get_segment(vcpu, var, seg);
 }
 
 void kvm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l)
@@ -2816,7 +3070,7 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
        sregs->cr2 = vcpu->arch.cr2;
        sregs->cr3 = vcpu->arch.cr3;
        sregs->cr4 = vcpu->arch.cr4;
-       sregs->cr8 = get_cr8(vcpu);
+       sregs->cr8 = kvm_get_cr8(vcpu);
        sregs->efer = vcpu->arch.shadow_efer;
        sregs->apic_base = kvm_get_apic_base(vcpu);
 
@@ -2836,12 +3090,438 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
        return 0;
 }
 
+int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
+                                   struct kvm_mp_state *mp_state)
+{
+       vcpu_load(vcpu);
+       mp_state->mp_state = vcpu->arch.mp_state;
+       vcpu_put(vcpu);
+       return 0;
+}
+
+int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
+                                   struct kvm_mp_state *mp_state)
+{
+       vcpu_load(vcpu);
+       vcpu->arch.mp_state = mp_state->mp_state;
+       vcpu_put(vcpu);
+       return 0;
+}
+
 static void set_segment(struct kvm_vcpu *vcpu,
                        struct kvm_segment *var, int seg)
 {
-       return kvm_x86_ops->set_segment(vcpu, var, seg);
+       kvm_x86_ops->set_segment(vcpu, var, seg);
+}
+
+static void seg_desct_to_kvm_desct(struct desc_struct *seg_desc, u16 selector,
+                                  struct kvm_segment *kvm_desct)
+{
+       kvm_desct->base = seg_desc->base0;
+       kvm_desct->base |= seg_desc->base1 << 16;
+       kvm_desct->base |= seg_desc->base2 << 24;
+       kvm_desct->limit = seg_desc->limit0;
+       kvm_desct->limit |= seg_desc->limit << 16;
+       kvm_desct->selector = selector;
+       kvm_desct->type = seg_desc->type;
+       kvm_desct->present = seg_desc->p;
+       kvm_desct->dpl = seg_desc->dpl;
+       kvm_desct->db = seg_desc->d;
+       kvm_desct->s = seg_desc->s;
+       kvm_desct->l = seg_desc->l;
+       kvm_desct->g = seg_desc->g;
+       kvm_desct->avl = seg_desc->avl;
+       if (!selector)
+               kvm_desct->unusable = 1;
+       else
+               kvm_desct->unusable = 0;
+       kvm_desct->padding = 0;
+}
+
+static void get_segment_descritptor_dtable(struct kvm_vcpu *vcpu,
+                                          u16 selector,
+                                          struct descriptor_table *dtable)
+{
+       if (selector & 1 << 2) {
+               struct kvm_segment kvm_seg;
+
+               get_segment(vcpu, &kvm_seg, VCPU_SREG_LDTR);
+
+               if (kvm_seg.unusable)
+                       dtable->limit = 0;
+               else
+                       dtable->limit = kvm_seg.limit;
+               dtable->base = kvm_seg.base;
+       }
+       else
+               kvm_x86_ops->get_gdt(vcpu, dtable);
+}
+
+/* allowed just for 8 bytes segments */
+static int load_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
+                                        struct desc_struct *seg_desc)
+{
+       struct descriptor_table dtable;
+       u16 index = selector >> 3;
+
+       get_segment_descritptor_dtable(vcpu, selector, &dtable);
+
+       if (dtable.limit < index * 8 + 7) {
+               kvm_queue_exception_e(vcpu, GP_VECTOR, selector & 0xfffc);
+               return 1;
+       }
+       return kvm_read_guest(vcpu->kvm, dtable.base + index * 8, seg_desc, 8);
+}
+
+/* allowed just for 8 bytes segments */
+static int save_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
+                                        struct desc_struct *seg_desc)
+{
+       struct descriptor_table dtable;
+       u16 index = selector >> 3;
+
+       get_segment_descritptor_dtable(vcpu, selector, &dtable);
+
+       if (dtable.limit < index * 8 + 7)
+               return 1;
+       return kvm_write_guest(vcpu->kvm, dtable.base + index * 8, seg_desc, 8);
+}
+
+static u32 get_tss_base_addr(struct kvm_vcpu *vcpu,
+                            struct desc_struct *seg_desc)
+{
+       u32 base_addr;
+
+       base_addr = seg_desc->base0;
+       base_addr |= (seg_desc->base1 << 16);
+       base_addr |= (seg_desc->base2 << 24);
+
+       return base_addr;
+}
+
+static int load_tss_segment32(struct kvm_vcpu *vcpu,
+                             struct desc_struct *seg_desc,
+                             struct tss_segment_32 *tss)
+{
+       u32 base_addr;
+
+       base_addr = get_tss_base_addr(vcpu, seg_desc);
+
+       return kvm_read_guest(vcpu->kvm, base_addr, tss,
+                             sizeof(struct tss_segment_32));
+}
+
+static int save_tss_segment32(struct kvm_vcpu *vcpu,
+                             struct desc_struct *seg_desc,
+                             struct tss_segment_32 *tss)
+{
+       u32 base_addr;
+
+       base_addr = get_tss_base_addr(vcpu, seg_desc);
+
+       return kvm_write_guest(vcpu->kvm, base_addr, tss,
+                              sizeof(struct tss_segment_32));
+}
+
+static int load_tss_segment16(struct kvm_vcpu *vcpu,
+                             struct desc_struct *seg_desc,
+                             struct tss_segment_16 *tss)
+{
+       u32 base_addr;
+
+       base_addr = get_tss_base_addr(vcpu, seg_desc);
+
+       return kvm_read_guest(vcpu->kvm, base_addr, tss,
+                             sizeof(struct tss_segment_16));
+}
+
+static int save_tss_segment16(struct kvm_vcpu *vcpu,
+                             struct desc_struct *seg_desc,
+                             struct tss_segment_16 *tss)
+{
+       u32 base_addr;
+
+       base_addr = get_tss_base_addr(vcpu, seg_desc);
+
+       return kvm_write_guest(vcpu->kvm, base_addr, tss,
+                              sizeof(struct tss_segment_16));
+}
+
+static u16 get_segment_selector(struct kvm_vcpu *vcpu, int seg)
+{
+       struct kvm_segment kvm_seg;
+
+       get_segment(vcpu, &kvm_seg, seg);
+       return kvm_seg.selector;
+}
+
+static int load_segment_descriptor_to_kvm_desct(struct kvm_vcpu *vcpu,
+                                               u16 selector,
+                                               struct kvm_segment *kvm_seg)
+{
+       struct desc_struct seg_desc;
+
+       if (load_guest_segment_descriptor(vcpu, selector, &seg_desc))
+               return 1;
+       seg_desct_to_kvm_desct(&seg_desc, selector, kvm_seg);
+       return 0;
+}
+
+static int load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
+                                  int type_bits, int seg)
+{
+       struct kvm_segment kvm_seg;
+
+       if (load_segment_descriptor_to_kvm_desct(vcpu, selector, &kvm_seg))
+               return 1;
+       kvm_seg.type |= type_bits;
+
+       if (seg != VCPU_SREG_SS && seg != VCPU_SREG_CS &&
+           seg != VCPU_SREG_LDTR)
+               if (!kvm_seg.s)
+                       kvm_seg.unusable = 1;
+
+       set_segment(vcpu, &kvm_seg, seg);
+       return 0;
+}
+
+static void save_state_to_tss32(struct kvm_vcpu *vcpu,
+                               struct tss_segment_32 *tss)
+{
+       tss->cr3 = vcpu->arch.cr3;
+       tss->eip = vcpu->arch.rip;
+       tss->eflags = kvm_x86_ops->get_rflags(vcpu);
+       tss->eax = vcpu->arch.regs[VCPU_REGS_RAX];
+       tss->ecx = vcpu->arch.regs[VCPU_REGS_RCX];
+       tss->edx = vcpu->arch.regs[VCPU_REGS_RDX];
+       tss->ebx = vcpu->arch.regs[VCPU_REGS_RBX];
+       tss->esp = vcpu->arch.regs[VCPU_REGS_RSP];
+       tss->ebp = vcpu->arch.regs[VCPU_REGS_RBP];
+       tss->esi = vcpu->arch.regs[VCPU_REGS_RSI];
+       tss->edi = vcpu->arch.regs[VCPU_REGS_RDI];
+
+       tss->es = get_segment_selector(vcpu, VCPU_SREG_ES);
+       tss->cs = get_segment_selector(vcpu, VCPU_SREG_CS);
+       tss->ss = get_segment_selector(vcpu, VCPU_SREG_SS);
+       tss->ds = get_segment_selector(vcpu, VCPU_SREG_DS);
+       tss->fs = get_segment_selector(vcpu, VCPU_SREG_FS);
+       tss->gs = get_segment_selector(vcpu, VCPU_SREG_GS);
+       tss->ldt_selector = get_segment_selector(vcpu, VCPU_SREG_LDTR);
+       tss->prev_task_link = get_segment_selector(vcpu, VCPU_SREG_TR);
+}
+
+static int load_state_from_tss32(struct kvm_vcpu *vcpu,
+                                 struct tss_segment_32 *tss)
+{
+       kvm_set_cr3(vcpu, tss->cr3);
+
+       vcpu->arch.rip = tss->eip;
+       kvm_x86_ops->set_rflags(vcpu, tss->eflags | 2);
+
+       vcpu->arch.regs[VCPU_REGS_RAX] = tss->eax;
+       vcpu->arch.regs[VCPU_REGS_RCX] = tss->ecx;
+       vcpu->arch.regs[VCPU_REGS_RDX] = tss->edx;
+       vcpu->arch.regs[VCPU_REGS_RBX] = tss->ebx;
+       vcpu->arch.regs[VCPU_REGS_RSP] = tss->esp;
+       vcpu->arch.regs[VCPU_REGS_RBP] = tss->ebp;
+       vcpu->arch.regs[VCPU_REGS_RSI] = tss->esi;
+       vcpu->arch.regs[VCPU_REGS_RDI] = tss->edi;
+
+       if (load_segment_descriptor(vcpu, tss->ldt_selector, 0, VCPU_SREG_LDTR))
+               return 1;
+
+       if (load_segment_descriptor(vcpu, tss->es, 1, VCPU_SREG_ES))
+               return 1;
+
+       if (load_segment_descriptor(vcpu, tss->cs, 9, VCPU_SREG_CS))
+               return 1;
+
+       if (load_segment_descriptor(vcpu, tss->ss, 1, VCPU_SREG_SS))
+               return 1;
+
+       if (load_segment_descriptor(vcpu, tss->ds, 1, VCPU_SREG_DS))
+               return 1;
+
+       if (load_segment_descriptor(vcpu, tss->fs, 1, VCPU_SREG_FS))
+               return 1;
+
+       if (load_segment_descriptor(vcpu, tss->gs, 1, VCPU_SREG_GS))
+               return 1;
+       return 0;
+}
+
+static void save_state_to_tss16(struct kvm_vcpu *vcpu,
+                               struct tss_segment_16 *tss)
+{
+       tss->ip = vcpu->arch.rip;
+       tss->flag = kvm_x86_ops->get_rflags(vcpu);
+       tss->ax = vcpu->arch.regs[VCPU_REGS_RAX];
+       tss->cx = vcpu->arch.regs[VCPU_REGS_RCX];
+       tss->dx = vcpu->arch.regs[VCPU_REGS_RDX];
+       tss->bx = vcpu->arch.regs[VCPU_REGS_RBX];
+       tss->sp = vcpu->arch.regs[VCPU_REGS_RSP];
+       tss->bp = vcpu->arch.regs[VCPU_REGS_RBP];
+       tss->si = vcpu->arch.regs[VCPU_REGS_RSI];
+       tss->di = vcpu->arch.regs[VCPU_REGS_RDI];
+
+       tss->es = get_segment_selector(vcpu, VCPU_SREG_ES);
+       tss->cs = get_segment_selector(vcpu, VCPU_SREG_CS);
+       tss->ss = get_segment_selector(vcpu, VCPU_SREG_SS);
+       tss->ds = get_segment_selector(vcpu, VCPU_SREG_DS);
+       tss->ldt = get_segment_selector(vcpu, VCPU_SREG_LDTR);
+       tss->prev_task_link = get_segment_selector(vcpu, VCPU_SREG_TR);
+}
+
+static int load_state_from_tss16(struct kvm_vcpu *vcpu,
+                                struct tss_segment_16 *tss)
+{
+       vcpu->arch.rip = tss->ip;
+       kvm_x86_ops->set_rflags(vcpu, tss->flag | 2);
+       vcpu->arch.regs[VCPU_REGS_RAX] = tss->ax;
+       vcpu->arch.regs[VCPU_REGS_RCX] = tss->cx;
+       vcpu->arch.regs[VCPU_REGS_RDX] = tss->dx;
+       vcpu->arch.regs[VCPU_REGS_RBX] = tss->bx;
+       vcpu->arch.regs[VCPU_REGS_RSP] = tss->sp;
+       vcpu->arch.regs[VCPU_REGS_RBP] = tss->bp;
+       vcpu->arch.regs[VCPU_REGS_RSI] = tss->si;
+       vcpu->arch.regs[VCPU_REGS_RDI] = tss->di;
+
+       if (load_segment_descriptor(vcpu, tss->ldt, 0, VCPU_SREG_LDTR))
+               return 1;
+
+       if (load_segment_descriptor(vcpu, tss->es, 1, VCPU_SREG_ES))
+               return 1;
+
+       if (load_segment_descriptor(vcpu, tss->cs, 9, VCPU_SREG_CS))
+               return 1;
+
+       if (load_segment_descriptor(vcpu, tss->ss, 1, VCPU_SREG_SS))
+               return 1;
+
+       if (load_segment_descriptor(vcpu, tss->ds, 1, VCPU_SREG_DS))
+               return 1;
+       return 0;
+}
+
+int kvm_task_switch_16(struct kvm_vcpu *vcpu, u16 tss_selector,
+                      struct desc_struct *cseg_desc,
+                      struct desc_struct *nseg_desc)
+{
+       struct tss_segment_16 tss_segment_16;
+       int ret = 0;
+
+       if (load_tss_segment16(vcpu, cseg_desc, &tss_segment_16))
+               goto out;
+
+       save_state_to_tss16(vcpu, &tss_segment_16);
+       save_tss_segment16(vcpu, cseg_desc, &tss_segment_16);
+
+       if (load_tss_segment16(vcpu, nseg_desc, &tss_segment_16))
+               goto out;
+       if (load_state_from_tss16(vcpu, &tss_segment_16))
+               goto out;
+
+       ret = 1;
+out:
+       return ret;
+}
+
+int kvm_task_switch_32(struct kvm_vcpu *vcpu, u16 tss_selector,
+                      struct desc_struct *cseg_desc,
+                      struct desc_struct *nseg_desc)
+{
+       struct tss_segment_32 tss_segment_32;
+       int ret = 0;
+
+       if (load_tss_segment32(vcpu, cseg_desc, &tss_segment_32))
+               goto out;
+
+       save_state_to_tss32(vcpu, &tss_segment_32);
+       save_tss_segment32(vcpu, cseg_desc, &tss_segment_32);
+
+       if (load_tss_segment32(vcpu, nseg_desc, &tss_segment_32))
+               goto out;
+       if (load_state_from_tss32(vcpu, &tss_segment_32))
+               goto out;
+
+       ret = 1;
+out:
+       return ret;
 }
 
+int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason)
+{
+       struct kvm_segment tr_seg;
+       struct desc_struct cseg_desc;
+       struct desc_struct nseg_desc;
+       int ret = 0;
+
+       get_segment(vcpu, &tr_seg, VCPU_SREG_TR);
+
+       if (load_guest_segment_descriptor(vcpu, tss_selector, &nseg_desc))
+               goto out;
+
+       if (load_guest_segment_descriptor(vcpu, tr_seg.selector, &cseg_desc))
+               goto out;
+
+
+       if (reason != TASK_SWITCH_IRET) {
+               int cpl;
+
+               cpl = kvm_x86_ops->get_cpl(vcpu);
+               if ((tss_selector & 3) > nseg_desc.dpl || cpl > nseg_desc.dpl) {
+                       kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
+                       return 1;
+               }
+       }
+
+       if (!nseg_desc.p || (nseg_desc.limit0 | nseg_desc.limit << 16) < 0x67) {
+               kvm_queue_exception_e(vcpu, TS_VECTOR, tss_selector & 0xfffc);
+               return 1;
+       }
+
+       if (reason == TASK_SWITCH_IRET || reason == TASK_SWITCH_JMP) {
+               cseg_desc.type &= ~(1 << 8); //clear the B flag
+               save_guest_segment_descriptor(vcpu, tr_seg.selector,
+                                             &cseg_desc);
+       }
+
+       if (reason == TASK_SWITCH_IRET) {
+               u32 eflags = kvm_x86_ops->get_rflags(vcpu);
+               kvm_x86_ops->set_rflags(vcpu, eflags & ~X86_EFLAGS_NT);
+       }
+
+       kvm_x86_ops->skip_emulated_instruction(vcpu);
+       kvm_x86_ops->cache_regs(vcpu);
+
+       if (nseg_desc.type & 8)
+               ret = kvm_task_switch_32(vcpu, tss_selector, &cseg_desc,
+                                        &nseg_desc);
+       else
+               ret = kvm_task_switch_16(vcpu, tss_selector, &cseg_desc,
+                                        &nseg_desc);
+
+       if (reason == TASK_SWITCH_CALL || reason == TASK_SWITCH_GATE) {
+               u32 eflags = kvm_x86_ops->get_rflags(vcpu);
+               kvm_x86_ops->set_rflags(vcpu, eflags | X86_EFLAGS_NT);
+       }
+
+       if (reason != TASK_SWITCH_IRET) {
+               nseg_desc.type |= (1 << 8);
+               save_guest_segment_descriptor(vcpu, tss_selector,
+                                             &nseg_desc);
+       }
+
+       kvm_x86_ops->set_cr0(vcpu, vcpu->arch.cr0 | X86_CR0_TS);
+       seg_desct_to_kvm_desct(&nseg_desc, tss_selector, &tr_seg);
+       tr_seg.type = 11;
+       set_segment(vcpu, &tr_seg, VCPU_SREG_TR);
+out:
+       kvm_x86_ops->decache_regs(vcpu);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(kvm_task_switch);
+
 int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
                                  struct kvm_sregs *sregs)
 {
@@ -2862,12 +3542,10 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        mmu_reset_needed |= vcpu->arch.cr3 != sregs->cr3;
        vcpu->arch.cr3 = sregs->cr3;
 
-       set_cr8(vcpu, sregs->cr8);
+       kvm_set_cr8(vcpu, sregs->cr8);
 
        mmu_reset_needed |= vcpu->arch.shadow_efer != sregs->efer;
-#ifdef CONFIG_X86_64
        kvm_x86_ops->set_efer(vcpu, sregs->efer);
-#endif
        kvm_set_apic_base(vcpu, sregs->apic_base);
 
        kvm_x86_ops->decache_cr4_guest_bits(vcpu);
@@ -3141,9 +3819,9 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 
        vcpu->arch.mmu.root_hpa = INVALID_PAGE;
        if (!irqchip_in_kernel(kvm) || vcpu->vcpu_id == 0)
-               vcpu->arch.mp_state = VCPU_MP_STATE_RUNNABLE;
+               vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
        else
-               vcpu->arch.mp_state = VCPU_MP_STATE_UNINITIALIZED;
+               vcpu->arch.mp_state = KVM_MP_STATE_UNINITIALIZED;
 
        page = alloc_page(GFP_KERNEL | __GFP_ZERO);
        if (!page) {
@@ -3175,7 +3853,9 @@ fail:
 void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
 {
        kvm_free_lapic(vcpu);
+       down_read(&vcpu->kvm->slots_lock);
        kvm_mmu_destroy(vcpu);
+       up_read(&vcpu->kvm->slots_lock);
        free_page((unsigned long)vcpu->arch.pio_data);
 }
 
@@ -3219,10 +3899,13 @@ static void kvm_free_vcpus(struct kvm *kvm)
 
 void kvm_arch_destroy_vm(struct kvm *kvm)
 {
+       kvm_free_pit(kvm);
        kfree(kvm->arch.vpic);
        kfree(kvm->arch.vioapic);
        kvm_free_vcpus(kvm);
        kvm_free_physmem(kvm);
+       if (kvm->arch.apic_access_page)
+               put_page(kvm->arch.apic_access_page);
        kfree(kvm);
 }
 
@@ -3278,8 +3961,8 @@ int kvm_arch_set_memory_region(struct kvm *kvm,
 
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
 {
-       return vcpu->arch.mp_state == VCPU_MP_STATE_RUNNABLE
-              || vcpu->arch.mp_state == VCPU_MP_STATE_SIPI_RECEIVED;
+       return vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE
+              || vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED;
 }
 
 static void vcpu_kick_intr(void *info)
@@ -3293,11 +3976,17 @@ static void vcpu_kick_intr(void *info)
 void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
 {
        int ipi_pcpu = vcpu->cpu;
+       int cpu = get_cpu();
 
        if (waitqueue_active(&vcpu->wq)) {
                wake_up_interruptible(&vcpu->wq);
                ++vcpu->stat.halt_wakeup;
        }
-       if (vcpu->guest_mode)
+       /*
+        * We may be called synchronously with irqs disabled in guest mode,
+        * So need not to call smp_call_function_single() in that case.
+        */
+       if (vcpu->guest_mode && vcpu->cpu != cpu)
                smp_call_function_single(ipi_pcpu, vcpu_kick_intr, vcpu, 0, 0);
+       put_cpu();
 }
index 79586003397aa7c90bc171f020710ce1fa2054e0..2ca08386f9937ea43c4d126ca011af96c10abde9 100644 (file)
 #define MemAbs      (1<<9)      /* Memory operand is absolute displacement */
 #define String      (1<<10)     /* String instruction (rep capable) */
 #define Stack       (1<<11)     /* Stack instruction (push/pop) */
+#define Group       (1<<14)     /* Bits 3:5 of modrm byte extend opcode */
+#define GroupDual   (1<<15)     /* Alternate decoding of mod == 3 */
+#define GroupMask   0xff        /* Group number stored in bits 0:7 */
+
+enum {
+       Group1_80, Group1_81, Group1_82, Group1_83,
+       Group1A, Group3_Byte, Group3, Group4, Group5, Group7,
+};
 
 static u16 opcode_table[256] = {
        /* 0x00 - 0x07 */
@@ -123,14 +131,14 @@ static u16 opcode_table[256] = {
        ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
        ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
        /* 0x80 - 0x87 */
-       ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM,
-       ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM,
+       Group | Group1_80, Group | Group1_81,
+       Group | Group1_82, Group | Group1_83,
        ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
        ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
        /* 0x88 - 0x8F */
        ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov,
        ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
-       0, ModRM | DstReg, 0, DstMem | SrcNone | ModRM | Mov | Stack,
+       0, ModRM | DstReg, 0, Group | Group1A,
        /* 0x90 - 0x9F */
        0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, ImplicitOps | Stack, ImplicitOps | Stack, 0, 0,
@@ -164,16 +172,15 @@ static u16 opcode_table[256] = {
        0, 0, 0, 0,
        /* 0xF0 - 0xF7 */
        0, 0, 0, 0,
-       ImplicitOps, ImplicitOps,
-       ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM,
+       ImplicitOps, ImplicitOps, Group | Group3_Byte, Group | Group3,
        /* 0xF8 - 0xFF */
        ImplicitOps, 0, ImplicitOps, ImplicitOps,
-       0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM
+       0, 0, Group | Group4, Group | Group5,
 };
 
 static u16 twobyte_table[256] = {
        /* 0x00 - 0x0F */
-       0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0,
+       0, Group | GroupDual | Group7, 0, 0, 0, 0, ImplicitOps, 0,
        ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
        /* 0x10 - 0x1F */
        0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0,
@@ -229,6 +236,56 @@ static u16 twobyte_table[256] = {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
+static u16 group_table[] = {
+       [Group1_80*8] =
+       ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
+       ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
+       ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
+       ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
+       [Group1_81*8] =
+       DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM,
+       DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM,
+       DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM,
+       DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM,
+       [Group1_82*8] =
+       ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
+       ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
+       ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
+       ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
+       [Group1_83*8] =
+       DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM,
+       DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM,
+       DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM,
+       DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM,
+       [Group1A*8] =
+       DstMem | SrcNone | ModRM | Mov | Stack, 0, 0, 0, 0, 0, 0, 0,
+       [Group3_Byte*8] =
+       ByteOp | SrcImm | DstMem | ModRM, 0,
+       ByteOp | DstMem | SrcNone | ModRM, ByteOp | DstMem | SrcNone | ModRM,
+       0, 0, 0, 0,
+       [Group3*8] =
+       DstMem | SrcImm | ModRM | SrcImm, 0,
+       DstMem | SrcNone | ModRM, ByteOp | DstMem | SrcNone | ModRM,
+       0, 0, 0, 0,
+       [Group4*8] =
+       ByteOp | DstMem | SrcNone | ModRM, ByteOp | DstMem | SrcNone | ModRM,
+       0, 0, 0, 0, 0, 0,
+       [Group5*8] =
+       DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM, 0, 0,
+       SrcMem | ModRM, 0, SrcMem | ModRM | Stack, 0,
+       [Group7*8] =
+       0, 0, ModRM | SrcMem, ModRM | SrcMem,
+       SrcNone | ModRM | DstMem | Mov, 0,
+       SrcMem16 | ModRM | Mov, SrcMem | ModRM | ByteOp,
+};
+
+static u16 group2_table[] = {
+       [Group7*8] =
+       SrcNone | ModRM, 0, 0, 0,
+       SrcNone | ModRM | DstMem | Mov, 0,
+       SrcMem16 | ModRM | Mov, 0,
+};
+
 /* EFLAGS bit definitions. */
 #define EFLG_OF (1<<11)
 #define EFLG_DF (1<<10)
@@ -317,7 +374,7 @@ static u16 twobyte_table[256] = {
 
 #define __emulate_2op(_op,_src,_dst,_eflags,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \
        do {                                                                 \
-               unsigned long _tmp;                                          \
+               unsigned long __tmp;                                         \
                switch ((_dst).bytes) {                                      \
                case 1:                                                      \
                        __asm__ __volatile__ (                               \
@@ -325,7 +382,7 @@ static u16 twobyte_table[256] = {
                                _op"b %"_bx"3,%1; "                          \
                                _POST_EFLAGS("0", "4", "2")                  \
                                : "=m" (_eflags), "=m" ((_dst).val),         \
-                                 "=&r" (_tmp)                               \
+                                 "=&r" (__tmp)                              \
                                : _by ((_src).val), "i" (EFLAGS_MASK));      \
                        break;                                               \
                default:                                                     \
@@ -426,29 +483,40 @@ static u16 twobyte_table[256] = {
        (_type)_x;                                                      \
 })
 
+static inline unsigned long ad_mask(struct decode_cache *c)
+{
+       return (1UL << (c->ad_bytes << 3)) - 1;
+}
+
 /* Access/update address held in a register, based on addressing mode. */
-#define address_mask(reg)                                              \
-       ((c->ad_bytes == sizeof(unsigned long)) ?                       \
-               (reg) : ((reg) & ((1UL << (c->ad_bytes << 3)) - 1)))
-#define register_address(base, reg)                                     \
-       ((base) + address_mask(reg))
-#define register_address_increment(reg, inc)                            \
-       do {                                                            \
-               /* signed type ensures sign extension to long */        \
-               int _inc = (inc);                                       \
-               if (c->ad_bytes == sizeof(unsigned long))               \
-                       (reg) += _inc;                                  \
-               else                                                    \
-                       (reg) = ((reg) &                                \
-                                ~((1UL << (c->ad_bytes << 3)) - 1)) |  \
-                               (((reg) + _inc) &                       \
-                                ((1UL << (c->ad_bytes << 3)) - 1));    \
-       } while (0)
+static inline unsigned long
+address_mask(struct decode_cache *c, unsigned long reg)
+{
+       if (c->ad_bytes == sizeof(unsigned long))
+               return reg;
+       else
+               return reg & ad_mask(c);
+}
 
-#define JMP_REL(rel)                                                   \
-       do {                                                            \
-               register_address_increment(c->eip, rel);                \
-       } while (0)
+static inline unsigned long
+register_address(struct decode_cache *c, unsigned long base, unsigned long reg)
+{
+       return base + address_mask(c, reg);
+}
+
+static inline void
+register_address_increment(struct decode_cache *c, unsigned long *reg, int inc)
+{
+       if (c->ad_bytes == sizeof(unsigned long))
+               *reg += inc;
+       else
+               *reg = (*reg & ~ad_mask(c)) | ((*reg + inc) & ad_mask(c));
+}
+
+static inline void jmp_rel(struct decode_cache *c, int rel)
+{
+       register_address_increment(c, &c->eip, rel);
+}
 
 static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt,
                              struct x86_emulate_ops *ops,
@@ -763,7 +831,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
        struct decode_cache *c = &ctxt->decode;
        int rc = 0;
        int mode = ctxt->mode;
-       int def_op_bytes, def_ad_bytes;
+       int def_op_bytes, def_ad_bytes, group;
 
        /* Shadow copy of register state. Committed on successful emulation. */
 
@@ -864,12 +932,24 @@ done_prefixes:
                        c->b = insn_fetch(u8, 1, c->eip);
                        c->d = twobyte_table[c->b];
                }
+       }
 
-               /* Unrecognised? */
-               if (c->d == 0) {
-                       DPRINTF("Cannot emulate %02x\n", c->b);
-                       return -1;
-               }
+       if (c->d & Group) {
+               group = c->d & GroupMask;
+               c->modrm = insn_fetch(u8, 1, c->eip);
+               --c->eip;
+
+               group = (group << 3) + ((c->modrm >> 3) & 7);
+               if ((c->d & GroupDual) && (c->modrm >> 6) == 3)
+                       c->d = group2_table[group];
+               else
+                       c->d = group_table[group];
+       }
+
+       /* Unrecognised? */
+       if (c->d == 0) {
+               DPRINTF("Cannot emulate %02x\n", c->b);
+               return -1;
        }
 
        if (mode == X86EMUL_MODE_PROT64 && (c->d & Stack))
@@ -924,6 +1004,7 @@ done_prefixes:
                 */
                if ((c->d & ModRM) && c->modrm_mod == 3) {
                        c->src.type = OP_REG;
+                       c->src.val = c->modrm_val;
                        break;
                }
                c->src.type = OP_MEM;
@@ -967,6 +1048,7 @@ done_prefixes:
        case DstMem:
                if ((c->d & ModRM) && c->modrm_mod == 3) {
                        c->dst.type = OP_REG;
+                       c->dst.val = c->dst.orig_val = c->modrm_val;
                        break;
                }
                c->dst.type = OP_MEM;
@@ -984,8 +1066,8 @@ static inline void emulate_push(struct x86_emulate_ctxt *ctxt)
        c->dst.type  = OP_MEM;
        c->dst.bytes = c->op_bytes;
        c->dst.val = c->src.val;
-       register_address_increment(c->regs[VCPU_REGS_RSP], -c->op_bytes);
-       c->dst.ptr = (void *) register_address(ctxt->ss_base,
+       register_address_increment(c, &c->regs[VCPU_REGS_RSP], -c->op_bytes);
+       c->dst.ptr = (void *) register_address(c, ctxt->ss_base,
                                               c->regs[VCPU_REGS_RSP]);
 }
 
@@ -995,13 +1077,13 @@ static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt,
        struct decode_cache *c = &ctxt->decode;
        int rc;
 
-       rc = ops->read_std(register_address(ctxt->ss_base,
+       rc = ops->read_std(register_address(c, ctxt->ss_base,
                                            c->regs[VCPU_REGS_RSP]),
                           &c->dst.val, c->dst.bytes, ctxt->vcpu);
        if (rc != 0)
                return rc;
 
-       register_address_increment(c->regs[VCPU_REGS_RSP], c->dst.bytes);
+       register_address_increment(c, &c->regs[VCPU_REGS_RSP], c->dst.bytes);
 
        return 0;
 }
@@ -1043,26 +1125,6 @@ static inline int emulate_grp3(struct x86_emulate_ctxt *ctxt,
 
        switch (c->modrm_reg) {
        case 0 ... 1:   /* test */
-               /*
-                * Special case in Grp3: test has an immediate
-                * source operand.
-                */
-               c->src.type = OP_IMM;
-               c->src.ptr = (unsigned long *)c->eip;
-               c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
-               if (c->src.bytes == 8)
-                       c->src.bytes = 4;
-               switch (c->src.bytes) {
-               case 1:
-                       c->src.val = insn_fetch(s8, 1, c->eip);
-                       break;
-               case 2:
-                       c->src.val = insn_fetch(s16, 2, c->eip);
-                       break;
-               case 4:
-                       c->src.val = insn_fetch(s32, 4, c->eip);
-                       break;
-               }
                emulate_2op_SrcV("test", c->src, c->dst, ctxt->eflags);
                break;
        case 2: /* not */
@@ -1076,7 +1138,6 @@ static inline int emulate_grp3(struct x86_emulate_ctxt *ctxt,
                rc = X86EMUL_UNHANDLEABLE;
                break;
        }
-done:
        return rc;
 }
 
@@ -1084,7 +1145,6 @@ static inline int emulate_grp45(struct x86_emulate_ctxt *ctxt,
                               struct x86_emulate_ops *ops)
 {
        struct decode_cache *c = &ctxt->decode;
-       int rc;
 
        switch (c->modrm_reg) {
        case 0: /* inc */
@@ -1094,36 +1154,11 @@ static inline int emulate_grp45(struct x86_emulate_ctxt *ctxt,
                emulate_1op("dec", c->dst, ctxt->eflags);
                break;
        case 4: /* jmp abs */
-               if (c->b == 0xff)
-                       c->eip = c->dst.val;
-               else {
-                       DPRINTF("Cannot emulate %02x\n", c->b);
-                       return X86EMUL_UNHANDLEABLE;
-               }
+               c->eip = c->src.val;
                break;
        case 6: /* push */
-
-               /* 64-bit mode: PUSH always pushes a 64-bit operand. */
-
-               if (ctxt->mode == X86EMUL_MODE_PROT64) {
-                       c->dst.bytes = 8;
-                       rc = ops->read_std((unsigned long)c->dst.ptr,
-                                          &c->dst.val, 8, ctxt->vcpu);
-                       if (rc != 0)
-                               return rc;
-               }
-               register_address_increment(c->regs[VCPU_REGS_RSP],
-                                          -c->dst.bytes);
-               rc = ops->write_emulated(register_address(ctxt->ss_base,
-                                   c->regs[VCPU_REGS_RSP]), &c->dst.val,
-                                   c->dst.bytes, ctxt->vcpu);
-               if (rc != 0)
-                       return rc;
-               c->dst.type = OP_NONE;
+               emulate_push(ctxt);
                break;
-       default:
-               DPRINTF("Cannot emulate %02x\n", c->b);
-               return X86EMUL_UNHANDLEABLE;
        }
        return 0;
 }
@@ -1361,19 +1396,19 @@ special_insn:
                c->dst.type  = OP_MEM;
                c->dst.bytes = c->op_bytes;
                c->dst.val = c->src.val;
-               register_address_increment(c->regs[VCPU_REGS_RSP],
+               register_address_increment(c, &c->regs[VCPU_REGS_RSP],
                                           -c->op_bytes);
                c->dst.ptr = (void *) register_address(
-                       ctxt->ss_base, c->regs[VCPU_REGS_RSP]);
+                       c, ctxt->ss_base, c->regs[VCPU_REGS_RSP]);
                break;
        case 0x58 ... 0x5f: /* pop reg */
        pop_instruction:
-               if ((rc = ops->read_std(register_address(ctxt->ss_base,
+               if ((rc = ops->read_std(register_address(c, ctxt->ss_base,
                        c->regs[VCPU_REGS_RSP]), c->dst.ptr,
                        c->op_bytes, ctxt->vcpu)) != 0)
                        goto done;
 
-               register_address_increment(c->regs[VCPU_REGS_RSP],
+               register_address_increment(c, &c->regs[VCPU_REGS_RSP],
                                           c->op_bytes);
                c->dst.type = OP_NONE;  /* Disable writeback. */
                break;
@@ -1393,9 +1428,9 @@ special_insn:
                                1,
                                (c->d & ByteOp) ? 1 : c->op_bytes,
                                c->rep_prefix ?
-                               address_mask(c->regs[VCPU_REGS_RCX]) : 1,
+                               address_mask(c, c->regs[VCPU_REGS_RCX]) : 1,
                                (ctxt->eflags & EFLG_DF),
-                               register_address(ctxt->es_base,
+                               register_address(c, ctxt->es_base,
                                                 c->regs[VCPU_REGS_RDI]),
                                c->rep_prefix,
                                c->regs[VCPU_REGS_RDX]) == 0) {
@@ -1409,9 +1444,9 @@ special_insn:
                                0,
                                (c->d & ByteOp) ? 1 : c->op_bytes,
                                c->rep_prefix ?
-                               address_mask(c->regs[VCPU_REGS_RCX]) : 1,
+                               address_mask(c, c->regs[VCPU_REGS_RCX]) : 1,
                                (ctxt->eflags & EFLG_DF),
-                               register_address(c->override_base ?
+                               register_address(c, c->override_base ?
                                                        *c->override_base :
                                                        ctxt->ds_base,
                                                 c->regs[VCPU_REGS_RSI]),
@@ -1425,7 +1460,7 @@ special_insn:
                int rel = insn_fetch(s8, 1, c->eip);
 
                if (test_cc(c->b, ctxt->eflags))
-                       JMP_REL(rel);
+                       jmp_rel(c, rel);
                break;
        }
        case 0x80 ... 0x83:     /* Grp1 */
@@ -1477,7 +1512,7 @@ special_insn:
        case 0x88 ... 0x8b:     /* mov */
                goto mov;
        case 0x8d: /* lea r16/r32, m */
-               c->dst.val = c->modrm_val;
+               c->dst.val = c->modrm_ea;
                break;
        case 0x8f:              /* pop (sole member of Grp1a) */
                rc = emulate_grp1a(ctxt, ops);
@@ -1501,27 +1536,27 @@ special_insn:
        case 0xa4 ... 0xa5:     /* movs */
                c->dst.type = OP_MEM;
                c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
-               c->dst.ptr = (unsigned long *)register_address(
+               c->dst.ptr = (unsigned long *)register_address(c,
                                                   ctxt->es_base,
                                                   c->regs[VCPU_REGS_RDI]);
-               if ((rc = ops->read_emulated(register_address(
+               if ((rc = ops->read_emulated(register_address(c,
                      c->override_base ? *c->override_base :
                                        ctxt->ds_base,
                                        c->regs[VCPU_REGS_RSI]),
                                        &c->dst.val,
                                        c->dst.bytes, ctxt->vcpu)) != 0)
                        goto done;
-               register_address_increment(c->regs[VCPU_REGS_RSI],
+               register_address_increment(c, &c->regs[VCPU_REGS_RSI],
                                       (ctxt->eflags & EFLG_DF) ? -c->dst.bytes
                                                           : c->dst.bytes);
-               register_address_increment(c->regs[VCPU_REGS_RDI],
+               register_address_increment(c, &c->regs[VCPU_REGS_RDI],
                                       (ctxt->eflags & EFLG_DF) ? -c->dst.bytes
                                                           : c->dst.bytes);
                break;
        case 0xa6 ... 0xa7:     /* cmps */
                c->src.type = OP_NONE; /* Disable writeback. */
                c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
-               c->src.ptr = (unsigned long *)register_address(
+               c->src.ptr = (unsigned long *)register_address(c,
                                c->override_base ? *c->override_base :
                                                   ctxt->ds_base,
                                                   c->regs[VCPU_REGS_RSI]);
@@ -1533,7 +1568,7 @@ special_insn:
 
                c->dst.type = OP_NONE; /* Disable writeback. */
                c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
-               c->dst.ptr = (unsigned long *)register_address(
+               c->dst.ptr = (unsigned long *)register_address(c,
                                                   ctxt->es_base,
                                                   c->regs[VCPU_REGS_RDI]);
                if ((rc = ops->read_emulated((unsigned long)c->dst.ptr,
@@ -1546,10 +1581,10 @@ special_insn:
 
                emulate_2op_SrcV("cmp", c->src, c->dst, ctxt->eflags);
 
-               register_address_increment(c->regs[VCPU_REGS_RSI],
+               register_address_increment(c, &c->regs[VCPU_REGS_RSI],
                                       (ctxt->eflags & EFLG_DF) ? -c->src.bytes
                                                                  : c->src.bytes);
-               register_address_increment(c->regs[VCPU_REGS_RDI],
+               register_address_increment(c, &c->regs[VCPU_REGS_RDI],
                                       (ctxt->eflags & EFLG_DF) ? -c->dst.bytes
                                                                  : c->dst.bytes);
 
@@ -1557,11 +1592,11 @@ special_insn:
        case 0xaa ... 0xab:     /* stos */
                c->dst.type = OP_MEM;
                c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
-               c->dst.ptr = (unsigned long *)register_address(
+               c->dst.ptr = (unsigned long *)register_address(c,
                                                   ctxt->es_base,
                                                   c->regs[VCPU_REGS_RDI]);
                c->dst.val = c->regs[VCPU_REGS_RAX];
-               register_address_increment(c->regs[VCPU_REGS_RDI],
+               register_address_increment(c, &c->regs[VCPU_REGS_RDI],
                                       (ctxt->eflags & EFLG_DF) ? -c->dst.bytes
                                                           : c->dst.bytes);
                break;
@@ -1569,7 +1604,7 @@ special_insn:
                c->dst.type = OP_REG;
                c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
                c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX];
-               if ((rc = ops->read_emulated(register_address(
+               if ((rc = ops->read_emulated(register_address(c,
                                c->override_base ? *c->override_base :
                                                   ctxt->ds_base,
                                                 c->regs[VCPU_REGS_RSI]),
@@ -1577,7 +1612,7 @@ special_insn:
                                                 c->dst.bytes,
                                                 ctxt->vcpu)) != 0)
                        goto done;
-               register_address_increment(c->regs[VCPU_REGS_RSI],
+               register_address_increment(c, &c->regs[VCPU_REGS_RSI],
                                       (ctxt->eflags & EFLG_DF) ? -c->dst.bytes
                                                           : c->dst.bytes);
                break;
@@ -1616,14 +1651,14 @@ special_insn:
                        goto cannot_emulate;
                }
                c->src.val = (unsigned long) c->eip;
-               JMP_REL(rel);
+               jmp_rel(c, rel);
                c->op_bytes = c->ad_bytes;
                emulate_push(ctxt);
                break;
        }
        case 0xe9: /* jmp rel */
        case 0xeb: /* jmp rel short */
-               JMP_REL(c->src.val);
+               jmp_rel(c, c->src.val);
                c->dst.type = OP_NONE; /* Disable writeback. */
                break;
        case 0xf4:              /* hlt */
@@ -1690,6 +1725,8 @@ twobyte_insn:
                                goto done;
 
                        kvm_emulate_hypercall(ctxt->vcpu);
+                       /* Disable writeback. */
+                       c->dst.type = OP_NONE;
                        break;
                case 2: /* lgdt */
                        rc = read_descriptor(ctxt, ops, c->src.ptr,
@@ -1697,6 +1734,8 @@ twobyte_insn:
                        if (rc)
                                goto done;
                        realmode_lgdt(ctxt->vcpu, size, address);
+                       /* Disable writeback. */
+                       c->dst.type = OP_NONE;
                        break;
                case 3: /* lidt/vmmcall */
                        if (c->modrm_mod == 3 && c->modrm_rm == 1) {
@@ -1712,27 +1751,25 @@ twobyte_insn:
                                        goto done;
                                realmode_lidt(ctxt->vcpu, size, address);
                        }
+                       /* Disable writeback. */
+                       c->dst.type = OP_NONE;
                        break;
                case 4: /* smsw */
-                       if (c->modrm_mod != 3)
-                               goto cannot_emulate;
-                       *(u16 *)&c->regs[c->modrm_rm]
-                               = realmode_get_cr(ctxt->vcpu, 0);
+                       c->dst.bytes = 2;
+                       c->dst.val = realmode_get_cr(ctxt->vcpu, 0);
                        break;
                case 6: /* lmsw */
-                       if (c->modrm_mod != 3)
-                               goto cannot_emulate;
-                       realmode_lmsw(ctxt->vcpu, (u16)c->modrm_val,
-                                                 &ctxt->eflags);
+                       realmode_lmsw(ctxt->vcpu, (u16)c->src.val,
+                                     &ctxt->eflags);
                        break;
                case 7: /* invlpg*/
                        emulate_invlpg(ctxt->vcpu, memop);
+                       /* Disable writeback. */
+                       c->dst.type = OP_NONE;
                        break;
                default:
                        goto cannot_emulate;
                }
-               /* Disable writeback. */
-               c->dst.type = OP_NONE;
                break;
        case 0x06:
                emulate_clts(ctxt->vcpu);
@@ -1823,7 +1860,7 @@ twobyte_insn:
                        goto cannot_emulate;
                }
                if (test_cc(c->b, ctxt->eflags))
-                       JMP_REL(rel);
+                       jmp_rel(c, rel);
                c->dst.type = OP_NONE;
                break;
        }
index 25df1c1989fe5e5574ba4e833978d99317b168c2..76f60f52a885246ff1a8f6ce9bad2c3791d1df94 100644 (file)
@@ -11,7 +11,7 @@ lib-y += memcpy_$(BITS).o
 ifeq ($(CONFIG_X86_32),y)
         lib-y += checksum_32.o
         lib-y += strstr_32.o
-        lib-y += bitops_32.o semaphore_32.o string_32.o
+        lib-y += semaphore_32.o string_32.o
 
         lib-$(CONFIG_X86_USE_3DNOW) += mmx_32.o
 else
@@ -21,7 +21,6 @@ else
 
         lib-y += csum-partial_64.o csum-copy_64.o csum-wrappers_64.o
         lib-y += thunk_64.o clear_page_64.o copy_page_64.o
-        lib-y += bitops_64.o
         lib-y += memmove_64.o memset_64.o
         lib-y += copy_user_64.o rwlock_64.o copy_user_nocache_64.o
 endif
diff --git a/arch/x86/lib/bitops_32.c b/arch/x86/lib/bitops_32.c
deleted file mode 100644 (file)
index b654404..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#include <linux/bitops.h>
-#include <linux/module.h>
-
-/**
- * find_next_bit - find the next set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-int find_next_bit(const unsigned long *addr, int size, int offset)
-{
-       const unsigned long *p = addr + (offset >> 5);
-       int set = 0, bit = offset & 31, res;
-
-       if (bit) {
-               /*
-                * Look for nonzero in the first 32 bits:
-                */
-               __asm__("bsfl %1,%0\n\t"
-                       "jne 1f\n\t"
-                       "movl $32, %0\n"
-                       "1:"
-                       : "=r" (set)
-                       : "r" (*p >> bit));
-               if (set < (32 - bit))
-                       return set + offset;
-               set = 32 - bit;
-               p++;
-       }
-       /*
-        * No set bit yet, search remaining full words for a bit
-        */
-       res = find_first_bit (p, size - 32 * (p - addr));
-       return (offset + set + res);
-}
-EXPORT_SYMBOL(find_next_bit);
-
-/**
- * find_next_zero_bit - find the first zero bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-int find_next_zero_bit(const unsigned long *addr, int size, int offset)
-{
-       const unsigned long *p = addr + (offset >> 5);
-       int set = 0, bit = offset & 31, res;
-
-       if (bit) {
-               /*
-                * Look for zero in the first 32 bits.
-                */
-               __asm__("bsfl %1,%0\n\t"
-                       "jne 1f\n\t"
-                       "movl $32, %0\n"
-                       "1:"
-                       : "=r" (set)
-                       : "r" (~(*p >> bit)));
-               if (set < (32 - bit))
-                       return set + offset;
-               set = 32 - bit;
-               p++;
-       }
-       /*
-        * No zero yet, search remaining full bytes for a zero
-        */
-       res = find_first_zero_bit(p, size - 32 * (p - addr));
-       return (offset + set + res);
-}
-EXPORT_SYMBOL(find_next_zero_bit);
diff --git a/arch/x86/lib/bitops_64.c b/arch/x86/lib/bitops_64.c
deleted file mode 100644 (file)
index 0e8f491..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-#include <linux/bitops.h>
-
-#undef find_first_zero_bit
-#undef find_next_zero_bit
-#undef find_first_bit
-#undef find_next_bit
-
-static inline long
-__find_first_zero_bit(const unsigned long * addr, unsigned long size)
-{
-       long d0, d1, d2;
-       long res;
-
-       /*
-        * We must test the size in words, not in bits, because
-        * otherwise incoming sizes in the range -63..-1 will not run
-        * any scasq instructions, and then the flags used by the je
-        * instruction will have whatever random value was in place
-        * before.  Nobody should call us like that, but
-        * find_next_zero_bit() does when offset and size are at the
-        * same word and it fails to find a zero itself.
-        */
-       size += 63;
-       size >>= 6;
-       if (!size)
-               return 0;
-       asm volatile(
-               "  repe; scasq\n"
-               "  je 1f\n"
-               "  xorq -8(%%rdi),%%rax\n"
-               "  subq $8,%%rdi\n"
-               "  bsfq %%rax,%%rdx\n"
-               "1:  subq %[addr],%%rdi\n"
-               "  shlq $3,%%rdi\n"
-               "  addq %%rdi,%%rdx"
-               :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
-               :"0" (0ULL), "1" (size), "2" (addr), "3" (-1ULL),
-                [addr] "S" (addr) : "memory");
-       /*
-        * Any register would do for [addr] above, but GCC tends to
-        * prefer rbx over rsi, even though rsi is readily available
-        * and doesn't have to be saved.
-        */
-       return res;
-}
-
-/**
- * find_first_zero_bit - find the first zero bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit-number of the first zero bit, not the number of the byte
- * containing a bit.
- */
-long find_first_zero_bit(const unsigned long * addr, unsigned long size)
-{
-       return __find_first_zero_bit (addr, size);
-}
-
-/**
- * find_next_zero_bit - find the next zero bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-long find_next_zero_bit (const unsigned long * addr, long size, long offset)
-{
-       const unsigned long * p = addr + (offset >> 6);
-       unsigned long set = 0;
-       unsigned long res, bit = offset&63;
-
-       if (bit) {
-               /*
-                * Look for zero in first word
-                */
-               asm("bsfq %1,%0\n\t"
-                   "cmoveq %2,%0"
-                   : "=r" (set)
-                   : "r" (~(*p >> bit)), "r"(64L));
-               if (set < (64 - bit))
-                       return set + offset;
-               set = 64 - bit;
-               p++;
-       }
-       /*
-        * No zero yet, search remaining full words for a zero
-        */
-       res = __find_first_zero_bit (p, size - 64 * (p - addr));
-
-       return (offset + set + res);
-}
-
-static inline long
-__find_first_bit(const unsigned long * addr, unsigned long size)
-{
-       long d0, d1;
-       long res;
-
-       /*
-        * We must test the size in words, not in bits, because
-        * otherwise incoming sizes in the range -63..-1 will not run
-        * any scasq instructions, and then the flags used by the jz
-        * instruction will have whatever random value was in place
-        * before.  Nobody should call us like that, but
-        * find_next_bit() does when offset and size are at the same
-        * word and it fails to find a one itself.
-        */
-       size += 63;
-       size >>= 6;
-       if (!size)
-               return 0;
-       asm volatile(
-               "   repe; scasq\n"
-               "   jz 1f\n"
-               "   subq $8,%%rdi\n"
-               "   bsfq (%%rdi),%%rax\n"
-               "1: subq %[addr],%%rdi\n"
-               "   shlq $3,%%rdi\n"
-               "   addq %%rdi,%%rax"
-               :"=a" (res), "=&c" (d0), "=&D" (d1)
-               :"0" (0ULL), "1" (size), "2" (addr),
-                [addr] "r" (addr) : "memory");
-       return res;
-}
-
-/**
- * find_first_bit - find the first set bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit-number of the first set bit, not the number of the byte
- * containing a bit.
- */
-long find_first_bit(const unsigned long * addr, unsigned long size)
-{
-       return __find_first_bit(addr,size);
-}
-
-/**
- * find_next_bit - find the first set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-long find_next_bit(const unsigned long * addr, long size, long offset)
-{
-       const unsigned long * p = addr + (offset >> 6);
-       unsigned long set = 0, bit = offset & 63, res;
-
-       if (bit) {
-               /*
-                * Look for nonzero in the first 64 bits:
-                */
-               asm("bsfq %1,%0\n\t"
-                   "cmoveq %2,%0\n\t"
-                   : "=r" (set)
-                   : "r" (*p >> bit), "r" (64L));
-               if (set < (64 - bit))
-                       return set + offset;
-               set = 64 - bit;
-               p++;
-       }
-       /*
-        * No set bit yet, search remaining full words for a bit
-        */
-       res = __find_first_bit (p, size - 64 * (p - addr));
-       return (offset + set + res);
-}
-
-#include <linux/module.h>
-
-EXPORT_SYMBOL(find_next_bit);
-EXPORT_SYMBOL(find_first_bit);
-EXPORT_SYMBOL(find_first_zero_bit);
-EXPORT_SYMBOL(find_next_zero_bit);
index 2a8456a1f44fc5896fe7de8ed25aa106d8bead68..57484e91ab904c35b327464d80bd16766556f3eb 100644 (file)
 /* Have we found an MP table */
 int smp_found_config;
 
-/*
- * Various Linux-internal data structures created from the
- * MP-table.
- */
-int apic_version [MAX_APICS];
-
 int pic_mode;
-unsigned long mp_lapic_addr;
-
-/* Processor that is doing the boot up */
-unsigned int boot_cpu_physical_apicid = -1U;
-
-/* Bitmask of physically existing CPUs */
-physid_mask_t phys_cpu_present_map;
 
-unsigned int __initdata maxcpus = NR_CPUS;
+extern unsigned int __cpuinitdata maxcpus;
 
 /*
  * The Visual Workstation is Intel MP compliant in the hardware
index 96f60c7cd124a141e7f4825bbbe555e8893d9ef3..8acbf0cdf1a5fb8eb4d75e1d57905104b23cce14 100644 (file)
@@ -113,7 +113,7 @@ static inline void send_QIC_CPI(__u32 cpuset, __u8 cpi)
        for_each_online_cpu(cpu) {
                if (cpuset & (1 << cpu)) {
 #ifdef VOYAGER_DEBUG
-                       if (!cpu_isset(cpu, cpu_online_map))
+                       if (!cpu_online(cpu))
                                VDEBUG(("CPU%d sending cpi %d to CPU%d not in "
                                        "cpu_online_map\n",
                                        hard_smp_processor_id(), cpi, cpu));
@@ -206,11 +206,6 @@ static struct irq_chip vic_chip = {
 /* used to count up as CPUs are brought on line (starts at 0) */
 static int cpucount = 0;
 
-/* steal a page from the bottom of memory for the trampoline and
- * squirrel its address away here.  This will be in kernel virtual
- * space */
-unsigned char *trampoline_base;
-
 /* The per cpu profile stuff - used in smp_local_timer_interrupt */
 static DEFINE_PER_CPU(int, prof_multiplier) = 1;
 static DEFINE_PER_CPU(int, prof_old_multiplier) = 1;
@@ -427,18 +422,6 @@ void __init smp_store_cpu_info(int id)
        identify_secondary_cpu(c);
 }
 
-/* set up the trampoline and return the physical address of the code */
-unsigned long __init setup_trampoline(void)
-{
-       /* these two are global symbols in trampoline.S */
-       extern const __u8 trampoline_end[];
-       extern const __u8 trampoline_data[];
-
-       memcpy(trampoline_base, trampoline_data,
-              trampoline_end - trampoline_data);
-       return virt_to_phys(trampoline_base);
-}
-
 /* Routine initially called when a non-boot CPU is brought online */
 static void __init start_secondary(void *unused)
 {
@@ -560,8 +543,8 @@ static void __init do_boot_cpu(__u8 cpu)
                hijack_source.idt.Offset, stack_start.sp));
 
        /* init lowmem identity mapping */
-       clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
-                       min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS));
+       clone_pgd_range(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
+                       min_t(unsigned long, KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY));
        flush_tlb_all();
 
        if (quad_boot) {
@@ -700,9 +683,9 @@ void __init smp_boot_cpus(void)
         * Code added from smpboot.c */
        {
                unsigned long bogosum = 0;
-               for (i = 0; i < NR_CPUS; i++)
-                       if (cpu_isset(i, cpu_online_map))
-                               bogosum += cpu_data(i).loops_per_jiffy;
+
+               for_each_online_cpu(i)
+                       bogosum += cpu_data(i).loops_per_jiffy;
                printk(KERN_INFO "Total of %d processors activated "
                       "(%lu.%02lu BogoMIPS).\n",
                       cpucount + 1, bogosum / (500000 / HZ),
@@ -1855,7 +1838,7 @@ static int __cpuinit voyager_cpu_up(unsigned int cpu)
                return -EIO;
        /* Unleash the CPU! */
        cpu_set(cpu, smp_commenced_mask);
-       while (!cpu_isset(cpu, cpu_online_map))
+       while (!cpu_online(cpu))
                mb();
        return 0;
 }
index 20941d2954e234d057f7bb326212d6533aeb184b..b7b3e4c7cfc9c4cd35e953ba75d64ad7cde484f5 100644 (file)
@@ -1,5 +1,5 @@
 obj-y  :=  init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \
-           pat.o
+           pat.o pgtable.o
 
 obj-$(CONFIG_X86_32)           += pgtable_32.o
 
index 6791b8334bc6809ebd7d35bc69c29f1e23e2ff64..2c24bea92c669457d50c77b7752c1954e6654f11 100644 (file)
@@ -324,7 +324,7 @@ static const struct file_operations ptdump_fops = {
        .release        = single_release,
 };
 
-int pt_dump_init(void)
+static int pt_dump_init(void)
 {
        struct dentry *pe;
 
index 9ec62da85fd79a75fc450b58c4ea54e4c77f857b..4a4761892951af0c3f0de4a5c055152254c9c26c 100644 (file)
@@ -71,7 +71,7 @@ static pmd_t * __init one_md_table_init(pgd_t *pgd)
        if (!(pgd_val(*pgd) & _PAGE_PRESENT)) {
                pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
 
-               paravirt_alloc_pd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT);
+               paravirt_alloc_pmd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT);
                set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
                pud = pud_offset(pgd, 0);
                BUG_ON(pmd_table != pmd_offset(pud, 0));
@@ -100,7 +100,7 @@ static pte_t * __init one_page_table_init(pmd_t *pmd)
                                (pte_t *)alloc_bootmem_low_pages(PAGE_SIZE);
                }
 
-               paravirt_alloc_pt(&init_mm, __pa(page_table) >> PAGE_SHIFT);
+               paravirt_alloc_pte(&init_mm, __pa(page_table) >> PAGE_SHIFT);
                set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
                BUG_ON(page_table != pte_offset_kernel(pmd, 0));
        }
@@ -227,6 +227,25 @@ static inline int page_kills_ppro(unsigned long pagenr)
        return 0;
 }
 
+/*
+ * devmem_is_allowed() checks to see if /dev/mem access to a certain address
+ * is valid. The argument is a physical page number.
+ *
+ *
+ * On x86, access has to be given to the first megabyte of ram because that area
+ * contains bios code and data regions used by X and dosemu and similar apps.
+ * Access has to be given to non-kernel-ram areas as well, these contain the PCI
+ * mmio resources as well as potential bios/acpi data regions.
+ */
+int devmem_is_allowed(unsigned long pagenr)
+{
+       if (pagenr <= 256)
+               return 1;
+       if (!page_is_ram(pagenr))
+               return 1;
+       return 0;
+}
+
 #ifdef CONFIG_HIGHMEM
 pte_t *kmap_pte;
 pgprot_t kmap_prot;
@@ -365,7 +384,7 @@ void __init native_pagetable_setup_start(pgd_t *base)
 
                pte_clear(NULL, va, pte);
        }
-       paravirt_alloc_pd(&init_mm, __pa(base) >> PAGE_SHIFT);
+       paravirt_alloc_pmd(&init_mm, __pa(base) >> PAGE_SHIFT);
 }
 
 void __init native_pagetable_setup_done(pgd_t *base)
@@ -457,7 +476,7 @@ void zap_low_mappings(void)
         * Note that "pgd_clear()" doesn't do it for
         * us, because pgd_clear() is a no-op on i386.
         */
-       for (i = 0; i < USER_PTRS_PER_PGD; i++) {
+       for (i = 0; i < KERNEL_PGD_BOUNDARY; i++) {
 #ifdef CONFIG_X86_PAE
                set_pgd(swapper_pg_dir+i, __pgd(1 + __pa(empty_zero_page)));
 #else
@@ -547,9 +566,9 @@ void __init paging_init(void)
 
 /*
  * Test if the WP bit works in supervisor mode. It isn't supported on 386's
- * and also on some strange 486's (NexGen etc.). All 586+'s are OK. This
- * used to involve black magic jumps to work around some nasty CPU bugs,
- * but fortunately the switch to using exceptions got rid of all that.
+ * and also on some strange 486's. All 586+'s are OK. This used to involve
+ * black magic jumps to work around some nasty CPU bugs, but fortunately the
+ * switch to using exceptions got rid of all that.
  */
 static void __init test_wp_bit(void)
 {
index 1ff7906a9a4dbc7afa6dfdd24f274e077cd26773..5fbb8652cf59e21130f2699c6b473847dbee58db 100644 (file)
@@ -135,7 +135,7 @@ static __init void *spp_getpage(void)
        return ptr;
 }
 
-static __init void
+static void
 set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot)
 {
        pgd_t *pgd;
@@ -173,7 +173,7 @@ set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot)
        new_pte = pfn_pte(phys >> PAGE_SHIFT, prot);
 
        pte = pte_offset_kernel(pmd, vaddr);
-       if (!pte_none(*pte) &&
+       if (!pte_none(*pte) && pte_val(new_pte) &&
            pte_val(*pte) != (pte_val(new_pte) & __supported_pte_mask))
                pte_ERROR(*pte);
        set_pte(pte, new_pte);
@@ -214,8 +214,7 @@ void __init cleanup_highmap(void)
 }
 
 /* NOTE: this is meant to be run only at boot */
-void __init
-__set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
+void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
 {
        unsigned long address = __fix_to_virt(idx);
 
@@ -664,6 +663,26 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
 
 #endif /* CONFIG_MEMORY_HOTPLUG */
 
+/*
+ * devmem_is_allowed() checks to see if /dev/mem access to a certain address
+ * is valid. The argument is a physical page number.
+ *
+ *
+ * On x86, access has to be given to the first megabyte of ram because that area
+ * contains bios code and data regions used by X and dosemu and similar apps.
+ * Access has to be given to non-kernel-ram areas as well, these contain the PCI
+ * mmio resources as well as potential bios/acpi data regions.
+ */
+int devmem_is_allowed(unsigned long pagenr)
+{
+       if (pagenr <= 256)
+               return 1;
+       if (!page_is_ram(pagenr))
+               return 1;
+       return 0;
+}
+
+
 static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel,
                         kcore_modules, kcore_vsyscall;
 
@@ -791,7 +810,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
 void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
 {
 #ifdef CONFIG_NUMA
-       int nid = phys_to_nid(phys);
+       int nid, next_nid;
 #endif
        unsigned long pfn = phys >> PAGE_SHIFT;
 
@@ -810,10 +829,16 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
 
        /* Should check here against the e820 map to avoid double free */
 #ifdef CONFIG_NUMA
-       reserve_bootmem_node(NODE_DATA(nid), phys, len, BOOTMEM_DEFAULT);
+       nid = phys_to_nid(phys);
+       next_nid = phys_to_nid(phys + len - 1);
+       if (nid == next_nid)
+               reserve_bootmem_node(NODE_DATA(nid), phys, len, BOOTMEM_DEFAULT);
+       else
+               reserve_bootmem(phys, len, BOOTMEM_DEFAULT);
 #else
        reserve_bootmem(phys, len, BOOTMEM_DEFAULT);
 #endif
+
        if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
                dma_reserve += len / PAGE_SIZE;
                set_dma_reserve(dma_reserve);
@@ -907,6 +932,10 @@ const char *arch_vma_name(struct vm_area_struct *vma)
 /*
  * Initialise the sparsemem vmemmap using huge-pages at the PMD level.
  */
+static long __meminitdata addr_start, addr_end;
+static void __meminitdata *p_start, *p_end;
+static int __meminitdata node_start;
+
 int __meminit
 vmemmap_populate(struct page *start_page, unsigned long size, int node)
 {
@@ -941,12 +970,32 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node)
                                                        PAGE_KERNEL_LARGE);
                        set_pmd(pmd, __pmd(pte_val(entry)));
 
-                       printk(KERN_DEBUG " [%lx-%lx] PMD ->%p on node %d\n",
-                               addr, addr + PMD_SIZE - 1, p, node);
+                       /* check to see if we have contiguous blocks */
+                       if (p_end != p || node_start != node) {
+                               if (p_start)
+                                       printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n",
+                                               addr_start, addr_end-1, p_start, p_end-1, node_start);
+                               addr_start = addr;
+                               node_start = node;
+                               p_start = p;
+                       }
+                       addr_end = addr + PMD_SIZE;
+                       p_end = p + PMD_SIZE;
                } else {
                        vmemmap_verify((pte_t *)pmd, node, addr, next);
                }
        }
        return 0;
 }
+
+void __meminit vmemmap_populate_print_last(void)
+{
+       if (p_start) {
+               printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n",
+                       addr_start, addr_end-1, p_start, p_end-1, node_start);
+               p_start = NULL;
+               p_end = NULL;
+               node_start = 0;
+       }
+}
 #endif
index 3a4baf95e24d5a5cee6626a5b8789064e9dce564..d176b23110cc875187be67d3c22f227ec38cbdeb 100644 (file)
@@ -336,6 +336,35 @@ void iounmap(volatile void __iomem *addr)
 }
 EXPORT_SYMBOL(iounmap);
 
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+void *xlate_dev_mem_ptr(unsigned long phys)
+{
+       void *addr;
+       unsigned long start = phys & PAGE_MASK;
+
+       /* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
+       if (page_is_ram(start >> PAGE_SHIFT))
+               return __va(phys);
+
+       addr = (void *)ioremap(start, PAGE_SIZE);
+       if (addr)
+               addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));
+
+       return addr;
+}
+
+void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
+{
+       if (page_is_ram(phys >> PAGE_SHIFT))
+               return;
+
+       iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
+       return;
+}
+
 #ifdef CONFIG_X86_32
 
 int __initdata early_ioremap_debug;
@@ -407,7 +436,7 @@ void __init early_ioremap_clear(void)
 
        pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
        pmd_clear(pmd);
-       paravirt_release_pt(__pa(bm_pte) >> PAGE_SHIFT);
+       paravirt_release_pte(__pa(bm_pte) >> PAGE_SHIFT);
        __flush_tlb_all();
 }
 
index 9a6892200b271a1ebec5fe64da0adef13b54df78..c5066d519e5de4cf73dec673f6d51c2ca131075b 100644 (file)
@@ -196,6 +196,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start,
        unsigned long bootmap_start, nodedata_phys;
        void *bootmap;
        const int pgdat_size = round_up(sizeof(pg_data_t), PAGE_SIZE);
+       int nid;
 
        start = round_up(start, ZONE_ALIGN);
 
@@ -218,9 +219,19 @@ void __init setup_node_bootmem(int nodeid, unsigned long start,
        NODE_DATA(nodeid)->node_start_pfn = start_pfn;
        NODE_DATA(nodeid)->node_spanned_pages = end_pfn - start_pfn;
 
-       /* Find a place for the bootmem map */
+       /*
+        * Find a place for the bootmem map
+        * nodedata_phys could be on other nodes by alloc_bootmem,
+        * so need to sure bootmap_start not to be small, otherwise
+        * early_node_mem will get that with find_e820_area instead
+        * of alloc_bootmem, that could clash with reserved range
+        */
        bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
-       bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE);
+       nid = phys_to_nid(nodedata_phys);
+       if (nid == nodeid)
+               bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE);
+       else
+               bootmap_start = round_up(start, PAGE_SIZE);
        /*
         * SMP_CAHCE_BYTES could be enough, but init_bootmem_node like
         * to use that to align to PAGE_SIZE
@@ -245,10 +256,29 @@ void __init setup_node_bootmem(int nodeid, unsigned long start,
 
        free_bootmem_with_active_regions(nodeid, end);
 
-       reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size,
-                       BOOTMEM_DEFAULT);
-       reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start,
-                       bootmap_pages<<PAGE_SHIFT, BOOTMEM_DEFAULT);
+       /*
+        * convert early reserve to bootmem reserve earlier
+        * otherwise early_node_mem could use early reserved mem
+        * on previous node
+        */
+       early_res_to_bootmem(start, end);
+
+       /*
+        * in some case early_node_mem could use alloc_bootmem
+        * to get range on other node, don't reserve that again
+        */
+       if (nid != nodeid)
+               printk(KERN_INFO "    NODE_DATA(%d) on node %d\n", nodeid, nid);
+       else
+               reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys,
+                                       pgdat_size, BOOTMEM_DEFAULT);
+       nid = phys_to_nid(bootmap_start);
+       if (nid != nodeid)
+               printk(KERN_INFO "    bootmap(%d) on node %d\n", nodeid, nid);
+       else
+               reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start,
+                                bootmap_pages<<PAGE_SHIFT, BOOTMEM_DEFAULT);
+
 #ifdef CONFIG_ACPI_NUMA
        srat_reserve_add_area(nodeid);
 #endif
index f7823a17286838d016985c3c3bb9885c08982c95..bd5e05c654dccfb33d368718e4b7acdbdd16d5d0 100644 (file)
@@ -483,9 +483,7 @@ static int split_large_page(pte_t *kpte, unsigned long address)
                goto out_unlock;
 
        pbase = (pte_t *)page_address(base);
-#ifdef CONFIG_X86_32
-       paravirt_alloc_pt(&init_mm, page_to_pfn(base));
-#endif
+       paravirt_alloc_pte(&init_mm, page_to_pfn(base));
        ref_prot = pte_pgprot(pte_clrhuge(*kpte));
 
 #ifdef CONFIG_X86_64
@@ -993,7 +991,7 @@ static const struct file_operations dpa_fops = {
        .release        = single_release,
 };
 
-int __init debug_pagealloc_proc_init(void)
+static int __init debug_pagealloc_proc_init(void)
 {
        struct dentry *de;
 
index 72c0f6097402bfae75d7d658efa4dc6544994c78..e7ca7fc48d123d723be9e3efef3e63b1c34b74ba 100644 (file)
 #include <linux/kernel.h>
 #include <linux/gfp.h>
 #include <linux/fs.h>
+#include <linux/bootmem.h>
 
 #include <asm/msr.h>
 #include <asm/tlbflush.h>
 #include <asm/processor.h>
+#include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/pat.h>
 #include <asm/e820.h>
 #include <asm/cacheflush.h>
 #include <asm/fcntl.h>
 #include <asm/mtrr.h>
+#include <asm/io.h>
 
 int pat_wc_enabled = 1;
 
@@ -190,6 +193,21 @@ static int pat_x_mtrr_type(u64 start, u64 end, unsigned long prot,
        return 0;
 }
 
+/*
+ * req_type typically has one of the:
+ * - _PAGE_CACHE_WB
+ * - _PAGE_CACHE_WC
+ * - _PAGE_CACHE_UC_MINUS
+ * - _PAGE_CACHE_UC
+ *
+ * req_type will have a special case value '-1', when requester want to inherit
+ * the memory type from mtrr (if WB), existing PAT, defaulting to UC_MINUS.
+ *
+ * If ret_type is NULL, function will return an error if it cannot reserve the
+ * region with req_type. If ret_type is non-null, function will return
+ * available type in ret_type in case of no error. In case of any error
+ * it will return a negative return value.
+ */
 int reserve_memtype(u64 start, u64 end, unsigned long req_type,
                        unsigned long *ret_type)
 {
@@ -200,9 +218,14 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
 
        /* Only track when pat_wc_enabled */
        if (!pat_wc_enabled) {
-               if (ret_type)
-                       *ret_type = req_type;
-
+               /* This is identical to page table setting without PAT */
+               if (ret_type) {
+                       if (req_type == -1) {
+                               *ret_type = _PAGE_CACHE_WB;
+                       } else {
+                               *ret_type = req_type;
+                       }
+               }
                return 0;
        }
 
@@ -214,8 +237,29 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
                return 0;
        }
 
-       req_type &= _PAGE_CACHE_MASK;
-       err = pat_x_mtrr_type(start, end, req_type, &actual_type);
+       if (req_type == -1) {
+               /*
+                * Special case where caller wants to inherit from mtrr or
+                * existing pat mapping, defaulting to UC_MINUS in case of
+                * no match.
+                */
+               u8 mtrr_type = mtrr_type_lookup(start, end);
+               if (mtrr_type == 0xFE) { /* MTRR match error */
+                       err = -1;
+               }
+
+               if (mtrr_type == MTRR_TYPE_WRBACK) {
+                       req_type = _PAGE_CACHE_WB;
+                       actual_type = _PAGE_CACHE_WB;
+               } else {
+                       req_type = _PAGE_CACHE_UC_MINUS;
+                       actual_type = _PAGE_CACHE_UC_MINUS;
+               }
+       } else {
+               req_type &= _PAGE_CACHE_MASK;
+               err = pat_x_mtrr_type(start, end, req_type, &actual_type);
+       }
+
        if (err) {
                if (ret_type)
                        *ret_type = actual_type;
@@ -241,7 +285,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
                struct memtype *saved_ptr;
 
                if (parse->start >= end) {
-                       printk("New Entry\n");
+                       pr_debug("New Entry\n");
                        list_add(&new_entry->nd, parse->nd.prev);
                        new_entry = NULL;
                        break;
@@ -291,7 +335,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
                                break;
                        }
 
-                       printk("Overlap at 0x%Lx-0x%Lx\n",
+                       pr_debug("Overlap at 0x%Lx-0x%Lx\n",
                               saved_ptr->start, saved_ptr->end);
                        /* No conflict. Go ahead and add this new entry */
                        list_add(&new_entry->nd, saved_ptr->nd.prev);
@@ -343,7 +387,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
                                break;
                        }
 
-                       printk("Overlap at 0x%Lx-0x%Lx\n",
+                       printk(KERN_INFO "Overlap at 0x%Lx-0x%Lx\n",
                               saved_ptr->start, saved_ptr->end);
                        /* No conflict. Go ahead and add this new entry */
                        list_add(&new_entry->nd, &saved_ptr->nd);
@@ -353,7 +397,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
        }
 
        if (err) {
-               printk(
+               printk(KERN_INFO
        "reserve_memtype failed 0x%Lx-0x%Lx, track %s, req %s\n",
                        start, end, cattr_name(new_entry->type),
                        cattr_name(req_type));
@@ -365,16 +409,16 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
        if (new_entry) {
                /* No conflict. Not yet added to the list. Add to the tail */
                list_add_tail(&new_entry->nd, &memtype_list);
-               printk("New Entry\n");
-       }
+               pr_debug("New Entry\n");
+       }
 
        if (ret_type) {
-               printk(
+               pr_debug(
        "reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
                        start, end, cattr_name(actual_type),
                        cattr_name(req_type), cattr_name(*ret_type));
        } else {
-               printk(
+               pr_debug(
        "reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s\n",
                        start, end, cattr_name(actual_type),
                        cattr_name(req_type));
@@ -411,11 +455,145 @@ int free_memtype(u64 start, u64 end)
        spin_unlock(&memtype_lock);
 
        if (err) {
-               printk(KERN_DEBUG "%s:%d freeing invalid memtype %Lx-%Lx\n",
+               printk(KERN_INFO "%s:%d freeing invalid memtype %Lx-%Lx\n",
                        current->comm, current->pid, start, end);
        }
 
-       printk( "free_memtype request 0x%Lx-0x%Lx\n", start, end);
+       pr_debug("free_memtype request 0x%Lx-0x%Lx\n", start, end);
        return err;
 }
 
+
+/*
+ * /dev/mem mmap interface. The memtype used for mapping varies:
+ * - Use UC for mappings with O_SYNC flag
+ * - Without O_SYNC flag, if there is any conflict in reserve_memtype,
+ *   inherit the memtype from existing mapping.
+ * - Else use UC_MINUS memtype (for backward compatibility with existing
+ *   X drivers.
+ */
+pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+                               unsigned long size, pgprot_t vma_prot)
+{
+       return vma_prot;
+}
+
+#ifdef CONFIG_NONPROMISC_DEVMEM
+/* This check is done in drivers/char/mem.c in case of NONPROMISC_DEVMEM*/
+static inline int range_is_allowed(unsigned long pfn, unsigned long size)
+{
+       return 1;
+}
+#else
+static inline int range_is_allowed(unsigned long pfn, unsigned long size)
+{
+       u64 from = ((u64)pfn) << PAGE_SHIFT;
+       u64 to = from + size;
+       u64 cursor = from;
+
+       while (cursor < to) {
+               if (!devmem_is_allowed(pfn)) {
+                       printk(KERN_INFO
+               "Program %s tried to access /dev/mem between %Lx->%Lx.\n",
+                               current->comm, from, to);
+                       return 0;
+               }
+               cursor += PAGE_SIZE;
+               pfn++;
+       }
+       return 1;
+}
+#endif /* CONFIG_NONPROMISC_DEVMEM */
+
+int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
+                               unsigned long size, pgprot_t *vma_prot)
+{
+       u64 offset = ((u64) pfn) << PAGE_SHIFT;
+       unsigned long flags = _PAGE_CACHE_UC_MINUS;
+       unsigned long ret_flags;
+       int retval;
+
+       if (!range_is_allowed(pfn, size))
+               return 0;
+
+       if (file->f_flags & O_SYNC) {
+               flags = _PAGE_CACHE_UC;
+       }
+
+#ifdef CONFIG_X86_32
+       /*
+        * On the PPro and successors, the MTRRs are used to set
+        * memory types for physical addresses outside main memory,
+        * so blindly setting UC or PWT on those pages is wrong.
+        * For Pentiums and earlier, the surround logic should disable
+        * caching for the high addresses through the KEN pin, but
+        * we maintain the tradition of paranoia in this code.
+        */
+       if (!pat_wc_enabled &&
+           ! ( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ||
+               test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ||
+               test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
+               test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability)) &&
+          (pfn << PAGE_SHIFT) >= __pa(high_memory)) {
+               flags = _PAGE_CACHE_UC;
+       }
+#endif
+
+       /*
+        * With O_SYNC, we can only take UC mapping. Fail if we cannot.
+        * Without O_SYNC, we want to get
+        * - WB for WB-able memory and no other conflicting mappings
+        * - UC_MINUS for non-WB-able memory with no other conflicting mappings
+        * - Inherit from confliting mappings otherwise
+        */
+       if (flags != _PAGE_CACHE_UC_MINUS) {
+               retval = reserve_memtype(offset, offset + size, flags, NULL);
+       } else {
+               retval = reserve_memtype(offset, offset + size, -1, &ret_flags);
+       }
+
+       if (retval < 0)
+               return 0;
+
+       flags = ret_flags;
+
+       if (pfn <= max_pfn_mapped &&
+            ioremap_change_attr((unsigned long)__va(offset), size, flags) < 0) {
+               free_memtype(offset, offset + size);
+               printk(KERN_INFO
+               "%s:%d /dev/mem ioremap_change_attr failed %s for %Lx-%Lx\n",
+                       current->comm, current->pid,
+                       cattr_name(flags),
+                       offset, offset + size);
+               return 0;
+       }
+
+       *vma_prot = __pgprot((pgprot_val(*vma_prot) & ~_PAGE_CACHE_MASK) |
+                            flags);
+       return 1;
+}
+
+void map_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot)
+{
+       u64 addr = (u64)pfn << PAGE_SHIFT;
+       unsigned long flags;
+       unsigned long want_flags = (pgprot_val(vma_prot) & _PAGE_CACHE_MASK);
+
+       reserve_memtype(addr, addr + size, want_flags, &flags);
+       if (flags != want_flags) {
+               printk(KERN_INFO
+               "%s:%d /dev/mem expected mapping type %s for %Lx-%Lx, got %s\n",
+                       current->comm, current->pid,
+                       cattr_name(want_flags),
+                       addr, addr + size,
+                       cattr_name(flags));
+       }
+}
+
+void unmap_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot)
+{
+       u64 addr = (u64)pfn << PAGE_SHIFT;
+
+       free_memtype(addr, addr + size);
+}
+
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
new file mode 100644 (file)
index 0000000..5015976
--- /dev/null
@@ -0,0 +1,276 @@
+#include <linux/mm.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/tlb.h>
+
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+       return (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+}
+
+pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+       struct page *pte;
+
+#ifdef CONFIG_HIGHPTE
+       pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT|__GFP_ZERO, 0);
+#else
+       pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+#endif
+       if (pte)
+               pgtable_page_ctor(pte);
+       return pte;
+}
+
+void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
+{
+       pgtable_page_dtor(pte);
+       paravirt_release_pte(page_to_pfn(pte));
+       tlb_remove_page(tlb, pte);
+}
+
+#if PAGETABLE_LEVELS > 2
+void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
+{
+       paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
+       tlb_remove_page(tlb, virt_to_page(pmd));
+}
+
+#if PAGETABLE_LEVELS > 3
+void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
+{
+       paravirt_release_pud(__pa(pud) >> PAGE_SHIFT);
+       tlb_remove_page(tlb, virt_to_page(pud));
+}
+#endif /* PAGETABLE_LEVELS > 3 */
+#endif /* PAGETABLE_LEVELS > 2 */
+
+static inline void pgd_list_add(pgd_t *pgd)
+{
+       struct page *page = virt_to_page(pgd);
+
+       list_add(&page->lru, &pgd_list);
+}
+
+static inline void pgd_list_del(pgd_t *pgd)
+{
+       struct page *page = virt_to_page(pgd);
+
+       list_del(&page->lru);
+}
+
+#define UNSHARED_PTRS_PER_PGD                          \
+       (SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD)
+
+static void pgd_ctor(void *p)
+{
+       pgd_t *pgd = p;
+       unsigned long flags;
+
+       /* Clear usermode parts of PGD */
+       memset(pgd, 0, KERNEL_PGD_BOUNDARY*sizeof(pgd_t));
+
+       spin_lock_irqsave(&pgd_lock, flags);
+
+       /* If the pgd points to a shared pagetable level (either the
+          ptes in non-PAE, or shared PMD in PAE), then just copy the
+          references from swapper_pg_dir. */
+       if (PAGETABLE_LEVELS == 2 ||
+           (PAGETABLE_LEVELS == 3 && SHARED_KERNEL_PMD) ||
+           PAGETABLE_LEVELS == 4) {
+               clone_pgd_range(pgd + KERNEL_PGD_BOUNDARY,
+                               swapper_pg_dir + KERNEL_PGD_BOUNDARY,
+                               KERNEL_PGD_PTRS);
+               paravirt_alloc_pmd_clone(__pa(pgd) >> PAGE_SHIFT,
+                                        __pa(swapper_pg_dir) >> PAGE_SHIFT,
+                                        KERNEL_PGD_BOUNDARY,
+                                        KERNEL_PGD_PTRS);
+       }
+
+       /* list required to sync kernel mapping updates */
+       if (!SHARED_KERNEL_PMD)
+               pgd_list_add(pgd);
+
+       spin_unlock_irqrestore(&pgd_lock, flags);
+}
+
+static void pgd_dtor(void *pgd)
+{
+       unsigned long flags; /* can be called from interrupt context */
+
+       if (SHARED_KERNEL_PMD)
+               return;
+
+       spin_lock_irqsave(&pgd_lock, flags);
+       pgd_list_del(pgd);
+       spin_unlock_irqrestore(&pgd_lock, flags);
+}
+
+/*
+ * List of all pgd's needed for non-PAE so it can invalidate entries
+ * in both cached and uncached pgd's; not needed for PAE since the
+ * kernel pmd is shared. If PAE were not to share the pmd a similar
+ * tactic would be needed. This is essentially codepath-based locking
+ * against pageattr.c; it is the unique case in which a valid change
+ * of kernel pagetables can't be lazily synchronized by vmalloc faults.
+ * vmalloc faults work because attached pagetables are never freed.
+ * -- wli
+ */
+
+#ifdef CONFIG_X86_PAE
+/*
+ * Mop up any pmd pages which may still be attached to the pgd.
+ * Normally they will be freed by munmap/exit_mmap, but any pmd we
+ * preallocate which never got a corresponding vma will need to be
+ * freed manually.
+ */
+static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
+{
+       int i;
+
+       for(i = 0; i < UNSHARED_PTRS_PER_PGD; i++) {
+               pgd_t pgd = pgdp[i];
+
+               if (pgd_val(pgd) != 0) {
+                       pmd_t *pmd = (pmd_t *)pgd_page_vaddr(pgd);
+
+                       pgdp[i] = native_make_pgd(0);
+
+                       paravirt_release_pmd(pgd_val(pgd) >> PAGE_SHIFT);
+                       pmd_free(mm, pmd);
+               }
+       }
+}
+
+/*
+ * In PAE mode, we need to do a cr3 reload (=tlb flush) when
+ * updating the top-level pagetable entries to guarantee the
+ * processor notices the update.  Since this is expensive, and
+ * all 4 top-level entries are used almost immediately in a
+ * new process's life, we just pre-populate them here.
+ *
+ * Also, if we're in a paravirt environment where the kernel pmd is
+ * not shared between pagetables (!SHARED_KERNEL_PMDS), we allocate
+ * and initialize the kernel pmds here.
+ */
+static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
+{
+       pud_t *pud;
+       unsigned long addr;
+       int i;
+
+       pud = pud_offset(pgd, 0);
+       for (addr = i = 0; i < UNSHARED_PTRS_PER_PGD;
+            i++, pud++, addr += PUD_SIZE) {
+               pmd_t *pmd = pmd_alloc_one(mm, addr);
+
+               if (!pmd) {
+                       pgd_mop_up_pmds(mm, pgd);
+                       return 0;
+               }
+
+               if (i >= KERNEL_PGD_BOUNDARY)
+                       memcpy(pmd, (pmd_t *)pgd_page_vaddr(swapper_pg_dir[i]),
+                              sizeof(pmd_t) * PTRS_PER_PMD);
+
+               pud_populate(mm, pud, pmd);
+       }
+
+       return 1;
+}
+
+void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
+{
+       paravirt_alloc_pmd(mm, __pa(pmd) >> PAGE_SHIFT);
+
+       /* Note: almost everything apart from _PAGE_PRESENT is
+          reserved at the pmd (PDPT) level. */
+       set_pud(pudp, __pud(__pa(pmd) | _PAGE_PRESENT));
+
+       /*
+        * According to Intel App note "TLBs, Paging-Structure Caches,
+        * and Their Invalidation", April 2007, document 317080-001,
+        * section 8.1: in PAE mode we explicitly have to flush the
+        * TLB via cr3 if the top-level pgd is changed...
+        */
+       if (mm == current->active_mm)
+               write_cr3(read_cr3());
+}
+#else  /* !CONFIG_X86_PAE */
+/* No need to prepopulate any pagetable entries in non-PAE modes. */
+static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
+{
+       return 1;
+}
+
+static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgd)
+{
+}
+#endif /* CONFIG_X86_PAE */
+
+pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+       pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+
+       /* so that alloc_pmd can use it */
+       mm->pgd = pgd;
+       if (pgd)
+               pgd_ctor(pgd);
+
+       if (pgd && !pgd_prepopulate_pmd(mm, pgd)) {
+               pgd_dtor(pgd);
+               free_page((unsigned long)pgd);
+               pgd = NULL;
+       }
+
+       return pgd;
+}
+
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+       pgd_mop_up_pmds(mm, pgd);
+       pgd_dtor(pgd);
+       free_page((unsigned long)pgd);
+}
+
+int ptep_set_access_flags(struct vm_area_struct *vma,
+                         unsigned long address, pte_t *ptep,
+                         pte_t entry, int dirty)
+{
+       int changed = !pte_same(*ptep, entry);
+
+       if (changed && dirty) {
+               *ptep = entry;
+               pte_update_defer(vma->vm_mm, address, ptep);
+               flush_tlb_page(vma, address);
+       }
+
+       return changed;
+}
+
+int ptep_test_and_clear_young(struct vm_area_struct *vma,
+                             unsigned long addr, pte_t *ptep)
+{
+       int ret = 0;
+
+       if (pte_young(*ptep))
+               ret = test_and_clear_bit(_PAGE_BIT_ACCESSED,
+                                        &ptep->pte);
+
+       if (ret)
+               pte_update(vma->vm_mm, addr, ptep);
+
+       return ret;
+}
+
+int ptep_clear_flush_young(struct vm_area_struct *vma,
+                          unsigned long address, pte_t *ptep)
+{
+       int young;
+
+       young = ptep_test_and_clear_young(vma, address, ptep);
+       if (young)
+               flush_tlb_page(vma, address);
+
+       return young;
+}
index 6fb9e7c6893fd44afad45232355b47c867c7cf75..9ee007be914299ab8dae9d3f52df22ae606816f1 100644 (file)
@@ -173,210 +173,6 @@ void reserve_top_address(unsigned long reserve)
        __VMALLOC_RESERVE += reserve;
 }
 
-pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
-{
-       return (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
-}
-
-pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
-{
-       struct page *pte;
-
-#ifdef CONFIG_HIGHPTE
-       pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT|__GFP_ZERO, 0);
-#else
-       pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
-#endif
-       if (pte)
-               pgtable_page_ctor(pte);
-       return pte;
-}
-
-/*
- * List of all pgd's needed for non-PAE so it can invalidate entries
- * in both cached and uncached pgd's; not needed for PAE since the
- * kernel pmd is shared. If PAE were not to share the pmd a similar
- * tactic would be needed. This is essentially codepath-based locking
- * against pageattr.c; it is the unique case in which a valid change
- * of kernel pagetables can't be lazily synchronized by vmalloc faults.
- * vmalloc faults work because attached pagetables are never freed.
- * -- wli
- */
-static inline void pgd_list_add(pgd_t *pgd)
-{
-       struct page *page = virt_to_page(pgd);
-
-       list_add(&page->lru, &pgd_list);
-}
-
-static inline void pgd_list_del(pgd_t *pgd)
-{
-       struct page *page = virt_to_page(pgd);
-
-       list_del(&page->lru);
-}
-
-#define UNSHARED_PTRS_PER_PGD                          \
-       (SHARED_KERNEL_PMD ? USER_PTRS_PER_PGD : PTRS_PER_PGD)
-
-static void pgd_ctor(void *p)
-{
-       pgd_t *pgd = p;
-       unsigned long flags;
-
-       /* Clear usermode parts of PGD */
-       memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
-
-       spin_lock_irqsave(&pgd_lock, flags);
-
-       /* If the pgd points to a shared pagetable level (either the
-          ptes in non-PAE, or shared PMD in PAE), then just copy the
-          references from swapper_pg_dir. */
-       if (PAGETABLE_LEVELS == 2 ||
-           (PAGETABLE_LEVELS == 3 && SHARED_KERNEL_PMD)) {
-               clone_pgd_range(pgd + USER_PTRS_PER_PGD,
-                               swapper_pg_dir + USER_PTRS_PER_PGD,
-                               KERNEL_PGD_PTRS);
-               paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
-                                       __pa(swapper_pg_dir) >> PAGE_SHIFT,
-                                       USER_PTRS_PER_PGD,
-                                       KERNEL_PGD_PTRS);
-       }
-
-       /* list required to sync kernel mapping updates */
-       if (!SHARED_KERNEL_PMD)
-               pgd_list_add(pgd);
-
-       spin_unlock_irqrestore(&pgd_lock, flags);
-}
-
-static void pgd_dtor(void *pgd)
-{
-       unsigned long flags; /* can be called from interrupt context */
-
-       if (SHARED_KERNEL_PMD)
-               return;
-
-       spin_lock_irqsave(&pgd_lock, flags);
-       pgd_list_del(pgd);
-       spin_unlock_irqrestore(&pgd_lock, flags);
-}
-
-#ifdef CONFIG_X86_PAE
-/*
- * Mop up any pmd pages which may still be attached to the pgd.
- * Normally they will be freed by munmap/exit_mmap, but any pmd we
- * preallocate which never got a corresponding vma will need to be
- * freed manually.
- */
-static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
-{
-       int i;
-
-       for(i = 0; i < UNSHARED_PTRS_PER_PGD; i++) {
-               pgd_t pgd = pgdp[i];
-
-               if (pgd_val(pgd) != 0) {
-                       pmd_t *pmd = (pmd_t *)pgd_page_vaddr(pgd);
-
-                       pgdp[i] = native_make_pgd(0);
-
-                       paravirt_release_pd(pgd_val(pgd) >> PAGE_SHIFT);
-                       pmd_free(mm, pmd);
-               }
-       }
-}
-
-/*
- * In PAE mode, we need to do a cr3 reload (=tlb flush) when
- * updating the top-level pagetable entries to guarantee the
- * processor notices the update.  Since this is expensive, and
- * all 4 top-level entries are used almost immediately in a
- * new process's life, we just pre-populate them here.
- *
- * Also, if we're in a paravirt environment where the kernel pmd is
- * not shared between pagetables (!SHARED_KERNEL_PMDS), we allocate
- * and initialize the kernel pmds here.
- */
-static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
-{
-       pud_t *pud;
-       unsigned long addr;
-       int i;
-
-       pud = pud_offset(pgd, 0);
-       for (addr = i = 0; i < UNSHARED_PTRS_PER_PGD;
-            i++, pud++, addr += PUD_SIZE) {
-               pmd_t *pmd = pmd_alloc_one(mm, addr);
-
-               if (!pmd) {
-                       pgd_mop_up_pmds(mm, pgd);
-                       return 0;
-               }
-
-               if (i >= USER_PTRS_PER_PGD)
-                       memcpy(pmd, (pmd_t *)pgd_page_vaddr(swapper_pg_dir[i]),
-                              sizeof(pmd_t) * PTRS_PER_PMD);
-
-               pud_populate(mm, pud, pmd);
-       }
-
-       return 1;
-}
-#else  /* !CONFIG_X86_PAE */
-/* No need to prepopulate any pagetable entries in non-PAE modes. */
-static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
-{
-       return 1;
-}
-
-static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
-{
-}
-#endif /* CONFIG_X86_PAE */
-
-pgd_t *pgd_alloc(struct mm_struct *mm)
-{
-       pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
-
-       /* so that alloc_pd can use it */
-       mm->pgd = pgd;
-       if (pgd)
-               pgd_ctor(pgd);
-
-       if (pgd && !pgd_prepopulate_pmd(mm, pgd)) {
-               pgd_dtor(pgd);
-               free_page((unsigned long)pgd);
-               pgd = NULL;
-       }
-
-       return pgd;
-}
-
-void pgd_free(struct mm_struct *mm, pgd_t *pgd)
-{
-       pgd_mop_up_pmds(mm, pgd);
-       pgd_dtor(pgd);
-       free_page((unsigned long)pgd);
-}
-
-void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
-{
-       pgtable_page_dtor(pte);
-       paravirt_release_pt(page_to_pfn(pte));
-       tlb_remove_page(tlb, pte);
-}
-
-#ifdef CONFIG_X86_PAE
-
-void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
-{
-       paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
-       tlb_remove_page(tlb, virt_to_page(pmd));
-}
-
-#endif
-
 int pmd_bad(pmd_t pmd)
 {
        WARN_ON_ONCE(pmd_bad_v1(pmd) != pmd_bad_v2(pmd));
index fb43d89f46f3c92b51e5eedc85be49340eabd765..3890234e5b2629f54f1449224510ba612d58ba68 100644 (file)
@@ -163,7 +163,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
               pxm, apic_id, node);
 }
 
-int update_end_of_memory(unsigned long end) {return -1;}
+static int update_end_of_memory(unsigned long end) {return -1;}
 static int hotadd_enough_memory(struct bootnode *nd) {return 1;}
 #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
 static inline int save_add_info(void) {return 1;}
index 4d5f2649bee4e9e5dc0dd7f9cc0dab20c31c7d0d..2e641be2737e162171f5a96df11a5ad4c30c7476 100644 (file)
@@ -6,7 +6,7 @@ config XEN
        bool "Xen guest support"
        select PARAVIRT
        depends on X86_32
-       depends on X86_CMPXCHG && X86_TSC && !NEED_MULTIPLE_NODES && !(X86_VISWS || X86_VOYAGER)
+       depends on X86_CMPXCHG && X86_TSC && !(X86_VISWS || X86_VOYAGER)
        help
          This is the Linux Xen port.  Enabling this will allow the
          kernel to boot in a paravirtualized environment under the
index 343df246bd3eedd31d0a35db9736a0cdc904b78a..3d8df981d5fd8e84cb58993a65d4c2d46a0b3407 100644 (file)
@@ -1,4 +1,4 @@
-obj-y          := enlighten.o setup.o features.o multicalls.o mmu.o \
-                       events.o time.o manage.o xen-asm.o
+obj-y          := enlighten.o setup.o multicalls.o mmu.o \
+                       time.o manage.o xen-asm.o grant-table.o
 
 obj-$(CONFIG_SMP)      += smp.o
index c0388220cf9728a8e5b47c6032b0baeef1ed12f9..c8a56e457d61a35c21040bbe91486f9ceb9bf6bf 100644 (file)
@@ -155,7 +155,8 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
        if (*ax == 1)
                maskedx = ~((1 << X86_FEATURE_APIC) |  /* disable APIC */
                            (1 << X86_FEATURE_ACPI) |  /* disable ACPI */
-                           (1 << X86_FEATURE_SEP)  |  /* disable SEP */
+                           (1 << X86_FEATURE_MCE)  |  /* disable MCE */
+                           (1 << X86_FEATURE_MCA)  |  /* disable MCA */
                            (1 << X86_FEATURE_ACC));   /* thermal monitoring */
 
        asm(XEN_EMULATE_PREFIX "cpuid"
@@ -531,26 +532,37 @@ static void xen_apic_write(unsigned long reg, u32 val)
 static void xen_flush_tlb(void)
 {
        struct mmuext_op *op;
-       struct multicall_space mcs = xen_mc_entry(sizeof(*op));
+       struct multicall_space mcs;
+
+       preempt_disable();
+
+       mcs = xen_mc_entry(sizeof(*op));
 
        op = mcs.args;
        op->cmd = MMUEXT_TLB_FLUSH_LOCAL;
        MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
 
        xen_mc_issue(PARAVIRT_LAZY_MMU);
+
+       preempt_enable();
 }
 
 static void xen_flush_tlb_single(unsigned long addr)
 {
        struct mmuext_op *op;
-       struct multicall_space mcs = xen_mc_entry(sizeof(*op));
+       struct multicall_space mcs;
+
+       preempt_disable();
 
+       mcs = xen_mc_entry(sizeof(*op));
        op = mcs.args;
        op->cmd = MMUEXT_INVLPG_LOCAL;
        op->arg1.linear_addr = addr & PAGE_MASK;
        MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
 
        xen_mc_issue(PARAVIRT_LAZY_MMU);
+
+       preempt_enable();
 }
 
 static void xen_flush_tlb_others(const cpumask_t *cpus, struct mm_struct *mm,
@@ -655,15 +667,17 @@ static void xen_write_cr3(unsigned long cr3)
 
 /* Early in boot, while setting up the initial pagetable, assume
    everything is pinned. */
-static __init void xen_alloc_pt_init(struct mm_struct *mm, u32 pfn)
+static __init void xen_alloc_pte_init(struct mm_struct *mm, u32 pfn)
 {
+#ifdef CONFIG_FLATMEM
        BUG_ON(mem_map);        /* should only be used early */
+#endif
        make_lowmem_page_readonly(__va(PFN_PHYS(pfn)));
 }
 
-/* Early release_pt assumes that all pts are pinned, since there's
+/* Early release_pte assumes that all pts are pinned, since there's
    only init_mm and anything attached to that is pinned. */
-static void xen_release_pt_init(u32 pfn)
+static void xen_release_pte_init(u32 pfn)
 {
        make_lowmem_page_readwrite(__va(PFN_PHYS(pfn)));
 }
@@ -697,12 +711,12 @@ static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level)
        }
 }
 
-static void xen_alloc_pt(struct mm_struct *mm, u32 pfn)
+static void xen_alloc_pte(struct mm_struct *mm, u32 pfn)
 {
        xen_alloc_ptpage(mm, pfn, PT_PTE);
 }
 
-static void xen_alloc_pd(struct mm_struct *mm, u32 pfn)
+static void xen_alloc_pmd(struct mm_struct *mm, u32 pfn)
 {
        xen_alloc_ptpage(mm, pfn, PT_PMD);
 }
@@ -722,12 +736,12 @@ static void xen_release_ptpage(u32 pfn, unsigned level)
        }
 }
 
-static void xen_release_pt(u32 pfn)
+static void xen_release_pte(u32 pfn)
 {
        xen_release_ptpage(pfn, PT_PTE);
 }
 
-static void xen_release_pd(u32 pfn)
+static void xen_release_pmd(u32 pfn)
 {
        xen_release_ptpage(pfn, PT_PMD);
 }
@@ -849,10 +863,10 @@ static __init void xen_pagetable_setup_done(pgd_t *base)
 {
        /* This will work as long as patching hasn't happened yet
           (which it hasn't) */
-       pv_mmu_ops.alloc_pt = xen_alloc_pt;
-       pv_mmu_ops.alloc_pd = xen_alloc_pd;
-       pv_mmu_ops.release_pt = xen_release_pt;
-       pv_mmu_ops.release_pd = xen_release_pd;
+       pv_mmu_ops.alloc_pte = xen_alloc_pte;
+       pv_mmu_ops.alloc_pmd = xen_alloc_pmd;
+       pv_mmu_ops.release_pte = xen_release_pte;
+       pv_mmu_ops.release_pmd = xen_release_pmd;
        pv_mmu_ops.set_pte = xen_set_pte;
 
        setup_shared_info();
@@ -994,7 +1008,7 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = {
        .read_pmc = native_read_pmc,
 
        .iret = xen_iret,
-       .irq_enable_syscall_ret = NULL,  /* never called */
+       .irq_enable_syscall_ret = xen_sysexit,
 
        .load_tr_desc = paravirt_nop,
        .set_ldt = xen_set_ldt,
@@ -1059,11 +1073,11 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
        .pte_update = paravirt_nop,
        .pte_update_defer = paravirt_nop,
 
-       .alloc_pt = xen_alloc_pt_init,
-       .release_pt = xen_release_pt_init,
-       .alloc_pd = xen_alloc_pt_init,
-       .alloc_pd_clone = paravirt_nop,
-       .release_pd = xen_release_pt_init,
+       .alloc_pte = xen_alloc_pte_init,
+       .release_pte = xen_release_pte_init,
+       .alloc_pmd = xen_alloc_pte_init,
+       .alloc_pmd_clone = paravirt_nop,
+       .release_pmd = xen_release_pte_init,
 
 #ifdef CONFIG_HIGHPTE
        .kmap_atomic_pte = xen_kmap_atomic_pte,
diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c
new file mode 100644 (file)
index 0000000..49ba9b5
--- /dev/null
@@ -0,0 +1,91 @@
+/******************************************************************************
+ * grant_table.c
+ * x86 specific part
+ *
+ * Granting foreign access to our memory reservation.
+ *
+ * Copyright (c) 2005-2006, Christopher Clark
+ * Copyright (c) 2004-2005, K A Fraser
+ * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan. Split out x86 specific part.
+ *
+ * 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; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+
+#include <xen/interface/xen.h>
+#include <xen/page.h>
+#include <xen/grant_table.h>
+
+#include <asm/pgtable.h>
+
+static int map_pte_fn(pte_t *pte, struct page *pmd_page,
+                     unsigned long addr, void *data)
+{
+       unsigned long **frames = (unsigned long **)data;
+
+       set_pte_at(&init_mm, addr, pte, mfn_pte((*frames)[0], PAGE_KERNEL));
+       (*frames)++;
+       return 0;
+}
+
+static int unmap_pte_fn(pte_t *pte, struct page *pmd_page,
+                       unsigned long addr, void *data)
+{
+
+       set_pte_at(&init_mm, addr, pte, __pte(0));
+       return 0;
+}
+
+int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
+                          unsigned long max_nr_gframes,
+                          struct grant_entry **__shared)
+{
+       int rc;
+       struct grant_entry *shared = *__shared;
+
+       if (shared == NULL) {
+               struct vm_struct *area =
+                       xen_alloc_vm_area(PAGE_SIZE * max_nr_gframes);
+               BUG_ON(area == NULL);
+               shared = area->addr;
+               *__shared = shared;
+       }
+
+       rc = apply_to_page_range(&init_mm, (unsigned long)shared,
+                                PAGE_SIZE * nr_gframes,
+                                map_pte_fn, &frames);
+       return rc;
+}
+
+void arch_gnttab_unmap_shared(struct grant_entry *shared,
+                             unsigned long nr_gframes)
+{
+       apply_to_page_range(&init_mm, (unsigned long)shared,
+                           PAGE_SIZE * nr_gframes, unmap_pte_fn, NULL);
+}
index 2a054ef2a3dab3ac6fc3cebd380a21b8b84dd54a..6cbcf65609addd6f04d6d6b8d05607624442337b 100644 (file)
@@ -156,6 +156,10 @@ void set_pte_mfn(unsigned long vaddr, unsigned long mfn, pgprot_t flags)
 void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
                    pte_t *ptep, pte_t pteval)
 {
+       /* updates to init_mm may be done without lock */
+       if (mm == &init_mm)
+               preempt_disable();
+
        if (mm == current->mm || mm == &init_mm) {
                if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
                        struct multicall_space mcs;
@@ -163,14 +167,61 @@ void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
 
                        MULTI_update_va_mapping(mcs.mc, addr, pteval, 0);
                        xen_mc_issue(PARAVIRT_LAZY_MMU);
-                       return;
+                       goto out;
                } else
                        if (HYPERVISOR_update_va_mapping(addr, pteval, 0) == 0)
-                               return;
+                               goto out;
        }
        xen_set_pte(ptep, pteval);
+
+out:
+       if (mm == &init_mm)
+               preempt_enable();
+}
+
+pteval_t xen_pte_val(pte_t pte)
+{
+       pteval_t ret = pte.pte;
+
+       if (ret & _PAGE_PRESENT)
+               ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT;
+
+       return ret;
+}
+
+pgdval_t xen_pgd_val(pgd_t pgd)
+{
+       pgdval_t ret = pgd.pgd;
+       if (ret & _PAGE_PRESENT)
+               ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT;
+       return ret;
+}
+
+pte_t xen_make_pte(pteval_t pte)
+{
+       if (pte & _PAGE_PRESENT) {
+               pte = phys_to_machine(XPADDR(pte)).maddr;
+               pte &= ~(_PAGE_PCD | _PAGE_PWT);
+       }
+
+       return (pte_t){ .pte = pte };
 }
 
+pgd_t xen_make_pgd(pgdval_t pgd)
+{
+       if (pgd & _PAGE_PRESENT)
+               pgd = phys_to_machine(XPADDR(pgd)).maddr;
+
+       return (pgd_t){ pgd };
+}
+
+pmdval_t xen_pmd_val(pmd_t pmd)
+{
+       pmdval_t ret = native_pmd_val(pmd);
+       if (ret & _PAGE_PRESENT)
+               ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT;
+       return ret;
+}
 #ifdef CONFIG_X86_PAE
 void xen_set_pud(pud_t *ptr, pud_t val)
 {
@@ -214,100 +265,18 @@ void xen_pmd_clear(pmd_t *pmdp)
        xen_set_pmd(pmdp, __pmd(0));
 }
 
-unsigned long long xen_pte_val(pte_t pte)
+pmd_t xen_make_pmd(pmdval_t pmd)
 {
-       unsigned long long ret = 0;
-
-       if (pte.pte_low) {
-               ret = ((unsigned long long)pte.pte_high << 32) | pte.pte_low;
-               ret = machine_to_phys(XMADDR(ret)).paddr | 1;
-       }
-
-       return ret;
-}
-
-unsigned long long xen_pmd_val(pmd_t pmd)
-{
-       unsigned long long ret = pmd.pmd;
-       if (ret)
-               ret = machine_to_phys(XMADDR(ret)).paddr | 1;
-       return ret;
-}
-
-unsigned long long xen_pgd_val(pgd_t pgd)
-{
-       unsigned long long ret = pgd.pgd;
-       if (ret)
-               ret = machine_to_phys(XMADDR(ret)).paddr | 1;
-       return ret;
-}
-
-pte_t xen_make_pte(unsigned long long pte)
-{
-       if (pte & _PAGE_PRESENT) {
-               pte = phys_to_machine(XPADDR(pte)).maddr;
-               pte &= ~(_PAGE_PCD | _PAGE_PWT);
-       }
-
-       return (pte_t){ .pte = pte };
-}
-
-pmd_t xen_make_pmd(unsigned long long pmd)
-{
-       if (pmd & 1)
+       if (pmd & _PAGE_PRESENT)
                pmd = phys_to_machine(XPADDR(pmd)).maddr;
 
-       return (pmd_t){ pmd };
-}
-
-pgd_t xen_make_pgd(unsigned long long pgd)
-{
-       if (pgd & _PAGE_PRESENT)
-               pgd = phys_to_machine(XPADDR(pgd)).maddr;
-
-       return (pgd_t){ pgd };
+       return native_make_pmd(pmd);
 }
 #else  /* !PAE */
 void xen_set_pte(pte_t *ptep, pte_t pte)
 {
        *ptep = pte;
 }
-
-unsigned long xen_pte_val(pte_t pte)
-{
-       unsigned long ret = pte.pte_low;
-
-       if (ret & _PAGE_PRESENT)
-               ret = machine_to_phys(XMADDR(ret)).paddr;
-
-       return ret;
-}
-
-unsigned long xen_pgd_val(pgd_t pgd)
-{
-       unsigned long ret = pgd.pgd;
-       if (ret)
-               ret = machine_to_phys(XMADDR(ret)).paddr | 1;
-       return ret;
-}
-
-pte_t xen_make_pte(unsigned long pte)
-{
-       if (pte & _PAGE_PRESENT) {
-               pte = phys_to_machine(XPADDR(pte)).maddr;
-               pte &= ~(_PAGE_PCD | _PAGE_PWT);
-       }
-
-       return (pte_t){ pte };
-}
-
-pgd_t xen_make_pgd(unsigned long pgd)
-{
-       if (pgd & _PAGE_PRESENT)
-               pgd = phys_to_machine(XPADDR(pgd)).maddr;
-
-       return (pgd_t){ pgd };
-}
 #endif /* CONFIG_X86_PAE */
 
 /*
index 2341492bf7a056743097e06bfabd0b8c01f7436f..82517e4a752a19049c0177768851f48a1190a639 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
 
+#include <xen/interface/callback.h>
 #include <xen/interface/physdev.h>
 #include <xen/features.h>
 
@@ -68,6 +69,24 @@ static void __init fiddle_vdso(void)
        *mask |= 1 << VDSO_NOTE_NONEGSEG_BIT;
 }
 
+void xen_enable_sysenter(void)
+{
+       int cpu = smp_processor_id();
+       extern void xen_sysenter_target(void);
+       /* Mask events on entry, even though they get enabled immediately */
+       static struct callback_register sysenter = {
+               .type = CALLBACKTYPE_sysenter,
+               .address = { __KERNEL_CS, (unsigned long)xen_sysenter_target },
+               .flags = CALLBACKF_mask_events,
+       };
+
+       if (!boot_cpu_has(X86_FEATURE_SEP) ||
+           HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) != 0) {
+               clear_cpu_cap(&cpu_data(cpu), X86_FEATURE_SEP);
+               clear_cpu_cap(&boot_cpu_data, X86_FEATURE_SEP);
+       }
+}
+
 void __init xen_arch_setup(void)
 {
        struct physdev_set_iopl set_iopl;
@@ -82,6 +101,8 @@ void __init xen_arch_setup(void)
        HYPERVISOR_set_callbacks(__KERNEL_CS, (unsigned long)xen_hypervisor_callback,
                                 __KERNEL_CS, (unsigned long)xen_failsafe_callback);
 
+       xen_enable_sysenter();
+
        set_iopl.iopl = 1;
        rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl);
        if (rc != 0)
index e340ff92f6b6e4299396ddf53f79b5908fe90636..94e69000f9826e80da488a694477ee329998d230 100644 (file)
@@ -36,8 +36,9 @@
 #include "mmu.h"
 
 static cpumask_t xen_cpu_initialized_map;
-static DEFINE_PER_CPU(int, resched_irq);
-static DEFINE_PER_CPU(int, callfunc_irq);
+static DEFINE_PER_CPU(int, resched_irq) = -1;
+static DEFINE_PER_CPU(int, callfunc_irq) = -1;
+static DEFINE_PER_CPU(int, debug_irq) = -1;
 
 /*
  * Structure and data for smp_call_function(). This is designed to minimise
@@ -72,6 +73,7 @@ static __cpuinit void cpu_bringup_and_idle(void)
        int cpu = smp_processor_id();
 
        cpu_init();
+       xen_enable_sysenter();
 
        preempt_disable();
        per_cpu(cpu_state, cpu) = CPU_ONLINE;
@@ -88,9 +90,7 @@ static __cpuinit void cpu_bringup_and_idle(void)
 static int xen_smp_intr_init(unsigned int cpu)
 {
        int rc;
-       const char *resched_name, *callfunc_name;
-
-       per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) = -1;
+       const char *resched_name, *callfunc_name, *debug_name;
 
        resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu);
        rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR,
@@ -114,6 +114,14 @@ static int xen_smp_intr_init(unsigned int cpu)
                goto fail;
        per_cpu(callfunc_irq, cpu) = rc;
 
+       debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu);
+       rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, xen_debug_interrupt,
+                                    IRQF_DISABLED | IRQF_PERCPU | IRQF_NOBALANCING,
+                                    debug_name, NULL);
+       if (rc < 0)
+               goto fail;
+       per_cpu(debug_irq, cpu) = rc;
+
        return 0;
 
  fail:
@@ -121,6 +129,8 @@ static int xen_smp_intr_init(unsigned int cpu)
                unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
        if (per_cpu(callfunc_irq, cpu) >= 0)
                unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
+       if (per_cpu(debug_irq, cpu) >= 0)
+               unbind_from_irqhandler(per_cpu(debug_irq, cpu), NULL);
        return rc;
 }
 
@@ -183,7 +193,7 @@ void __init xen_smp_prepare_cpus(unsigned int max_cpus)
 
        /* Restrict the possible_map according to max_cpus. */
        while ((num_possible_cpus() > 1) && (num_possible_cpus() > max_cpus)) {
-               for (cpu = NR_CPUS-1; !cpu_isset(cpu, cpu_possible_map); cpu--)
+               for (cpu = NR_CPUS - 1; !cpu_possible(cpu); cpu--)
                        continue;
                cpu_clear(cpu, cpu_possible_map);
        }
index fe161ed4b01e49de531b6e5b26462aad7d0c222d..2497a30f41de0331b93c5f36df5804013a68ee9b 100644 (file)
@@ -107,6 +107,20 @@ ENDPATCH(xen_restore_fl_direct)
        ENDPROC(xen_restore_fl_direct)
        RELOC(xen_restore_fl_direct, 2b+1)
 
+/*
+       We can't use sysexit directly, because we're not running in ring0.
+       But we can easily fake it up using iret.  Assuming xen_sysexit
+       is jumped to with a standard stack frame, we can just strip it
+       back to a standard iret frame and use iret.
+ */
+ENTRY(xen_sysexit)
+       movl PT_EAX(%esp), %eax                 /* Shouldn't be necessary? */
+       orl $X86_EFLAGS_IF, PT_EFLAGS(%esp)
+       lea PT_EIP(%esp), %esp
+
+       jmp xen_iret
+ENDPROC(xen_sysexit)
+
 /*
        This is run where a normal iret would be run, with the same stack setup:
              8: eflags
@@ -184,8 +198,12 @@ iret_restore_end:
           region is OK. */
        je xen_hypervisor_callback
 
-       iret
+1:     iret
 xen_iret_end_crit:
+.section __ex_table,"a"
+       .align 4
+       .long 1b,iret_exc
+.previous
 
 hyper_iret:
        /* put this out of line since its very rarely used */
@@ -219,9 +237,7 @@ hyper_iret:
         ds             }  SAVE_ALL state
         eax            }
          :             :
-        ebx            }
-       ----------------
-        return addr     <- esp
+        ebx            }<- esp
        ----------------
 
    In order to deliver the nested exception properly, we need to shift
@@ -236,10 +252,8 @@ hyper_iret:
    it's usermode state which we eventually need to restore.
  */
 ENTRY(xen_iret_crit_fixup)
-       /* offsets +4 for return address */
-
        /*
-          Paranoia: Make sure we're really coming from userspace.
+          Paranoia: Make sure we're really coming from kernel space.
           One could imagine a case where userspace jumps into the
           critical range address, but just before the CPU delivers a GP,
           it decides to deliver an interrupt instead.  Unlikely?
@@ -248,32 +262,32 @@ ENTRY(xen_iret_crit_fixup)
           jump instruction itself, not the destination, but some virtual
           environments get this wrong.
         */
-       movl PT_CS+4(%esp), %ecx
+       movl PT_CS(%esp), %ecx
        andl $SEGMENT_RPL_MASK, %ecx
        cmpl $USER_RPL, %ecx
        je 2f
 
-       lea PT_ORIG_EAX+4(%esp), %esi
-       lea PT_EFLAGS+4(%esp), %edi
+       lea PT_ORIG_EAX(%esp), %esi
+       lea PT_EFLAGS(%esp), %edi
 
        /* If eip is before iret_restore_end then stack
           hasn't been restored yet. */
        cmp $iret_restore_end, %eax
        jae 1f
 
-       movl 0+4(%edi),%eax             /* copy EAX */
-       movl %eax, PT_EAX+4(%esp)
+       movl 0+4(%edi),%eax             /* copy EAX (just above top of frame) */
+       movl %eax, PT_EAX(%esp)
 
        lea ESP_OFFSET(%edi),%edi       /* move dest up over saved regs */
 
        /* set up the copy */
 1:     std
-       mov $(PT_EIP+4) / 4, %ecx       /* copy ret+saved regs up to orig_eax */
+       mov $PT_EIP / 4, %ecx           /* saved regs up to orig_eax */
        rep movsl
        cld
 
        lea 4(%edi),%esp                /* point esp to new frame */
-2:     ret
+2:     jmp xen_do_upcall
 
 
 /*
index 956a491ea998b1e5dddc0a90dde1b88ad5b25268..f1063ae0803795014d29af4a02ca9eb4211536b1 100644 (file)
@@ -2,6 +2,8 @@
 #define XEN_OPS_H
 
 #include <linux/init.h>
+#include <linux/irqreturn.h>
+#include <xen/xen-ops.h>
 
 /* These are code, but not functions.  Defined in entry.S */
 extern const char xen_hypervisor_callback[];
@@ -9,7 +11,6 @@ extern const char xen_failsafe_callback[];
 
 void xen_copy_trap_info(struct trap_info *traps);
 
-DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
 DECLARE_PER_CPU(unsigned long, xen_cr3);
 DECLARE_PER_CPU(unsigned long, xen_current_cr3);
 
@@ -19,6 +20,7 @@ extern struct shared_info *HYPERVISOR_shared_info;
 char * __init xen_memory_setup(void);
 void __init xen_arch_setup(void);
 void __init xen_init_IRQ(void);
+void xen_enable_sysenter(void);
 
 void xen_setup_timer(int cpu);
 void xen_setup_cpu_clockevents(void);
@@ -28,6 +30,8 @@ unsigned long xen_get_wallclock(void);
 int xen_set_wallclock(unsigned long time);
 unsigned long long xen_sched_clock(void);
 
+irqreturn_t xen_debug_interrupt(int irq, void *dev_id);
+
 bool xen_vcpu_stolen(int vcpu);
 
 void xen_mark_init_mm_pinned(void);
@@ -64,4 +68,6 @@ DECL_ASM(unsigned long, xen_save_fl_direct, void);
 DECL_ASM(void, xen_restore_fl_direct, unsigned long);
 
 void xen_iret(void);
+void xen_sysexit(void);
+
 #endif /* XEN_OPS_H */
index f51172ed27c25b02f54dc91895e794d30e9d3914..23ea4fd1a66d9464b0b3af5dd53f997852f65c1a 100644 (file)
@@ -699,14 +699,26 @@ static struct bsg_device *bsg_alloc_device(void)
        return bd;
 }
 
+static void bsg_kref_release_function(struct kref *kref)
+{
+       struct bsg_class_device *bcd =
+               container_of(kref, struct bsg_class_device, ref);
+
+       if (bcd->release)
+               bcd->release(bcd->parent);
+
+       put_device(bcd->parent);
+}
+
 static int bsg_put_device(struct bsg_device *bd)
 {
-       int ret = 0;
-       struct device *dev = bd->queue->bsg_dev.dev;
+       int ret = 0, do_free;
+       struct request_queue *q = bd->queue;
 
        mutex_lock(&bsg_mutex);
 
-       if (!atomic_dec_and_test(&bd->ref_count))
+       do_free = atomic_dec_and_test(&bd->ref_count);
+       if (!do_free)
                goto out;
 
        dprintk("%s: tearing down\n", bd->name);
@@ -723,12 +735,13 @@ static int bsg_put_device(struct bsg_device *bd)
         */
        ret = bsg_complete_all_commands(bd);
 
-       blk_put_queue(bd->queue);
        hlist_del(&bd->dev_list);
        kfree(bd);
 out:
        mutex_unlock(&bsg_mutex);
-       put_device(dev);
+       kref_put(&q->bsg_dev.ref, bsg_kref_release_function);
+       if (do_free)
+               blk_put_queue(q);
        return ret;
 }
 
@@ -796,7 +809,7 @@ static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
        mutex_lock(&bsg_mutex);
        bcd = idr_find(&bsg_minor_idr, iminor(inode));
        if (bcd)
-               get_device(bcd->dev);
+               kref_get(&bcd->ref);
        mutex_unlock(&bsg_mutex);
 
        if (!bcd)
@@ -808,7 +821,7 @@ static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
 
        bd = bsg_add_device(inode, bcd->queue, file);
        if (IS_ERR(bd))
-               put_device(bcd->dev);
+               kref_put(&bcd->ref, bsg_kref_release_function);
 
        return bd;
 }
@@ -947,14 +960,14 @@ void bsg_unregister_queue(struct request_queue *q)
        idr_remove(&bsg_minor_idr, bcd->minor);
        sysfs_remove_link(&q->kobj, "bsg");
        device_unregister(bcd->class_dev);
-       put_device(bcd->dev);
        bcd->class_dev = NULL;
+       kref_put(&bcd->ref, bsg_kref_release_function);
        mutex_unlock(&bsg_mutex);
 }
 EXPORT_SYMBOL_GPL(bsg_unregister_queue);
 
-int bsg_register_queue(struct request_queue *q, struct device *gdev,
-                      const char *name)
+int bsg_register_queue(struct request_queue *q, struct device *parent,
+                      const char *name, void (*release)(struct device *))
 {
        struct bsg_class_device *bcd;
        dev_t dev;
@@ -965,7 +978,7 @@ int bsg_register_queue(struct request_queue *q, struct device *gdev,
        if (name)
                devname = name;
        else
-               devname = gdev->bus_id;
+               devname = parent->bus_id;
 
        /*
         * we need a proper transport to send commands, not a stacked device
@@ -996,9 +1009,11 @@ int bsg_register_queue(struct request_queue *q, struct device *gdev,
 
        bcd->minor = minor;
        bcd->queue = q;
-       bcd->dev = get_device(gdev);
+       bcd->parent = get_device(parent);
+       bcd->release = release;
+       kref_init(&bcd->ref);
        dev = MKDEV(bsg_major, bcd->minor);
-       class_dev = device_create(bsg_class, gdev, dev, "%s", devname);
+       class_dev = device_create(bsg_class, parent, dev, "%s", devname);
        if (IS_ERR(class_dev)) {
                ret = PTR_ERR(class_dev);
                goto put_dev;
@@ -1017,7 +1032,7 @@ int bsg_register_queue(struct request_queue *q, struct device *gdev,
 unregister_class_dev:
        device_unregister(class_dev);
 put_dev:
-       put_device(gdev);
+       put_device(parent);
 remove_idr:
        idr_remove(&bsg_minor_idr, minor);
 unlock:
index 3a0e3549739f5980c6458d53c135f33878346ead..80f0ec91e2cf3fd04f6076661c6e223ec931a5db 100644 (file)
@@ -97,4 +97,6 @@ source "drivers/dca/Kconfig"
 source "drivers/auxdisplay/Kconfig"
 
 source "drivers/uio/Kconfig"
+
+source "drivers/xen/Kconfig"
 endmenu
index 788da9781f80ffb5311b396cd3557b0786376dcd..0d90ff5fd1172440b724f161b1ad51657511eb3a 100644 (file)
@@ -418,13 +418,12 @@ static void acpi_processor_idle(void)
 
        cx = pr->power.state;
        if (!cx || acpi_idle_suspend) {
-               if (pm_idle_save)
-                       pm_idle_save();
-               else
+               if (pm_idle_save) {
+                       pm_idle_save(); /* enables IRQs */
+               } else {
                        acpi_safe_halt();
-
-               if (irqs_disabled())
                        local_irq_enable();
+               }
 
                return;
        }
@@ -520,10 +519,12 @@ static void acpi_processor_idle(void)
                 * Use the appropriate idle routine, the one that would
                 * be used without acpi C-states.
                 */
-               if (pm_idle_save)
-                       pm_idle_save();
-               else
+               if (pm_idle_save) {
+                       pm_idle_save(); /* enables IRQs */
+               } else {
                        acpi_safe_halt();
+                       local_irq_enable();
+               }
 
                /*
                 * TBD: Can't get time duration while in C1, as resumes
@@ -534,8 +535,6 @@ static void acpi_processor_idle(void)
                 *       skew otherwise.
                 */
                sleep_ticks = 0xFFFFFFFF;
-               if (irqs_disabled())
-                       local_irq_enable();
 
                break;
 
index 986e3324e3026230bee39dbf9b0001fe23c15c64..7c4f886f1f1635cc99911db1085f5630ac9ba77f 100644 (file)
@@ -556,16 +556,27 @@ static inline void __iomem *ahci_port_base(struct ata_port *ap)
 
 static void ahci_enable_ahci(void __iomem *mmio)
 {
+       int i;
        u32 tmp;
 
        /* turn on AHCI_EN */
        tmp = readl(mmio + HOST_CTL);
-       if (!(tmp & HOST_AHCI_EN)) {
+       if (tmp & HOST_AHCI_EN)
+               return;
+
+       /* Some controllers need AHCI_EN to be written multiple times.
+        * Try a few times before giving up.
+        */
+       for (i = 0; i < 5; i++) {
                tmp |= HOST_AHCI_EN;
                writel(tmp, mmio + HOST_CTL);
                tmp = readl(mmio + HOST_CTL);   /* flush && sanity check */
-               WARN_ON(!(tmp & HOST_AHCI_EN));
+               if (tmp & HOST_AHCI_EN)
+                       return;
+               msleep(10);
        }
+
+       WARN_ON(1);
 }
 
 /**
index b7c38eeb498f4746983f84249c8314a55d2033d3..ea2c7649d399b38c70c987703246de96e9e2b00a 100644 (file)
@@ -573,6 +573,7 @@ static const struct ich_laptop ich_laptop[] = {
        { 0x27DF, 0x1043, 0x1267 },     /* ICH7 on Asus W5F */
        { 0x27DF, 0x103C, 0x30A1 },     /* ICH7 on HP Compaq nc2400 */
        { 0x24CA, 0x1025, 0x0061 },     /* ICH4 on ACER Aspire 2023WLMi */
+       { 0x2653, 0x1043, 0x82D8 },     /* ICH6M on Asus Eee 701 */
        /* end marker */
        { 0, }
 };
index 8c1cfc645c854e58cec7647e9967d40feb638a48..70b77e0899a84848d5da89b736505aaee977f2b2 100644 (file)
@@ -227,11 +227,9 @@ void ata_acpi_associate(struct ata_host *host)
                        acpi_install_notify_handler(ap->acpi_handle,
                                                    ACPI_SYSTEM_NOTIFY,
                                                    ata_acpi_ap_notify, ap);
-#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
                        /* we might be on a docking station */
                        register_hotplug_dock_device(ap->acpi_handle,
                                                     ata_acpi_ap_notify, ap);
-#endif
                }
 
                for (j = 0; j < ata_link_max_devices(&ap->link); j++) {
@@ -241,11 +239,9 @@ void ata_acpi_associate(struct ata_host *host)
                                acpi_install_notify_handler(dev->acpi_handle,
                                                ACPI_SYSTEM_NOTIFY,
                                                ata_acpi_dev_notify, dev);
-#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
                                /* we might be on a docking station */
                                register_hotplug_dock_device(dev->acpi_handle,
                                                ata_acpi_dev_notify, dev);
-#endif
                        }
                }
        }
index b0b00af90d0e18314782fec05cdd136cbd41eff1..51b7d2fad36a2539d72da75f44bcb2683ee041a5 100644 (file)
@@ -2616,7 +2616,7 @@ void ata_port_probe(struct ata_port *ap)
  *     LOCKING:
  *     None.
  */
-void sata_print_link_status(struct ata_link *link)
+static void sata_print_link_status(struct ata_link *link)
 {
        u32 sstatus, scontrol, tmp;
 
@@ -2772,7 +2772,7 @@ static int __sata_set_spd_needed(struct ata_link *link, u32 *scontrol)
  *     RETURNS:
  *     1 if SATA spd configuration is needed, 0 otherwise.
  */
-int sata_set_spd_needed(struct ata_link *link)
+static int sata_set_spd_needed(struct ata_link *link)
 {
        u32 scontrol;
 
@@ -3377,7 +3377,7 @@ int ata_wait_ready(struct ata_link *link, unsigned long deadline,
  *     RETURNS:
  *     0 if @linke is ready before @deadline; otherwise, -errno.
  */
-extern int ata_wait_after_reset(struct ata_link *link, unsigned long deadline,
+int ata_wait_after_reset(struct ata_link *link, unsigned long deadline,
                                int (*check_ready)(struct ata_link *link))
 {
        msleep(ATA_WAIT_AFTER_RESET_MSECS);
@@ -6208,7 +6208,6 @@ EXPORT_SYMBOL_GPL(ata_host_detach);
 EXPORT_SYMBOL_GPL(ata_sg_init);
 EXPORT_SYMBOL_GPL(ata_qc_complete);
 EXPORT_SYMBOL_GPL(ata_qc_complete_multiple);
-EXPORT_SYMBOL_GPL(sata_print_link_status);
 EXPORT_SYMBOL_GPL(atapi_cmd_type);
 EXPORT_SYMBOL_GPL(ata_tf_to_fis);
 EXPORT_SYMBOL_GPL(ata_tf_from_fis);
index d94359a24d419cbe36ee09bb155d9a32ef8d81fa..61dcd0026c64c301c8ce43a0ec89e5eebaf755f8 100644 (file)
@@ -1402,6 +1402,7 @@ static void ata_eh_analyze_ncq_error(struct ata_link *link)
        /* we've got the perpetrator, condemn it */
        qc = __ata_qc_from_tag(ap, tag);
        memcpy(&qc->result_tf, &tf, sizeof(tf));
+       qc->result_tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
        qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ;
        ehc->i.err_mask &= ~AC_ERR_DEV;
 }
index 15499522e6427392fe80f5fe47f35573d9479d81..2ec65a8fda79ecc46986ed0da6de7d886c71ccf5 100644 (file)
@@ -1208,7 +1208,7 @@ fsm_start:
                DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n",
                        ap->print_id, qc->dev->devno, status);
 
-               WARN_ON(qc->err_mask);
+               WARN_ON(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM));
 
                ap->hsm_task_state = HSM_ST_IDLE;
 
@@ -1222,7 +1222,7 @@ fsm_start:
                /* make sure qc->err_mask is available to
                 * know what's wrong and recover
                 */
-               WARN_ON(qc->err_mask == 0);
+               WARN_ON(!(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM)));
 
                ap->hsm_task_state = HSM_ST_IDLE;
 
index 4aeeabb10a478c26cdf094d12ff7bd72cd14ac65..ae2cfd95d43ef7591b1b6ead5b4497080ec5876e 100644 (file)
@@ -101,7 +101,6 @@ extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
                              unsigned int readid_flags);
 extern int ata_dev_configure(struct ata_device *dev);
 extern int sata_down_spd_limit(struct ata_link *link);
-extern int sata_set_spd_needed(struct ata_link *link);
 extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
 extern void ata_sg_clean(struct ata_queued_cmd *qc);
 extern void ata_qc_free(struct ata_queued_cmd *qc);
index 3e8651d78952c6c1bd31b066fe94037685d4716e..5e104385d6a374336d529dad852087e19df78770 100644 (file)
@@ -381,6 +381,9 @@ static int __exit pata_at32_remove(struct platform_device *pdev)
        return 0;
 }
 
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:at32_ide");
+
 static struct platform_driver pata_at32_driver = {
        .remove        = __exit_p(pata_at32_remove),
        .driver        = {
index 0a5ad98635b1c0005bd3847055b241ff30d80409..a75de0684c15cff77f21728fd36af031e7867b2c 100644 (file)
@@ -1417,7 +1417,7 @@ static int bfin_reset_controller(struct ata_host *host)
        count = 10000000;
        do {
                status = read_atapi_register(base, ATA_REG_STATUS);
-       } while (count-- && (status & ATA_BUSY));
+       } while (--count && (status & ATA_BUSY));
 
        /* Enable only ATAPI Device interrupt */
        ATAPI_SET_INT_MASK(base, 1);
@@ -1601,3 +1601,4 @@ MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
 MODULE_DESCRIPTION("PATA driver for blackfin 54x ATAPI controller");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
+MODULE_ALIAS("platform:" DRV_NAME);
index 8a175f23b907d7a4cb022617632dd387dd209d7a..de8d186f5abf01ba6c2e6dccfd0477e0e9fb4619 100644 (file)
@@ -221,6 +221,7 @@ MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
 MODULE_DESCRIPTION("low-level driver for ixp4xx Compact Flash PATA");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
+MODULE_ALIAS("platform:" DRV_NAME);
 
 module_init(ixp4xx_pata_init);
 module_exit(ixp4xx_pata_exit);
index 6527c56c34a3fd84537385c39a4c85a91b1f3330..8f65ad61b8af372f8e6263fb55ec85c79df5f801 100644 (file)
@@ -277,3 +277,4 @@ MODULE_AUTHOR("Paul Mundt");
 MODULE_DESCRIPTION("low-level driver for platform device ATA");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
+MODULE_ALIAS("platform:" DRV_NAME);
index 800ae4601f44b7eec6a0b7b20e55bc86a5c01707..4345174aaeecc7fd8038bf45dc280aa73830701e 100644 (file)
@@ -239,6 +239,9 @@ static __devexit int rb500_pata_driver_remove(struct platform_device *pdev)
        return 0;
 }
 
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:" DRV_NAME);
+
 static struct platform_driver rb500_pata_platform_driver = {
        .probe          = rb500_pata_driver_probe,
        .remove         = __devexit_p(rb500_pata_driver_remove),
index d52ce1188327bf2a9f89b21e9335c0442fb5f748..26a6337195b3681587d2025a9a97519f01bf8ca1 100644 (file)
  */
 
 /*
-  sata_mv TODO list:
-
-  1) Needs a full errata audit for all chipsets.  I implemented most
-  of the errata workarounds found in the Marvell vendor driver, but
-  I distinctly remember a couple workarounds (one related to PCI-X)
-  are still needed.
-
-  2) Improve/fix IRQ and error handling sequences.
-
-  3) ATAPI support (Marvell claims the 60xx/70xx chips can do it).
-
-  4) Think about TCQ support here, and for libata in general
-  with controllers that suppport it via host-queuing hardware
-  (a software-only implementation could be a nightmare).
-
-  5) Investigate problems with PCI Message Signalled Interrupts (MSI).
-
-  6) Cache frequently-accessed registers in mv_port_priv to reduce overhead.
-
-  7) Fix/reenable hot plug/unplug (should happen as a side-effect of (2) above).
-
-  8) Develop a low-power-consumption strategy, and implement it.
-
-  9) [Experiment, low priority] See if ATAPI can be supported using
-  "unknown FIS" or "vendor-specific FIS" support, or something creative
-  like that.
-
-  10) [Experiment, low priority] Investigate interrupt coalescing.
-  Quite often, especially with PCI Message Signalled Interrupts (MSI),
-  the overhead reduced by interrupt mitigation is quite often not
-  worth the latency cost.
-
-  11) [Experiment, Marvell value added] Is it possible to use target
-  mode to cross-connect two Linux boxes with Marvell cards?  If so,
-  creating LibATA target mode support would be very interesting.
-
-  Target mode, for those without docs, is the ability to directly
-  connect two SATA controllers.
-
-*/
+ * sata_mv TODO list:
+ *
+ * --> Errata workaround for NCQ device errors.
+ *
+ * --> More errata workarounds for PCI-X.
+ *
+ * --> Complete a full errata audit for all chipsets to identify others.
+ *
+ * --> ATAPI support (Marvell claims the 60xx/70xx chips can do it).
+ *
+ * --> Investigate problems with PCI Message Signalled Interrupts (MSI).
+ *
+ * --> Cache frequently-accessed registers in mv_port_priv to reduce overhead.
+ *
+ * --> Develop a low-power-consumption strategy, and implement it.
+ *
+ * --> [Experiment, low priority] Investigate interrupt coalescing.
+ *       Quite often, especially with PCI Message Signalled Interrupts (MSI),
+ *       the overhead reduced by interrupt mitigation is quite often not
+ *       worth the latency cost.
+ *
+ * --> [Experiment, Marvell value added] Is it possible to use target
+ *       mode to cross-connect two Linux boxes with Marvell cards?  If so,
+ *       creating LibATA target mode support would be very interesting.
+ *
+ *       Target mode, for those without docs, is the ability to directly
+ *       connect two SATA ports.
+ */
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -124,11 +112,11 @@ enum {
        MV_MAX_SG_CT            = 256,
        MV_SG_TBL_SZ            = (16 * MV_MAX_SG_CT),
 
-       MV_PORTS_PER_HC         = 4,
-       /* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
+       /* Determine hc from 0-7 port: hc = port >> MV_PORT_HC_SHIFT */
        MV_PORT_HC_SHIFT        = 2,
-       /* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
-       MV_PORT_MASK            = 3,
+       MV_PORTS_PER_HC         = (1 << MV_PORT_HC_SHIFT), /* 4 */
+       /* Determine hc port from 0-7 port: hardport = port & MV_PORT_MASK */
+       MV_PORT_MASK            = (MV_PORTS_PER_HC - 1),   /* 3 */
 
        /* Host Flags */
        MV_FLAG_DUAL_HC         = (1 << 30),  /* two SATA Host Controllers */
@@ -188,8 +176,8 @@ enum {
        HC_MAIN_IRQ_MASK_OFS    = 0x1d64,
        HC_SOC_MAIN_IRQ_CAUSE_OFS = 0x20020,
        HC_SOC_MAIN_IRQ_MASK_OFS = 0x20024,
-       PORT0_ERR               = (1 << 0),     /* shift by port # */
-       PORT0_DONE              = (1 << 1),     /* shift by port # */
+       ERR_IRQ                 = (1 << 0),     /* shift by port # */
+       DONE_IRQ                = (1 << 1),     /* shift by port # */
        HC0_IRQ_PEND            = 0x1ff,        /* bits 0-8 = HC0's ports */
        HC_SHIFT                = 9,            /* bits 9-17 = HC1's ports */
        PCI_ERR                 = (1 << 18),
@@ -205,6 +193,7 @@ enum {
        HC_MAIN_RSVD_5          = (0x1fff << 19), /* bits 31-19 */
        HC_MAIN_RSVD_SOC        = (0x3fffffb << 6),     /* bits 31-9, 7-6 */
        HC_MAIN_MASKED_IRQS     = (TRAN_LO_DONE | TRAN_HI_DONE |
+                                  PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
                                   PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
                                   HC_MAIN_RSVD),
        HC_MAIN_MASKED_IRQS_5   = (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
@@ -215,8 +204,8 @@ enum {
        HC_CFG_OFS              = 0,
 
        HC_IRQ_CAUSE_OFS        = 0x14,
-       CRPB_DMA_DONE           = (1 << 0),     /* shift by port # */
-       HC_IRQ_COAL             = (1 << 4),     /* IRQ coalescing */
+       DMA_IRQ                 = (1 << 0),     /* shift by port # */
+       HC_COAL_IRQ             = (1 << 4),     /* IRQ coalescing */
        DEV_IRQ                 = (1 << 8),     /* shift by port # */
 
        /* Shadow block registers */
@@ -299,9 +288,7 @@ enum {
        EDMA_ERR_IRQ_TRANSIENT  = EDMA_ERR_LNK_CTRL_RX_0 |
                                  EDMA_ERR_LNK_CTRL_RX_1 |
                                  EDMA_ERR_LNK_CTRL_RX_3 |
-                                 EDMA_ERR_LNK_CTRL_TX |
-                                /* temporary, until we fix hotplug: */
-                                (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON),
+                                 EDMA_ERR_LNK_CTRL_TX,
 
        EDMA_EH_FREEZE          = EDMA_ERR_D_PAR |
                                  EDMA_ERR_PRD_PAR |
@@ -349,6 +336,8 @@ enum {
        EDMA_IORDY_TMOUT        = 0x34,
        EDMA_ARB_CFG            = 0x38,
 
+       GEN_II_NCQ_MAX_SECTORS  = 256,          /* max sects/io on Gen2 w/NCQ */
+
        /* Host private flags (hp_flags) */
        MV_HP_FLAG_MSI          = (1 << 0),
        MV_HP_ERRATA_50XXB0     = (1 << 1),
@@ -722,11 +711,6 @@ static inline void writelfl(unsigned long data, void __iomem *addr)
        (void) readl(addr);     /* flush to avoid PCI posted write */
 }
 
-static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
-{
-       return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
-}
-
 static inline unsigned int mv_hc_from_port(unsigned int port)
 {
        return port >> MV_PORT_HC_SHIFT;
@@ -737,6 +721,29 @@ static inline unsigned int mv_hardport_from_port(unsigned int port)
        return port & MV_PORT_MASK;
 }
 
+/*
+ * Consolidate some rather tricky bit shift calculations.
+ * This is hot-path stuff, so not a function.
+ * Simple code, with two return values, so macro rather than inline.
+ *
+ * port is the sole input, in range 0..7.
+ * shift is one output, for use with the main_cause and main_mask registers.
+ * hardport is the other output, in range 0..3
+ *
+ * Note that port and hardport may be the same variable in some cases.
+ */
+#define MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport)   \
+{                                                              \
+       shift    = mv_hc_from_port(port) * HC_SHIFT;            \
+       hardport = mv_hardport_from_port(port);                 \
+       shift   += hardport * 2;                                \
+}
+
+static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
+{
+       return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
+}
+
 static inline void __iomem *mv_hc_base_from_port(void __iomem *base,
                                                 unsigned int port)
 {
@@ -783,7 +790,8 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
        /*
         * initialize request queue
         */
-       index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
+       pp->req_idx &= MV_MAX_Q_DEPTH_MASK;     /* paranoia */
+       index = pp->req_idx << 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);
@@ -799,7 +807,8 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
        /*
         * initialize response queue
         */
-       index = (pp->resp_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_RSP_Q_PTR_SHIFT;
+       pp->resp_idx &= MV_MAX_Q_DEPTH_MASK;    /* paranoia */
+       index = pp->resp_idx << 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);
@@ -837,9 +846,9 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
        }
        if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
                struct mv_host_priv *hpriv = ap->host->private_data;
-               int hard_port = mv_hardport_from_port(ap->port_no);
+               int hardport = mv_hardport_from_port(ap->port_no);
                void __iomem *hc_mmio = mv_hc_base_from_port(
-                                       mv_host_base(ap->host), hard_port);
+                                       mv_host_base(ap->host), hardport);
                u32 hc_irq_cause, ipending;
 
                /* clear EDMA event indicators, if any */
@@ -847,8 +856,7 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
 
                /* clear EDMA interrupt indicator, if any */
                hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
-               ipending = (DEV_IRQ << hard_port) |
-                               (CRPB_DMA_DONE << hard_port);
+               ipending = (DEV_IRQ | DMA_IRQ) << hardport;
                if (hc_irq_cause & ipending) {
                        writelfl(hc_irq_cause & ~ipending,
                                 hc_mmio + HC_IRQ_CAUSE_OFS);
@@ -864,7 +872,6 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
                writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS);
                pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
        }
-       WARN_ON(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)));
 }
 
 /**
@@ -1036,10 +1043,16 @@ static void mv6_dev_config(struct ata_device *adev)
         * See mv_qc_prep() for more info.
         */
        if (adev->flags & ATA_DFLAG_NCQ) {
-               if (sata_pmp_attached(adev->link->ap))
+               if (sata_pmp_attached(adev->link->ap)) {
                        adev->flags &= ~ATA_DFLAG_NCQ;
-               else if (adev->max_sectors > ATA_MAX_SECTORS)
-                       adev->max_sectors = ATA_MAX_SECTORS;
+                       ata_dev_printk(adev, KERN_INFO,
+                               "NCQ disabled for command-based switching\n");
+               } else if (adev->max_sectors > GEN_II_NCQ_MAX_SECTORS) {
+                       adev->max_sectors = GEN_II_NCQ_MAX_SECTORS;
+                       ata_dev_printk(adev, KERN_INFO,
+                               "max_sectors limited to %u for NCQ\n",
+                               adev->max_sectors);
+               }
        }
 }
 
@@ -1287,7 +1300,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
        flags |= (qc->dev->link->pmp & 0xf) << CRQB_PMP_SHIFT;
 
        /* get current queue index from software */
-       in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
+       in_index = pp->req_idx;
 
        pp->crqb[in_index].sg_addr =
                cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
@@ -1379,7 +1392,7 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
        flags |= (qc->dev->link->pmp & 0xf) << CRQB_PMP_SHIFT;
 
        /* get current queue index from software */
-       in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
+       in_index = pp->req_idx;
 
        crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
        crqb->addr = cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
@@ -1446,9 +1459,8 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
 
        mv_start_dma(ap, port_mmio, pp, qc->tf.protocol);
 
-       pp->req_idx++;
-
-       in_index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
+       pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK;
+       in_index = pp->req_idx << EDMA_REQ_Q_PTR_SHIFT;
 
        /* and write the request in pointer to kick the EDMA to life */
        writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
@@ -1457,16 +1469,51 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
        return 0;
 }
 
+static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap)
+{
+       struct mv_port_priv *pp = ap->private_data;
+       struct ata_queued_cmd *qc;
+
+       if (pp->pp_flags & MV_PP_FLAG_NCQ_EN)
+               return NULL;
+       qc = ata_qc_from_tag(ap, ap->link.active_tag);
+       if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
+               qc = NULL;
+       return qc;
+}
+
+static void mv_unexpected_intr(struct ata_port *ap)
+{
+       struct mv_port_priv *pp = ap->private_data;
+       struct ata_eh_info *ehi = &ap->link.eh_info;
+       char *when = "";
+
+       /*
+        * We got a device interrupt from something that
+        * was supposed to be using EDMA or polling.
+        */
+       ata_ehi_clear_desc(ehi);
+       if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
+               when = " while EDMA enabled";
+       } else {
+               struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag);
+               if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
+                       when = " while polling";
+       }
+       ata_ehi_push_desc(ehi, "unexpected device interrupt%s", when);
+       ehi->err_mask |= AC_ERR_OTHER;
+       ehi->action   |= ATA_EH_RESET;
+       ata_port_freeze(ap);
+}
+
 /**
  *      mv_err_intr - Handle error interrupts on the port
  *      @ap: ATA channel to manipulate
- *      @reset_allowed: bool: 0 == don't trigger from reset here
+ *      @qc: affected command (non-NCQ), or NULL
  *
- *      In most cases, just clear the interrupt and move on.  However,
- *      some cases require an eDMA reset, which also performs a COMRESET.
- *      The SERR case requires a clear of pending errors in the SATA
- *      SERROR register.  Finally, if the port disabled DMA,
- *      update our cached copy to match.
+ *      Most cases require a full reset of the chip's state machine,
+ *      which also performs a COMRESET.
+ *      Also, if the port disabled DMA, update our cached copy to match.
  *
  *      LOCKING:
  *      Inherited from caller.
@@ -1477,28 +1524,24 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
        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->link.eh_info;
 
        ata_ehi_clear_desc(ehi);
 
-       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->link, SCR_ERROR, &serr);
-               sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
-       }
-
+       /*
+        * Read and clear the err_cause bits.  This won't actually
+        * clear for some errors (eg. SError), but we will be doing
+        * a hard reset in those cases regardless, which *will* clear it.
+        */
        edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+       writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
 
-       ata_ehi_push_desc(ehi, "edma_err 0x%08x", edma_err_cause);
+       ata_ehi_push_desc(ehi, "edma_err_cause=%08x", edma_err_cause);
 
        /*
-        * all generations share these EDMA error cause bits
+        * 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 |
@@ -1515,34 +1558,36 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
                action |= ATA_EH_RESET;
        }
 
+       /*
+        * Gen-I has a different SELF_DIS bit,
+        * different FREEZE bits, and no SERR bit:
+        */
        if (IS_GEN_I(hpriv)) {
                eh_freeze_mask = EDMA_EH_FREEZE_5;
-
                if (edma_err_cause & EDMA_ERR_SELF_DIS_5) {
-                       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) {
-                       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->link, SCR_ERROR, &serr);
-                       sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
-                       err_mask = AC_ERR_ATA_BUS;
+                       /*
+                        * Ensure that we read our own SCR, not a pmp link SCR:
+                        */
+                       ap->ops->scr_read(ap, SCR_ERROR, &serr);
+                       /*
+                        * Don't clear SError here; leave it for libata-eh:
+                        */
+                       ata_ehi_push_desc(ehi, "SError=%08x", serr);
+                       err_mask |= AC_ERR_ATA_BUS;
                        action |= ATA_EH_RESET;
                }
        }
 
-       /* Clear EDMA now that SERR cleanup done */
-       writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
-
        if (!err_mask) {
                err_mask = AC_ERR_OTHER;
                action |= ATA_EH_RESET;
@@ -1562,178 +1607,151 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
                ata_port_abort(ap);
 }
 
-static void mv_intr_pio(struct ata_port *ap)
+static void mv_process_crpb_response(struct ata_port *ap,
+               struct mv_crpb *response, unsigned int tag, int ncq_enabled)
 {
-       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;
+       struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
 
-       /* get active ATA command */
-       qc = ata_qc_from_tag(ap, ap->link.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);
+       if (qc) {
+               u8 ata_status;
+               u16 edma_status = le16_to_cpu(response->flags);
+               /*
+                * edma_status from a response queue entry:
+                *   LSB is from EDMA_ERR_IRQ_CAUSE_OFS (non-NCQ only).
+                *   MSB is saved ATA status from command completion.
+                */
+               if (!ncq_enabled) {
+                       u8 err_cause = edma_status & 0xff & ~EDMA_ERR_DEV;
+                       if (err_cause) {
+                               /*
+                                * Error will be seen/handled by mv_err_intr().
+                                * So do nothing at all here.
+                                */
+                               return;
+                       }
+               }
+               ata_status = edma_status >> CRPB_FLAG_STATUS_SHIFT;
+               qc->err_mask |= ac_err_mask(ata_status);
+               ata_qc_complete(qc);
+       } else {
+               ata_port_printk(ap, KERN_ERR, "%s: no qc for tag=%d\n",
+                               __func__, tag);
+       }
 }
 
-static void mv_intr_edma(struct ata_port *ap)
+static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp)
 {
        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;
+       u32 in_index;
        bool work_done = false;
+       int ncq_enabled = (pp->pp_flags & MV_PP_FLAG_NCQ_EN);
 
-       /* get h/w response queue pointer */
+       /* Get the hardware queue position index */
        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;
+       /* Process new responses from since the last time we looked */
+       while (in_index != pp->resp_idx) {
                unsigned int tag;
+               struct mv_crpb *response = &pp->crpb[pp->resp_idx];
 
-               /* 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;
+               pp->resp_idx = (pp->resp_idx + 1) & MV_MAX_Q_DEPTH_MASK;
 
-               /* 50xx: get active ATA command */
-               if (IS_GEN_I(hpriv))
+               if (IS_GEN_I(hpriv)) {
+                       /* 50xx: no NCQ, only one command active at a time */
                        tag = ap->link.active_tag;
-
-               /* Gen II/IIE: get active ATA command via tag, to enable
-                * support for queueing.  this works transparently for
-                * queued and non-queued modes.
-                */
-               else
-                       tag = le16_to_cpu(pp->crpb[out_index].id) & 0x1f;
-
-               qc = ata_qc_from_tag(ap, tag);
-
-               /* For non-NCQ mode, the lower 8 bits of status
-                * are from EDMA_ERR_IRQ_CAUSE_OFS,
-                * which should be zero if all went well.
-                */
-               status = le16_to_cpu(pp->crpb[out_index].flags);
-               if ((status & 0xff) && !(pp->pp_flags & MV_PP_FLAG_NCQ_EN)) {
-                       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);
+               } else {
+                       /* Gen II/IIE: get command tag from CRPB entry */
+                       tag = le16_to_cpu(response->id) & 0x1f;
                }
-
-               /* advance software response queue pointer, to
-                * indicate (after the loop completes) to hardware
-                * that we have consumed a response queue entry.
-                */
+               mv_process_crpb_response(ap, response, tag, ncq_enabled);
                work_done = true;
-               pp->resp_idx++;
        }
 
+       /* Update the software queue position index in hardware */
        if (work_done)
                writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
-                        (out_index << EDMA_RSP_Q_PTR_SHIFT),
+                        (pp->resp_idx << EDMA_RSP_Q_PTR_SHIFT),
                         port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
 }
 
 /**
  *      mv_host_intr - Handle all interrupts on the given host controller
  *      @host: host specific structure
- *      @relevant: port error bits relevant to this host controller
- *      @hc: which host controller we're to look at
- *
- *      Read then write clear the HC interrupt status then walk each
- *      port connected to the HC and see if it needs servicing.  Port
- *      success ints are reported in the HC interrupt status reg, the
- *      port error ints are reported in the higher level main
- *      interrupt status register and thus are passed in via the
- *      'relevant' argument.
+ *      @main_cause: Main interrupt cause register for the chip.
  *
  *      LOCKING:
  *      Inherited from caller.
  */
-static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
+static int mv_host_intr(struct ata_host *host, u32 main_cause)
 {
        struct mv_host_priv *hpriv = host->private_data;
-       void __iomem *mmio = hpriv->base;
-       void __iomem *hc_mmio = mv_hc_base(mmio, hc);
-       u32 hc_irq_cause;
-       int port, port0, last_port;
+       void __iomem *mmio = hpriv->base, *hc_mmio = NULL;
+       u32 hc_irq_cause = 0;
+       unsigned int handled = 0, port;
 
-       if (hc == 0)
-               port0 = 0;
-       else
-               port0 = MV_PORTS_PER_HC;
-
-       if (HAS_PCI(host))
-               last_port = port0 + MV_PORTS_PER_HC;
-       else
-               last_port = port0 + hpriv->n_ports;
-       /* 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)
-               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 < last_port; port++) {
+       for (port = 0; port < hpriv->n_ports; port++) {
                struct ata_port *ap = host->ports[port];
                struct mv_port_priv *pp;
-               int have_err_bits, hard_port, shift;
-
-               if ((!ap) || (ap->flags & ATA_FLAG_DISABLED))
+               unsigned int shift, hardport, port_cause;
+               /*
+                * When we move to the second hc, flag our cached
+                * copies of hc_mmio (and hc_irq_cause) as invalid again.
+                */
+               if (port == MV_PORTS_PER_HC)
+                       hc_mmio = NULL;
+               /*
+                * Do nothing if port is not interrupting or is disabled:
+                */
+               MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
+               port_cause = (main_cause >> shift) & (DONE_IRQ | ERR_IRQ);
+               if (!port_cause || !ap || (ap->flags & ATA_FLAG_DISABLED))
                        continue;
-
+               /*
+                * Each hc within the host has its own hc_irq_cause register.
+                * We defer reading it until we know we need it, right now:
+                *
+                * FIXME later: we don't really need to read this register
+                * (some logic changes required below if we go that way),
+                * because it doesn't tell us anything new.  But we do need
+                * to write to it, outside the top of this loop,
+                * to reset the interrupt triggers for next time.
+                */
+               if (!hc_mmio) {
+                       hc_mmio = mv_hc_base_from_port(mmio, port);
+                       hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
+                       writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
+                       handled = 1;
+               }
+               /*
+                * Process completed CRPB response(s) before other events.
+                */
                pp = ap->private_data;
-
-               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->link.active_tag);
-                       if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
-                               continue;
-
-                       mv_err_intr(ap, qc);
-                       continue;
+               if (hc_irq_cause & (DMA_IRQ << hardport)) {
+                       if (pp->pp_flags & MV_PP_FLAG_EDMA_EN)
+                               mv_process_crpb_entries(ap, pp);
                }
-
-               hard_port = mv_hardport_from_port(port); /* range 0..3 */
-
-               if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
-                       if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause)
-                               mv_intr_edma(ap);
-               } else {
-                       if ((DEV_IRQ << hard_port) & hc_irq_cause)
-                               mv_intr_pio(ap);
+               /*
+                * Handle chip-reported errors, or continue on to handle PIO.
+                */
+               if (unlikely(port_cause & ERR_IRQ)) {
+                       mv_err_intr(ap, mv_get_active_qc(ap));
+               } else if (hc_irq_cause & (DEV_IRQ << hardport)) {
+                       if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
+                               struct ata_queued_cmd *qc = mv_get_active_qc(ap);
+                               if (qc) {
+                                       ata_sff_host_intr(ap, qc);
+                                       continue;
+                               }
+                       }
+                       mv_unexpected_intr(ap);
                }
        }
-       VPRINTK("EXIT\n");
+       return handled;
 }
 
-static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
+static int mv_pci_error(struct ata_host *host, void __iomem *mmio)
 {
        struct mv_host_priv *hpriv = host->private_data;
        struct ata_port *ap;
@@ -1771,6 +1789,7 @@ static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
                        ata_port_freeze(ap);
                }
        }
+       return 1;       /* handled */
 }
 
 /**
@@ -1791,41 +1810,23 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
 {
        struct ata_host *host = dev_instance;
        struct mv_host_priv *hpriv = host->private_data;
-       unsigned int hc, handled = 0, n_hcs;
-       void __iomem *mmio = hpriv->base;
-       u32 irq_stat, irq_mask;
+       unsigned int handled = 0;
+       u32 main_cause, main_mask;
 
-       /* Note to self: &host->lock == &ap->host->lock == ap->lock */
        spin_lock(&host->lock);
-
-       irq_stat = readl(hpriv->main_cause_reg_addr);
-       irq_mask = readl(hpriv->main_mask_reg_addr);
-
-       /* check the cases where we either have nothing pending or have read
-        * a bogus register value which can indicate HW removal or PCI fault
+       main_cause = readl(hpriv->main_cause_reg_addr);
+       main_mask  = readl(hpriv->main_mask_reg_addr);
+       /*
+        * Deal with cases where we either have nothing pending, or have read
+        * a bogus register value which can indicate HW removal or PCI fault.
         */
-       if (!(irq_stat & irq_mask) || (0xffffffffU == irq_stat))
-               goto out_unlock;
-
-       n_hcs = mv_get_hc_count(host->ports[0]->flags);
-
-       if (unlikely((irq_stat & PCI_ERR) && HAS_PCI(host))) {
-               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 = 1;
-               }
+       if ((main_cause & main_mask) && (main_cause != 0xffffffffU)) {
+               if (unlikely((main_cause & PCI_ERR) && HAS_PCI(host)))
+                       handled = mv_pci_error(host, hpriv->base);
+               else
+                       handled = mv_host_intr(host, main_cause);
        }
-
-out_unlock:
        spin_unlock(&host->lock);
-
        return IRQ_RETVAL(handled);
 }
 
@@ -2109,13 +2110,6 @@ static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
                printk(KERN_ERR DRV_NAME ": can't clear global reset\n");
                rc = 1;
        }
-       /*
-        * Temporary: wait 3 seconds before port-probing can happen,
-        * so that we don't miss finding sleepy SilXXXX port-multipliers.
-        * This can go away once hotplug is fully/correctly implemented.
-        */
-       if (rc == 0)
-               msleep(3000);
 done:
        return rc;
 }
@@ -2409,55 +2403,44 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class,
 static void mv_eh_freeze(struct ata_port *ap)
 {
        struct mv_host_priv *hpriv = ap->host->private_data;
-       unsigned int hc = (ap->port_no > 3) ? 1 : 0;
-       u32 tmp, mask;
-       unsigned int shift;
+       unsigned int shift, hardport, port = ap->port_no;
+       u32 main_mask;
 
        /* FIXME: handle coalescing completion events properly */
 
-       shift = ap->port_no * 2;
-       if (hc > 0)
-               shift++;
-
-       mask = 0x3 << shift;
+       mv_stop_edma(ap);
+       MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
 
        /* disable assertion of portN err, done events */
-       tmp = readl(hpriv->main_mask_reg_addr);
-       writelfl(tmp & ~mask, hpriv->main_mask_reg_addr);
+       main_mask = readl(hpriv->main_mask_reg_addr);
+       main_mask &= ~((DONE_IRQ | ERR_IRQ) << shift);
+       writelfl(main_mask, hpriv->main_mask_reg_addr);
 }
 
 static void mv_eh_thaw(struct ata_port *ap)
 {
        struct mv_host_priv *hpriv = ap->host->private_data;
-       void __iomem *mmio = hpriv->base;
-       unsigned int hc = (ap->port_no > 3) ? 1 : 0;
-       void __iomem *hc_mmio = mv_hc_base(mmio, hc);
+       unsigned int shift, hardport, port = ap->port_no;
+       void __iomem *hc_mmio = mv_hc_base_from_port(hpriv->base, port);
        void __iomem *port_mmio = mv_ap_base(ap);
-       u32 tmp, mask, hc_irq_cause;
-       unsigned int shift, hc_port_no = ap->port_no;
+       u32 main_mask, hc_irq_cause;
 
        /* FIXME: handle coalescing completion events properly */
 
-       shift = ap->port_no * 2;
-       if (hc > 0) {
-               shift++;
-               hc_port_no -= 4;
-       }
-
-       mask = 0x3 << shift;
+       MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
 
        /* 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);
+       hc_irq_cause &= ~((DEV_IRQ | DMA_IRQ) << hardport);
+       writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
 
        /* enable assertion of portN err, done events */
-       tmp = readl(hpriv->main_mask_reg_addr);
-       writelfl(tmp | mask, hpriv->main_mask_reg_addr);
+       main_mask = readl(hpriv->main_mask_reg_addr);
+       main_mask |= ((DONE_IRQ | ERR_IRQ) << shift);
+       writelfl(main_mask, hpriv->main_mask_reg_addr);
 }
 
 /**
@@ -2668,19 +2651,17 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
 
        rc = mv_chip_id(host, board_idx);
        if (rc)
-       goto done;
+               goto done;
 
        if (HAS_PCI(host)) {
-               hpriv->main_cause_reg_addr = hpriv->base +
-                 HC_MAIN_IRQ_CAUSE_OFS;
-               hpriv->main_mask_reg_addr = hpriv->base + HC_MAIN_IRQ_MASK_OFS;
+               hpriv->main_cause_reg_addr = mmio + HC_MAIN_IRQ_CAUSE_OFS;
+               hpriv->main_mask_reg_addr  = mmio + HC_MAIN_IRQ_MASK_OFS;
        } else {
-               hpriv->main_cause_reg_addr = hpriv->base +
-                 HC_SOC_MAIN_IRQ_CAUSE_OFS;
-               hpriv->main_mask_reg_addr = hpriv->base +
-                 HC_SOC_MAIN_IRQ_MASK_OFS;
+               hpriv->main_cause_reg_addr = mmio + HC_SOC_MAIN_IRQ_CAUSE_OFS;
+               hpriv->main_mask_reg_addr  = mmio + HC_SOC_MAIN_IRQ_MASK_OFS;
        }
-       /* global interrupt mask */
+
+       /* global interrupt mask: 0 == mask everything */
        writel(0, hpriv->main_mask_reg_addr);
 
        n_hc = mv_get_hc_count(host->ports[0]->flags);
index 109b07495721ebf684710d50949f00db78e63f8d..858f70610edaa8370a6b79b2367147cf3d69dba9 100644 (file)
@@ -1591,13 +1591,16 @@ static void nv_mcp55_thaw(struct ata_port *ap)
 static int nv_hardreset(struct ata_link *link, unsigned int *class,
                        unsigned long deadline)
 {
-       unsigned int dummy;
+       int rc;
 
        /* SATA hardreset fails to retrieve proper device signature on
-        * some controllers.  Don't classify on hardreset.  For more
-        * info, see http://bugzilla.kernel.org/show_bug.cgi?id=3352
+        * some controllers.  Request follow up SRST.  For more info,
+        * see http://bugzilla.kernel.org/show_bug.cgi?id=3352
         */
-       return sata_sff_hardreset(link, &dummy, deadline);
+       rc = sata_sff_hardreset(link, class, deadline);
+       if (rc)
+               return rc;
+       return -EAGAIN;
 }
 
 static void nv_adma_error_handler(struct ata_port *ap)
index 6b8e45ba32e8e89e91ef67966e8a8593842340c6..1010b3069bd5164bb9ded003df2d41371c4f91c9 100644 (file)
@@ -142,7 +142,7 @@ static u32 sis_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
        u8 pmr;
 
        if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
-               return 0xffffffff;
+               return -EINVAL;
 
        pci_read_config_byte(pdev, SIS_PMR, &pmr);
 
@@ -158,14 +158,14 @@ static u32 sis_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
        return 0;
 }
 
-static void sis_scr_cfg_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+static int sis_scr_cfg_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg);
        u8 pmr;
 
        if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
-               return;
+               return -EINVAL;
 
        pci_read_config_byte(pdev, SIS_PMR, &pmr);
 
@@ -174,6 +174,8 @@ static void sis_scr_cfg_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
        if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
            (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
                pci_write_config_dword(pdev, cfg_addr+0x10, val);
+
+       return 0;
 }
 
 static int sis_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
@@ -211,14 +213,14 @@ static int sis_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
        pci_read_config_byte(pdev, SIS_PMR, &pmr);
 
        if (ap->flags & SIS_FLAG_CFGSCR)
-               sis_scr_cfg_write(ap, sc_reg, val);
+               return sis_scr_cfg_write(ap, sc_reg, val);
        else {
                iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4));
                if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
                    (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
                        iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4)+0x10);
+               return 0;
        }
-       return 0;
 }
 
 static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
index 9c6f3f99208d073ad9cbfd3ff61e69a0e3dc0a02..d771da816d95d708cff253e41e3a6ab05cd9d930 100644 (file)
@@ -47,6 +47,7 @@
 
 #include <xen/interface/grant_table.h>
 #include <xen/interface/io/blkif.h>
+#include <xen/interface/io/protocols.h>
 
 #include <asm/xen/hypervisor.h>
 
@@ -74,7 +75,6 @@ static struct block_device_operations xlvbd_block_fops;
 struct blkfront_info
 {
        struct xenbus_device *xbdev;
-       dev_t dev;
        struct gendisk *gd;
        int vdevice;
        blkif_vdev_t handle;
@@ -88,6 +88,7 @@ struct blkfront_info
        struct blk_shadow shadow[BLK_RING_SIZE];
        unsigned long shadow_free;
        int feature_barrier;
+       int is_ready;
 
        /**
         * The number of people holding this device open.  We won't allow a
@@ -614,6 +615,12 @@ again:
                message = "writing event-channel";
                goto abort_transaction;
        }
+       err = xenbus_printf(xbt, dev->nodename, "protocol", "%s",
+                           XEN_IO_PROTO_ABI_NATIVE);
+       if (err) {
+               message = "writing protocol";
+               goto abort_transaction;
+       }
 
        err = xenbus_transaction_end(xbt, 0);
        if (err) {
@@ -833,6 +840,8 @@ static void blkfront_connect(struct blkfront_info *info)
        spin_unlock_irq(&blkif_io_lock);
 
        add_disk(info->gd);
+
+       info->is_ready = 1;
 }
 
 /**
@@ -896,7 +905,7 @@ static void backend_changed(struct xenbus_device *dev,
                break;
 
        case XenbusStateClosing:
-               bd = bdget(info->dev);
+               bd = bdget_disk(info->gd, 0);
                if (bd == NULL)
                        xenbus_dev_fatal(dev, -ENODEV, "bdget failed");
 
@@ -925,6 +934,13 @@ static int blkfront_remove(struct xenbus_device *dev)
        return 0;
 }
 
+static int blkfront_is_ready(struct xenbus_device *dev)
+{
+       struct blkfront_info *info = dev->dev.driver_data;
+
+       return info->is_ready;
+}
+
 static int blkif_open(struct inode *inode, struct file *filep)
 {
        struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
@@ -971,6 +987,7 @@ static struct xenbus_driver blkfront = {
        .remove = blkfront_remove,
        .resume = blkfront_resume,
        .otherend_changed = backend_changed,
+       .is_ready = blkfront_is_ready,
 };
 
 static int __init xlblk_init(void)
@@ -998,3 +1015,5 @@ module_exit(xlblk_exit);
 MODULE_DESCRIPTION("Xen virtual block device frontend");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_BLOCKDEV_MAJOR(XENVBD_MAJOR);
+MODULE_ALIAS("xen:vbd");
+MODULE_ALIAS("xenblk");
index d28669992147556cb6107d5fe3f8de9bb4d4264a..96bdb9296b0758832214aad8393f37569d258916 100644 (file)
@@ -436,8 +436,9 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
           system controller may experience noise due to strong drive strengths
         */
        if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_7006) {
-               u8 cap_ptr=0;
                struct pci_dev *gfxcard=NULL;
+
+               cap_ptr = 0;
                while (!cap_ptr) {
                        gfxcard = pci_get_class(PCI_CLASS_DISPLAY_VGA<<8, gfxcard);
                        if (!gfxcard) {
index 55d7a82bd071a725a8813d888dabb77215de79be..857b26227d87d69b894f51609a5307fd68ea4bab 100644 (file)
@@ -967,7 +967,7 @@ int agpioc_chipset_flush_wrap(struct agp_file_private *priv)
        return 0;
 }
 
-static int agp_ioctl(struct inode *inode, struct file *file,
+static long agp_ioctl(struct file *file,
                     unsigned int cmd, unsigned long arg)
 {
        struct agp_file_private *curr_priv = file->private_data;
@@ -1058,7 +1058,7 @@ static const struct file_operations agp_fops =
        .llseek         = no_llseek,
        .read           = agp_read,
        .write          = agp_write,
-       .ioctl          = agp_ioctl,
+       .unlocked_ioctl = agp_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = compat_agp_ioctl,
 #endif
index 141f4dfa0a117cdd6639abab27424bc529fae053..b710426bab3ee3f7c726e0fbebad56acdabc32fc 100644 (file)
@@ -167,13 +167,6 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
                        page_base += ATI_PCIGART_PAGE_SIZE;
                }
        }
-
-       if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
-               dma_sync_single_for_device(&dev->pdev->dev,
-                                          bus_address,
-                                          max_pages * sizeof(u32),
-                                          PCI_DMA_TODEVICE);
-
        ret = 1;
 
 #if defined(__i386__) || defined(__x86_64__)
index 3a05c6d5ebe1f9306bca6a3e11740d54b9e6e5ef..6874f31ca8caa329da769f13960bc0f08ae58f01 100644 (file)
@@ -471,6 +471,7 @@ struct drm_irq_busid {
 enum drm_vblank_seq_type {
        _DRM_VBLANK_ABSOLUTE = 0x0,     /**< Wait for specific vblank sequence number */
        _DRM_VBLANK_RELATIVE = 0x1,     /**< Wait for given number of vblanks */
+       _DRM_VBLANK_FLIP = 0x8000000,   /**< Scheduled buffer swap should flip */
        _DRM_VBLANK_NEXTONMISS = 0x10000000,    /**< If missed, wait for next vblank */
        _DRM_VBLANK_SECONDARY = 0x20000000,     /**< Secondary display controller */
        _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
@@ -503,6 +504,21 @@ union drm_wait_vblank {
        struct drm_wait_vblank_reply reply;
 };
 
+enum drm_modeset_ctl_cmd {
+       _DRM_PRE_MODESET = 1,
+       _DRM_POST_MODESET = 2,
+};
+
+/**
+ * DRM_IOCTL_MODESET_CTL ioctl argument type
+ *
+ * \sa drmModesetCtl().
+ */
+struct drm_modeset_ctl {
+       unsigned long arg;
+       enum drm_modeset_ctl_cmd cmd;
+};
+
 /**
  * DRM_IOCTL_AGP_ENABLE ioctl argument type.
  *
@@ -587,6 +603,7 @@ struct drm_set_version {
 #define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, struct drm_client)
 #define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, struct drm_stats)
 #define DRM_IOCTL_SET_VERSION          DRM_IOWR(0x07, struct drm_set_version)
+#define DRM_IOCTL_MODESET_CTL           DRM_IOW(0x08, struct drm_modeset_ctl)
 
 #define DRM_IOCTL_SET_UNIQUE           DRM_IOW( 0x10, struct drm_unique)
 #define DRM_IOCTL_AUTH_MAGIC           DRM_IOW( 0x11, struct drm_auth)
index 6540948d517622ff3b20dbc39902cde5b656dd9b..ecee3547a13f2216d076c62708293b7ee168767d 100644 (file)
@@ -100,10 +100,8 @@ struct drm_device;
 #define DRIVER_HAVE_DMA    0x20
 #define DRIVER_HAVE_IRQ    0x40
 #define DRIVER_IRQ_SHARED  0x80
-#define DRIVER_IRQ_VBL     0x100
 #define DRIVER_DMA_QUEUE   0x200
 #define DRIVER_FB_DMA      0x400
-#define DRIVER_IRQ_VBL2    0x800
 
 /***********************************************************************/
 /** \name Begin the DRM... */
@@ -379,13 +377,12 @@ struct drm_buf_entry {
 struct drm_file {
        int authenticated;
        int master;
-       int minor;
        pid_t pid;
        uid_t uid;
        drm_magic_t magic;
        unsigned long ioctl_count;
        struct list_head lhead;
-       struct drm_head *head;
+       struct drm_minor *minor;
        int remove_auth_on_close;
        unsigned long lock_count;
        struct file *filp;
@@ -580,10 +577,52 @@ struct drm_driver {
        int (*context_dtor) (struct drm_device *dev, int context);
        int (*kernel_context_switch) (struct drm_device *dev, int old,
                                      int new);
-       void (*kernel_context_switch_unlock) (struct drm_device *dev);
-       int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence);
-       int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence);
-       int (*dri_library_name) (struct drm_device *dev, char *buf);
+       void (*kernel_context_switch_unlock) (struct drm_device * dev);
+       /**
+        * get_vblank_counter - get raw hardware vblank counter
+        * @dev: DRM device
+        * @crtc: counter to fetch
+        *
+        * Driver callback for fetching a raw hardware vblank counter
+        * for @crtc.  If a device doesn't have a hardware counter, the
+        * driver can simply return the value of drm_vblank_count and
+        * make the enable_vblank() and disable_vblank() hooks into no-ops,
+        * leaving interrupts enabled at all times.
+        *
+        * Wraparound handling and loss of events due to modesetting is dealt
+        * with in the DRM core code.
+        *
+        * RETURNS
+        * Raw vblank counter value.
+        */
+       u32 (*get_vblank_counter) (struct drm_device *dev, int crtc);
+
+       /**
+        * enable_vblank - enable vblank interrupt events
+        * @dev: DRM device
+        * @crtc: which irq to enable
+        *
+        * Enable vblank interrupts for @crtc.  If the device doesn't have
+        * a hardware vblank counter, this routine should be a no-op, since
+        * interrupts will have to stay on to keep the count accurate.
+        *
+        * RETURNS
+        * Zero on success, appropriate errno if the given @crtc's vblank
+        * interrupt cannot be enabled.
+        */
+       int (*enable_vblank) (struct drm_device *dev, int crtc);
+
+       /**
+        * disable_vblank - disable vblank interrupt events
+        * @dev: DRM device
+        * @crtc: which irq to enable
+        *
+        * Disable vblank interrupts for @crtc.  If the device doesn't have
+        * a hardware vblank counter, this routine should be a no-op, since
+        * interrupts will have to stay on to keep the count accurate.
+        */
+       void (*disable_vblank) (struct drm_device *dev, int crtc);
+       int (*dri_library_name) (struct drm_device *dev, char * buf);
 
        /**
         * Called by \c drm_device_is_agp.  Typically used to determine if a
@@ -602,7 +641,7 @@ struct drm_driver {
 
        irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
        void (*irq_preinstall) (struct drm_device *dev);
-       void (*irq_postinstall) (struct drm_device *dev);
+       int (*irq_postinstall) (struct drm_device *dev);
        void (*irq_uninstall) (struct drm_device *dev);
        void (*reclaim_buffers) (struct drm_device *dev,
                                 struct drm_file * file_priv);
@@ -630,16 +669,19 @@ struct drm_driver {
        struct pci_driver pci_driver;
 };
 
+#define DRM_MINOR_UNASSIGNED 0
+#define DRM_MINOR_LEGACY 1
+
 /**
- * DRM head structure. This structure represent a video head on a card
- * that may contain multiple heads. Embed one per head of these in the
- * private drm_device structure.
+ * DRM minor structure. This structure represents a drm minor number.
  */
-struct drm_head {
-       int minor;                      /**< Minor device number */
+struct drm_minor {
+       int index;                      /**< Minor device number */
+       int type;                       /**< Control or render */
+       dev_t device;                   /**< Device number for mknod */
+       struct device kdev;             /**< Linux device */
        struct drm_device *dev;
        struct proc_dir_entry *dev_root;  /**< proc directory entry */
-       dev_t device;                   /**< Device number for mknod */
 };
 
 /**
@@ -647,7 +689,6 @@ struct drm_head {
  * may contain multiple heads.
  */
 struct drm_device {
-       struct device dev;              /**< Linux device */
        char *unique;                   /**< Unique identifier: e.g., busid */
        int unique_len;                 /**< Length of unique field */
        char *devname;                  /**< For /proc/interrupts */
@@ -729,13 +770,21 @@ struct drm_device {
        /** \name VBLANK IRQ support */
        /*@{ */
 
-       wait_queue_head_t vbl_queue;    /**< VBLANK wait queue */
-       atomic_t vbl_received;
-       atomic_t vbl_received2;         /**< number of secondary VBLANK interrupts */
+       wait_queue_head_t *vbl_queue;   /**< VBLANK wait queue */
+       atomic_t *_vblank_count;        /**< number of VBLANK interrupts (driver must alloc the right number of counters) */
        spinlock_t vbl_lock;
-       struct list_head vbl_sigs;              /**< signal list to send on VBLANK */
-       struct list_head vbl_sigs2;     /**< signals to send on secondary VBLANK */
-       unsigned int vbl_pending;
+       struct list_head *vbl_sigs;             /**< signal list to send on VBLANK */
+       atomic_t vbl_signal_pending;    /* number of signals pending on all crtcs*/
+       atomic_t *vblank_refcount;      /* number of users of vblank interrupts per crtc */
+       u32 *last_vblank;               /* protected by dev->vbl_lock, used */
+                                       /* for wraparound handling */
+       u32 *vblank_offset;             /* used to track how many vblanks */
+       int *vblank_enabled;            /* so we don't call enable more than
+                                          once per disable */
+       u32 *vblank_premodeset;         /*  were lost during modeset */
+       struct timer_list vblank_disable_timer;
+
+       unsigned long max_vblank_count; /**< size of vblank counter register */
        spinlock_t tasklet_lock;        /**< For drm_locked_tasklet */
        void (*locked_tasklet_func)(struct drm_device *dev);
 
@@ -755,6 +804,7 @@ struct drm_device {
 #ifdef __alpha__
        struct pci_controller *hose;
 #endif
+       int num_crtcs;                  /**< Number of CRTCs on this device */
        struct drm_sg_mem *sg;  /**< Scatter gather memory */
        void *dev_private;              /**< device private data */
        struct drm_sigdata sigdata;        /**< For block_all_signals */
@@ -763,7 +813,7 @@ struct drm_device {
        struct drm_driver *driver;
        drm_local_map_t *agp_buffer_map;
        unsigned int agp_buffer_token;
-       struct drm_head primary;                /**< primary screen head */
+       struct drm_minor *primary;              /**< render type primary screen head */
 
        /** \name Drawable information */
        /*@{ */
@@ -989,11 +1039,19 @@ extern void drm_driver_irq_preinstall(struct drm_device *dev);
 extern void drm_driver_irq_postinstall(struct drm_device *dev);
 extern void drm_driver_irq_uninstall(struct drm_device *dev);
 
-extern int drm_wait_vblank(struct drm_device *dev, void *data,
-                          struct drm_file *file_priv);
-extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
-extern void drm_vbl_send_signals(struct drm_device *dev);
+extern int drm_vblank_init(struct drm_device *dev, int num_crtcs);
+extern int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *filp);
+extern int drm_vblank_wait(struct drm_device * dev, unsigned int *vbl_seq);
 extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
+extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
+extern void drm_update_vblank_count(struct drm_device *dev, int crtc);
+extern void drm_handle_vblank(struct drm_device *dev, int crtc);
+extern int drm_vblank_get(struct drm_device *dev, int crtc);
+extern void drm_vblank_put(struct drm_device *dev, int crtc);
+
+                               /* Modesetting support */
+extern int drm_modeset_ctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
 
                                /* AGP/GART support (drm_agpsupport.h) */
 extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
@@ -1030,23 +1088,20 @@ extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
 extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
                       struct drm_driver *driver);
 extern int drm_put_dev(struct drm_device *dev);
-extern int drm_put_head(struct drm_head *head);
+extern int drm_put_minor(struct drm_minor **minor);
 extern unsigned int drm_debug;
-extern unsigned int drm_cards_limit;
-extern struct drm_head **drm_heads;
+
 extern struct class *drm_class;
 extern struct proc_dir_entry *drm_proc_root;
 
+extern struct idr drm_minors_idr;
+
 extern drm_local_map_t *drm_getsarea(struct drm_device *dev);
 
                                /* Proc support (drm_proc.h) */
-extern int drm_proc_init(struct drm_device *dev,
-                        int minor,
-                        struct proc_dir_entry *root,
-                        struct proc_dir_entry **dev_root);
-extern int drm_proc_cleanup(int minor,
-                           struct proc_dir_entry *root,
-                           struct proc_dir_entry *dev_root);
+extern int drm_proc_init(struct drm_minor *minor, int minor_id,
+                        struct proc_dir_entry *root);
+extern int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root);
 
                                /* Scatter Gather Support (drm_scatter.h) */
 extern void drm_sg_cleanup(struct drm_sg_mem * entry);
@@ -1071,8 +1126,8 @@ extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
 struct drm_sysfs_class;
 extern struct class *drm_sysfs_create(struct module *owner, char *name);
 extern void drm_sysfs_destroy(void);
-extern int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head);
-extern void drm_sysfs_device_remove(struct drm_device *dev);
+extern int drm_sysfs_device_add(struct drm_minor *minor);
+extern void drm_sysfs_device_remove(struct drm_minor *minor);
 
 /*
  * Basic memory manager support (drm_mm.c)
index 9468c7889ff1a24e83d78a3434c5498bd6265d08..aefa5ac4c0b1fdcec03418ca610e7ae781d1c8c4 100644 (file)
@@ -122,7 +122,7 @@ EXPORT_SYMBOL(drm_agp_acquire);
 int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
 {
-       return drm_agp_acquire((struct drm_device *) file_priv->head->dev);
+       return drm_agp_acquire((struct drm_device *) file_priv->minor->dev);
 }
 
 /**
index 0e7af53c87deda41d66e61957732b64586d1391d..fc54140551a71620d747aa27466ad8f1d4101376 100644 (file)
@@ -313,35 +313,36 @@ static void drm_cleanup(struct drm_device * dev)
        drm_ht_remove(&dev->map_hash);
        drm_ctxbitmap_cleanup(dev);
 
-       drm_put_head(&dev->primary);
+       drm_put_minor(&dev->primary);
        if (drm_put_dev(dev))
                DRM_ERROR("Cannot unload module\n");
 }
 
-void drm_exit(struct drm_driver *driver)
+int drm_minors_cleanup(int id, void *ptr, void *data)
 {
-       int i;
-       struct drm_device *dev = NULL;
-       struct drm_head *head;
+       struct drm_minor *minor = ptr;
+       struct drm_device *dev;
+       struct drm_driver *driver = data;
+
+       dev = minor->dev;
+       if (minor->dev->driver != driver)
+               return 0;
+
+       if (minor->type != DRM_MINOR_LEGACY)
+               return 0;
 
+       if (dev)
+               pci_dev_put(dev->pdev);
+       drm_cleanup(dev);
+       return 1;
+}
+
+void drm_exit(struct drm_driver *driver)
+{
        DRM_DEBUG("\n");
 
-       for (i = 0; i < drm_cards_limit; i++) {
-               head = drm_heads[i];
-               if (!head)
-                       continue;
-               if (!head->dev)
-                       continue;
-               if (head->dev->driver != driver)
-                       continue;
-               dev = head->dev;
-               if (dev) {
-                       /* release the pci driver */
-                       if (dev->pdev)
-                               pci_dev_put(dev->pdev);
-                       drm_cleanup(dev);
-               }
-       }
+       idr_for_each(&drm_minors_idr, &drm_minors_cleanup, driver);
+
        DRM_INFO("Module unloaded\n");
 }
 
@@ -357,13 +358,7 @@ static int __init drm_core_init(void)
 {
        int ret = -ENOMEM;
 
-       drm_cards_limit =
-           (drm_cards_limit <
-            DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1);
-       drm_heads =
-           drm_calloc(drm_cards_limit, sizeof(*drm_heads), DRM_MEM_STUB);
-       if (!drm_heads)
-               goto err_p1;
+       idr_init(&drm_minors_idr);
 
        if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
                goto err_p1;
@@ -391,7 +386,8 @@ err_p3:
        drm_sysfs_destroy();
 err_p2:
        unregister_chrdev(DRM_MAJOR, "drm");
-       drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
+
+       idr_destroy(&drm_minors_idr);
 err_p1:
        return ret;
 }
@@ -403,7 +399,7 @@ static void __exit drm_core_exit(void)
 
        unregister_chrdev(DRM_MAJOR, "drm");
 
-       drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
+       idr_destroy(&drm_minors_idr);
 }
 
 module_init(drm_core_init);
@@ -452,7 +448,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
              unsigned int cmd, unsigned long arg)
 {
        struct drm_file *file_priv = filp->private_data;
-       struct drm_device *dev = file_priv->head->dev;
+       struct drm_device *dev = file_priv->minor->dev;
        struct drm_ioctl_desc *ioctl;
        drm_ioctl_t *func;
        unsigned int nr = DRM_IOCTL_NR(cmd);
@@ -465,7 +461,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
 
        DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
                  task_pid_nr(current), cmd, nr,
-                 (long)old_encode_dev(file_priv->head->device),
+                 (long)old_encode_dev(file_priv->minor->device),
                  file_priv->authenticated);
 
        if ((nr >= DRM_CORE_IOCTL_COUNT) &&
index f09d4b5002b0f19e8ec9421cce760d03ce7d7178..68f0da801ed82b579efc5fcc3a94c6b755536f1c 100644 (file)
@@ -129,16 +129,15 @@ static int drm_setup(struct drm_device * dev)
 int drm_open(struct inode *inode, struct file *filp)
 {
        struct drm_device *dev = NULL;
-       int minor = iminor(inode);
+       int minor_id = iminor(inode);
+       struct drm_minor *minor;
        int retcode = 0;
 
-       if (!((minor >= 0) && (minor < drm_cards_limit)))
+       minor = idr_find(&drm_minors_idr, minor_id);
+       if (!minor)
                return -ENODEV;
 
-       if (!drm_heads[minor])
-               return -ENODEV;
-
-       if (!(dev = drm_heads[minor]->dev))
+       if (!(dev = minor->dev))
                return -ENODEV;
 
        retcode = drm_open_helper(inode, filp, dev);
@@ -168,19 +167,18 @@ EXPORT_SYMBOL(drm_open);
 int drm_stub_open(struct inode *inode, struct file *filp)
 {
        struct drm_device *dev = NULL;
-       int minor = iminor(inode);
+       struct drm_minor *minor;
+       int minor_id = iminor(inode);
        int err = -ENODEV;
        const struct file_operations *old_fops;
 
        DRM_DEBUG("\n");
 
-       if (!((minor >= 0) && (minor < drm_cards_limit)))
-               return -ENODEV;
-
-       if (!drm_heads[minor])
+       minor = idr_find(&drm_minors_idr, minor_id);
+       if (!minor)
                return -ENODEV;
 
-       if (!(dev = drm_heads[minor]->dev))
+       if (!(dev = minor->dev))
                return -ENODEV;
 
        old_fops = filp->f_op;
@@ -225,7 +223,7 @@ static int drm_cpu_valid(void)
 static int drm_open_helper(struct inode *inode, struct file *filp,
                           struct drm_device * dev)
 {
-       int minor = iminor(inode);
+       int minor_id = iminor(inode);
        struct drm_file *priv;
        int ret;
 
@@ -234,7 +232,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
        if (!drm_cpu_valid())
                return -EINVAL;
 
-       DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor);
+       DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id);
 
        priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
        if (!priv)
@@ -245,8 +243,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
        priv->filp = filp;
        priv->uid = current->euid;
        priv->pid = task_pid_nr(current);
-       priv->minor = minor;
-       priv->head = drm_heads[minor];
+       priv->minor = idr_find(&drm_minors_idr, minor_id);
        priv->ioctl_count = 0;
        /* for compatibility root is always authenticated */
        priv->authenticated = capable(CAP_SYS_ADMIN);
@@ -297,11 +294,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 int drm_fasync(int fd, struct file *filp, int on)
 {
        struct drm_file *priv = filp->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        int retcode;
 
        DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
-                 (long)old_encode_dev(priv->head->device));
+                 (long)old_encode_dev(priv->minor->device));
        retcode = fasync_helper(fd, filp, on, &dev->buf_async);
        if (retcode < 0)
                return retcode;
@@ -324,7 +321,7 @@ EXPORT_SYMBOL(drm_fasync);
 int drm_release(struct inode *inode, struct file *filp)
 {
        struct drm_file *file_priv = filp->private_data;
-       struct drm_device *dev = file_priv->head->dev;
+       struct drm_device *dev = file_priv->minor->dev;
        int retcode = 0;
        unsigned long irqflags;
 
@@ -341,14 +338,14 @@ int drm_release(struct inode *inode, struct file *filp)
 
        DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
                  task_pid_nr(current),
-                 (long)old_encode_dev(file_priv->head->device),
+                 (long)old_encode_dev(file_priv->minor->device),
                  dev->open_count);
 
        if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) {
                if (drm_i_have_hw_lock(dev, file_priv)) {
                        dev->driver->reclaim_buffers_locked(dev, file_priv);
                } else {
-                       unsigned long _end=jiffies + 3*DRM_HZ;
+                       unsigned long endtime = jiffies + 3 * DRM_HZ;
                        int locked = 0;
 
                        drm_idlelock_take(&dev->lock);
@@ -366,7 +363,7 @@ int drm_release(struct inode *inode, struct file *filp)
                                if (locked)
                                        break;
                                schedule();
-                       } while (!time_after_eq(jiffies, _end));
+                       } while (!time_after_eq(jiffies, endtime));
 
                        if (!locked) {
                                DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n"
index 089c015c01d148234fcd24abac9f935c9fd185ef..286f9d61e7d5df50e89f05985c20e246cbeacba9 100644 (file)
@@ -71,6 +71,117 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
        return 0;
 }
 
+static void vblank_disable_fn(unsigned long arg)
+{
+       struct drm_device *dev = (struct drm_device *)arg;
+       unsigned long irqflags;
+       int i;
+
+       for (i = 0; i < dev->num_crtcs; i++) {
+               spin_lock_irqsave(&dev->vbl_lock, irqflags);
+               if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
+                   dev->vblank_enabled[i]) {
+                       dev->driver->disable_vblank(dev, i);
+                       dev->vblank_enabled[i] = 0;
+               }
+               spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+       }
+}
+
+static void drm_vblank_cleanup(struct drm_device *dev)
+{
+       /* Bail if the driver didn't call drm_vblank_init() */
+       if (dev->num_crtcs == 0)
+               return;
+
+       del_timer(&dev->vblank_disable_timer);
+
+       vblank_disable_fn((unsigned long)dev);
+
+       drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * dev->num_crtcs,
+                DRM_MEM_DRIVER);
+       drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * dev->num_crtcs,
+                DRM_MEM_DRIVER);
+       drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) *
+                dev->num_crtcs, DRM_MEM_DRIVER);
+       drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
+                dev->num_crtcs, DRM_MEM_DRIVER);
+       drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) *
+                dev->num_crtcs, DRM_MEM_DRIVER);
+       drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,
+                DRM_MEM_DRIVER);
+       drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) *
+                dev->num_crtcs, DRM_MEM_DRIVER);
+       drm_free(dev->vblank_offset, sizeof(*dev->vblank_offset) * dev->num_crtcs,
+                DRM_MEM_DRIVER);
+
+       dev->num_crtcs = 0;
+}
+
+int drm_vblank_init(struct drm_device *dev, int num_crtcs)
+{
+       int i, ret = -ENOMEM;
+
+       setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
+                   (unsigned long)dev);
+       spin_lock_init(&dev->vbl_lock);
+       atomic_set(&dev->vbl_signal_pending, 0);
+       dev->num_crtcs = num_crtcs;
+
+       dev->vbl_queue = drm_alloc(sizeof(wait_queue_head_t) * num_crtcs,
+                                  DRM_MEM_DRIVER);
+       if (!dev->vbl_queue)
+               goto err;
+
+       dev->vbl_sigs = drm_alloc(sizeof(struct list_head) * num_crtcs,
+                                 DRM_MEM_DRIVER);
+       if (!dev->vbl_sigs)
+               goto err;
+
+       dev->_vblank_count = drm_alloc(sizeof(atomic_t) * num_crtcs,
+                                     DRM_MEM_DRIVER);
+       if (!dev->_vblank_count)
+               goto err;
+
+       dev->vblank_refcount = drm_alloc(sizeof(atomic_t) * num_crtcs,
+                                        DRM_MEM_DRIVER);
+       if (!dev->vblank_refcount)
+               goto err;
+
+       dev->vblank_enabled = drm_calloc(num_crtcs, sizeof(int),
+                                        DRM_MEM_DRIVER);
+       if (!dev->vblank_enabled)
+               goto err;
+
+       dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
+       if (!dev->last_vblank)
+               goto err;
+
+       dev->vblank_premodeset = drm_calloc(num_crtcs, sizeof(u32),
+                                           DRM_MEM_DRIVER);
+       if (!dev->vblank_premodeset)
+               goto err;
+
+       dev->vblank_offset = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
+       if (!dev->vblank_offset)
+               goto err;
+
+       /* Zero per-crtc vblank stuff */
+       for (i = 0; i < num_crtcs; i++) {
+               init_waitqueue_head(&dev->vbl_queue[i]);
+               INIT_LIST_HEAD(&dev->vbl_sigs[i]);
+               atomic_set(&dev->_vblank_count[i], 0);
+               atomic_set(&dev->vblank_refcount[i], 0);
+       }
+
+       return 0;
+
+err:
+       drm_vblank_cleanup(dev);
+       return ret;
+}
+EXPORT_SYMBOL(drm_vblank_init);
+
 /**
  * Install IRQ handler.
  *
@@ -109,17 +220,6 @@ static int drm_irq_install(struct drm_device * dev)
 
        DRM_DEBUG("irq=%d\n", dev->irq);
 
-       if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
-               init_waitqueue_head(&dev->vbl_queue);
-
-               spin_lock_init(&dev->vbl_lock);
-
-               INIT_LIST_HEAD(&dev->vbl_sigs);
-               INIT_LIST_HEAD(&dev->vbl_sigs2);
-
-               dev->vbl_pending = 0;
-       }
-
        /* Before installing handler */
        dev->driver->irq_preinstall(dev);
 
@@ -137,9 +237,14 @@ static int drm_irq_install(struct drm_device * dev)
        }
 
        /* After installing handler */
-       dev->driver->irq_postinstall(dev);
+       ret = dev->driver->irq_postinstall(dev);
+       if (ret < 0) {
+               mutex_lock(&dev->struct_mutex);
+               dev->irq_enabled = 0;
+               mutex_unlock(&dev->struct_mutex);
+       }
 
-       return 0;
+       return ret;
 }
 
 /**
@@ -170,6 +275,8 @@ int drm_irq_uninstall(struct drm_device * dev)
 
        free_irq(dev->irq, dev);
 
+       drm_vblank_cleanup(dev);
+
        dev->locked_tasklet_func = NULL;
 
        return 0;
@@ -213,6 +320,148 @@ int drm_control(struct drm_device *dev, void *data,
        }
 }
 
+/**
+ * drm_vblank_count - retrieve "cooked" vblank counter value
+ * @dev: DRM device
+ * @crtc: which counter to retrieve
+ *
+ * Fetches the "cooked" vblank count value that represents the number of
+ * vblank events since the system was booted, including lost events due to
+ * modesetting activity.
+ */
+u32 drm_vblank_count(struct drm_device *dev, int crtc)
+{
+       return atomic_read(&dev->_vblank_count[crtc]) +
+               dev->vblank_offset[crtc];
+}
+EXPORT_SYMBOL(drm_vblank_count);
+
+/**
+ * drm_update_vblank_count - update the master vblank counter
+ * @dev: DRM device
+ * @crtc: counter to update
+ *
+ * Call back into the driver to update the appropriate vblank counter
+ * (specified by @crtc).  Deal with wraparound, if it occurred, and
+ * update the last read value so we can deal with wraparound on the next
+ * call if necessary.
+ */
+void drm_update_vblank_count(struct drm_device *dev, int crtc)
+{
+       unsigned long irqflags;
+       u32 cur_vblank, diff;
+
+       /*
+        * Interrupts were disabled prior to this call, so deal with counter
+        * wrap if needed.
+        * NOTE!  It's possible we lost a full dev->max_vblank_count events
+        * here if the register is small or we had vblank interrupts off for
+        * a long time.
+        */
+       cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
+       spin_lock_irqsave(&dev->vbl_lock, irqflags);
+       if (cur_vblank < dev->last_vblank[crtc]) {
+               diff = dev->max_vblank_count -
+                       dev->last_vblank[crtc];
+               diff += cur_vblank;
+       } else {
+               diff = cur_vblank - dev->last_vblank[crtc];
+       }
+       dev->last_vblank[crtc] = cur_vblank;
+       spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+
+       atomic_add(diff, &dev->_vblank_count[crtc]);
+}
+EXPORT_SYMBOL(drm_update_vblank_count);
+
+/**
+ * drm_vblank_get - get a reference count on vblank events
+ * @dev: DRM device
+ * @crtc: which CRTC to own
+ *
+ * Acquire a reference count on vblank events to avoid having them disabled
+ * while in use.  Note callers will probably want to update the master counter
+ * using drm_update_vblank_count() above before calling this routine so that
+ * wakeups occur on the right vblank event.
+ *
+ * RETURNS
+ * Zero on success, nonzero on failure.
+ */
+int drm_vblank_get(struct drm_device *dev, int crtc)
+{
+       unsigned long irqflags;
+       int ret = 0;
+
+       spin_lock_irqsave(&dev->vbl_lock, irqflags);
+       /* Going from 0->1 means we have to enable interrupts again */
+       if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 &&
+           !dev->vblank_enabled[crtc]) {
+               ret = dev->driver->enable_vblank(dev, crtc);
+               if (ret)
+                       atomic_dec(&dev->vblank_refcount[crtc]);
+               else
+                       dev->vblank_enabled[crtc] = 1;
+       }
+       spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+
+       return ret;
+}
+EXPORT_SYMBOL(drm_vblank_get);
+
+/**
+ * drm_vblank_put - give up ownership of vblank events
+ * @dev: DRM device
+ * @crtc: which counter to give up
+ *
+ * Release ownership of a given vblank counter, turning off interrupts
+ * if possible.
+ */
+void drm_vblank_put(struct drm_device *dev, int crtc)
+{
+       /* Last user schedules interrupt disable */
+       if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
+           mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
+}
+EXPORT_SYMBOL(drm_vblank_put);
+
+/**
+ * drm_modeset_ctl - handle vblank event counter changes across mode switch
+ * @DRM_IOCTL_ARGS: standard ioctl arguments
+ *
+ * Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET
+ * ioctls around modesetting so that any lost vblank events are accounted for.
+ */
+int drm_modeset_ctl(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
+{
+       struct drm_modeset_ctl *modeset = data;
+       int crtc, ret = 0;
+       u32 new;
+
+       crtc = modeset->arg;
+       if (crtc >= dev->num_crtcs) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       switch (modeset->cmd) {
+       case _DRM_PRE_MODESET:
+               dev->vblank_premodeset[crtc] =
+                       dev->driver->get_vblank_counter(dev, crtc);
+               break;
+       case _DRM_POST_MODESET:
+               new = dev->driver->get_vblank_counter(dev, crtc);
+               dev->vblank_offset[crtc] = dev->vblank_premodeset[crtc] - new;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+out:
+       return ret;
+}
+
 /**
  * Wait for VBLANK.
  *
@@ -232,12 +481,13 @@ int drm_control(struct drm_device *dev, void *data,
  *
  * If a signal is not requested, then calls vblank_wait().
  */
-int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
+int drm_wait_vblank(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
 {
        union drm_wait_vblank *vblwait = data;
        struct timeval now;
        int ret = 0;
-       unsigned int flags, seq;
+       unsigned int flags, seq, crtc;
 
        if ((!dev->irq) || (!dev->irq_enabled))
                return -EINVAL;
@@ -251,13 +501,13 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
        }
 
        flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
+       crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
 
-       if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
-                                   DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
+       if (crtc >= dev->num_crtcs)
                return -EINVAL;
 
-       seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
-                         : &dev->vbl_received);
+       drm_update_vblank_count(dev, crtc);
+       seq = drm_vblank_count(dev, crtc);
 
        switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
        case _DRM_VBLANK_RELATIVE:
@@ -276,8 +526,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
 
        if (flags & _DRM_VBLANK_SIGNAL) {
                unsigned long irqflags;
-               struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
-                                     ? &dev->vbl_sigs2 : &dev->vbl_sigs;
+               struct list_head *vbl_sigs = &dev->vbl_sigs[crtc];
                struct drm_vbl_sig *vbl_sig;
 
                spin_lock_irqsave(&dev->vbl_lock, irqflags);
@@ -298,22 +547,26 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
                        }
                }
 
-               if (dev->vbl_pending >= 100) {
+               if (atomic_read(&dev->vbl_signal_pending) >= 100) {
                        spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
                        return -EBUSY;
                }
 
-               dev->vbl_pending++;
-
                spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 
-               if (!
-                   (vbl_sig =
-                    drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) {
+               vbl_sig = drm_calloc(1, sizeof(struct drm_vbl_sig),
+                                    DRM_MEM_DRIVER);
+               if (!vbl_sig)
                        return -ENOMEM;
+
+               ret = drm_vblank_get(dev, crtc);
+               if (ret) {
+                       drm_free(vbl_sig, sizeof(struct drm_vbl_sig),
+                                DRM_MEM_DRIVER);
+                       return ret;
                }
 
-               memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
+               atomic_inc(&dev->vbl_signal_pending);
 
                vbl_sig->sequence = vblwait->request.sequence;
                vbl_sig->info.si_signo = vblwait->request.signal;
@@ -327,17 +580,20 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
 
                vblwait->reply.sequence = seq;
        } else {
-               if (flags & _DRM_VBLANK_SECONDARY) {
-                       if (dev->driver->vblank_wait2)
-                               ret = dev->driver->vblank_wait2(dev, &vblwait->request.sequence);
-               } else if (dev->driver->vblank_wait)
-                       ret =
-                           dev->driver->vblank_wait(dev,
-                                                    &vblwait->request.sequence);
-
+               unsigned long cur_vblank;
+
+               ret = drm_vblank_get(dev, crtc);
+               if (ret)
+                       return ret;
+               DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
+                           (((cur_vblank = drm_vblank_count(dev, crtc))
+                             - vblwait->request.sequence) <= (1 << 23)));
+               drm_vblank_put(dev, crtc);
                do_gettimeofday(&now);
+
                vblwait->reply.tval_sec = now.tv_sec;
                vblwait->reply.tval_usec = now.tv_usec;
+               vblwait->reply.sequence = cur_vblank;
        }
 
       done:
@@ -348,44 +604,57 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
  * Send the VBLANK signals.
  *
  * \param dev DRM device.
+ * \param crtc CRTC where the vblank event occurred
  *
  * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
  *
  * If a signal is not requested, then calls vblank_wait().
  */
-void drm_vbl_send_signals(struct drm_device * dev)
+static void drm_vbl_send_signals(struct drm_device * dev, int crtc)
 {
+       struct drm_vbl_sig *vbl_sig, *tmp;
+       struct list_head *vbl_sigs;
+       unsigned int vbl_seq;
        unsigned long flags;
-       int i;
 
        spin_lock_irqsave(&dev->vbl_lock, flags);
 
-       for (i = 0; i < 2; i++) {
-               struct drm_vbl_sig *vbl_sig, *tmp;
-               struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
-               unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
-                                                  &dev->vbl_received);
+       vbl_sigs = &dev->vbl_sigs[crtc];
+       vbl_seq = drm_vblank_count(dev, crtc);
 
-               list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
-                       if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
-                               vbl_sig->info.si_code = vbl_seq;
-                               send_sig_info(vbl_sig->info.si_signo,
-                                             &vbl_sig->info, vbl_sig->task);
+       list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
+           if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
+               vbl_sig->info.si_code = vbl_seq;
+               send_sig_info(vbl_sig->info.si_signo,
+                             &vbl_sig->info, vbl_sig->task);
 
-                               list_del(&vbl_sig->head);
+               list_del(&vbl_sig->head);
 
-                               drm_free(vbl_sig, sizeof(*vbl_sig),
-                                        DRM_MEM_DRIVER);
-
-                               dev->vbl_pending--;
-                       }
-               }
+               drm_free(vbl_sig, sizeof(*vbl_sig),
+                        DRM_MEM_DRIVER);
+               atomic_dec(&dev->vbl_signal_pending);
+               drm_vblank_put(dev, crtc);
+           }
        }
 
        spin_unlock_irqrestore(&dev->vbl_lock, flags);
 }
 
-EXPORT_SYMBOL(drm_vbl_send_signals);
+/**
+ * drm_handle_vblank - handle a vblank event
+ * @dev: DRM device
+ * @crtc: where this event occurred
+ *
+ * Drivers should call this routine in their vblank interrupt handlers to
+ * update the vblank counter and send any signals that may be pending.
+ */
+void drm_handle_vblank(struct drm_device *dev, int crtc)
+{
+       drm_update_vblank_count(dev, crtc);
+       DRM_WAKEUP(&dev->vbl_queue[crtc]);
+       drm_vbl_send_signals(dev, crtc);
+}
+EXPORT_SYMBOL(drm_handle_vblank);
 
 /**
  * Tasklet wrapper function.
index d9b560fe9bbe68b0543091273cdacc7e5d87b2af..93b1e0475c93bef525c06ea89785dded441d4f39 100644 (file)
@@ -87,34 +87,35 @@ static struct drm_proc_list {
  * "/proc/dri/%minor%/", and each entry in proc_list as
  * "/proc/dri/%minor%/%name%".
  */
-int drm_proc_init(struct drm_device * dev, int minor,
-                 struct proc_dir_entry *root, struct proc_dir_entry **dev_root)
+int drm_proc_init(struct drm_minor *minor, int minor_id,
+                 struct proc_dir_entry *root)
 {
        struct proc_dir_entry *ent;
        int i, j;
        char name[64];
 
-       sprintf(name, "%d", minor);
-       *dev_root = proc_mkdir(name, root);
-       if (!*dev_root) {
+       sprintf(name, "%d", minor_id);
+       minor->dev_root = proc_mkdir(name, root);
+       if (!minor->dev_root) {
                DRM_ERROR("Cannot create /proc/dri/%s\n", name);
                return -1;
        }
 
        for (i = 0; i < DRM_PROC_ENTRIES; i++) {
                ent = create_proc_entry(drm_proc_list[i].name,
-                                       S_IFREG | S_IRUGO, *dev_root);
+                                       S_IFREG | S_IRUGO, minor->dev_root);
                if (!ent) {
                        DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
                                  name, drm_proc_list[i].name);
                        for (j = 0; j < i; j++)
                                remove_proc_entry(drm_proc_list[i].name,
-                                                 *dev_root);
+                                                 minor->dev_root);
                        remove_proc_entry(name, root);
+                       minor->dev_root = NULL;
                        return -1;
                }
                ent->read_proc = drm_proc_list[i].f;
-               ent->data = dev;
+               ent->data = minor;
        }
 
        return 0;
@@ -130,18 +131,17 @@ int drm_proc_init(struct drm_device * dev, int minor,
  *
  * Remove all proc entries created by proc_init().
  */
-int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
-                    struct proc_dir_entry *dev_root)
+int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
 {
        int i;
        char name[64];
 
-       if (!root || !dev_root)
+       if (!root || !minor->dev_root)
                return 0;
 
        for (i = 0; i < DRM_PROC_ENTRIES; i++)
-               remove_proc_entry(drm_proc_list[i].name, dev_root);
-       sprintf(name, "%d", minor);
+               remove_proc_entry(drm_proc_list[i].name, minor->dev_root);
+       sprintf(name, "%d", minor->index);
        remove_proc_entry(name, root);
 
        return 0;
@@ -163,7 +163,8 @@ int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
 static int drm_name_info(char *buf, char **start, off_t offset, int request,
                         int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int len = 0;
 
        if (offset > DRM_PROC_LIMIT) {
@@ -205,7 +206,8 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,
 static int drm__vm_info(char *buf, char **start, off_t offset, int request,
                        int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int len = 0;
        struct drm_map *map;
        struct drm_map_list *r_list;
@@ -261,7 +263,8 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
 static int drm_vm_info(char *buf, char **start, off_t offset, int request,
                       int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
@@ -284,7 +287,8 @@ static int drm_vm_info(char *buf, char **start, off_t offset, int request,
 static int drm__queues_info(char *buf, char **start, off_t offset,
                            int request, int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int len = 0;
        int i;
        struct drm_queue *q;
@@ -334,7 +338,8 @@ static int drm__queues_info(char *buf, char **start, off_t offset,
 static int drm_queues_info(char *buf, char **start, off_t offset, int request,
                           int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
@@ -357,7 +362,8 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request,
 static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
                          int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int len = 0;
        struct drm_device_dma *dma = dev->dma;
        int i;
@@ -406,7 +412,8 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
 static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
                         int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
@@ -429,7 +436,8 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
 static int drm__clients_info(char *buf, char **start, off_t offset,
                             int request, int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int len = 0;
        struct drm_file *priv;
 
@@ -445,7 +453,7 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
        list_for_each_entry(priv, &dev->filelist, lhead) {
                DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
                               priv->authenticated ? 'y' : 'n',
-                              priv->minor,
+                              priv->minor->index,
                               priv->pid,
                               priv->uid, priv->magic, priv->ioctl_count);
        }
@@ -462,7 +470,8 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
 static int drm_clients_info(char *buf, char **start, off_t offset,
                            int request, int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
@@ -476,7 +485,8 @@ static int drm_clients_info(char *buf, char **start, off_t offset,
 static int drm__vma_info(char *buf, char **start, off_t offset, int request,
                         int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int len = 0;
        struct drm_vma_entry *pt;
        struct vm_area_struct *vma;
@@ -535,7 +545,8 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
 static int drm_vma_info(char *buf, char **start, off_t offset, int request,
                        int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
index d93a217f856a7303d185396ea2a376e8cc3c3e65..c2f584f3b46c6b56e5cbba2303b70da5d5fa3067 100644 (file)
 #include "drmP.h"
 #include "drm_core.h"
 
-unsigned int drm_cards_limit = 16;     /* Enough for one machine */
 unsigned int drm_debug = 0;    /* 1 to enable debug output */
 EXPORT_SYMBOL(drm_debug);
 
 MODULE_AUTHOR(CORE_AUTHOR);
 MODULE_DESCRIPTION(CORE_DESC);
 MODULE_LICENSE("GPL and additional rights");
-MODULE_PARM_DESC(cards_limit, "Maximum number of graphics cards");
 MODULE_PARM_DESC(debug, "Enable debug output");
 
-module_param_named(cards_limit, drm_cards_limit, int, 0444);
 module_param_named(debug, drm_debug, int, 0600);
 
-struct drm_head **drm_heads;
+struct idr drm_minors_idr;
+
 struct class *drm_class;
 struct proc_dir_entry *drm_proc_root;
 
+static int drm_minor_get_id(struct drm_device *dev, int type)
+{
+       int new_id;
+       int ret;
+       int base = 0, limit = 63;
+
+again:
+       if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) {
+               DRM_ERROR("Out of memory expanding drawable idr\n");
+               return -ENOMEM;
+       }
+       mutex_lock(&dev->struct_mutex);
+       ret = idr_get_new_above(&drm_minors_idr, NULL,
+                               base, &new_id);
+       mutex_unlock(&dev->struct_mutex);
+       if (ret == -EAGAIN) {
+               goto again;
+       } else if (ret) {
+               return ret;
+       }
+
+       if (new_id >= limit) {
+               idr_remove(&drm_minors_idr, new_id);
+               return -EINVAL;
+       }
+       return new_id;
+}
+
 static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
                           const struct pci_device_id *ent,
                           struct drm_driver *driver)
@@ -145,48 +171,60 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
  * create the proc init entry via proc_init(). This routines assigns
  * minor numbers to secondary heads of multi-headed cards
  */
-static int drm_get_head(struct drm_device * dev, struct drm_head * head)
+static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
 {
-       struct drm_head **heads = drm_heads;
+       struct drm_minor *new_minor;
        int ret;
-       int minor;
+       int minor_id;
 
        DRM_DEBUG("\n");
 
-       for (minor = 0; minor < drm_cards_limit; minor++, heads++) {
-               if (!*heads) {
-
-                       *head = (struct drm_head) {
-                       .dev = dev,.device =
-                                   MKDEV(DRM_MAJOR, minor),.minor = minor,};
-
-                       if ((ret =
-                            drm_proc_init(dev, minor, drm_proc_root,
-                                          &head->dev_root))) {
-                               printk(KERN_ERR
-                                      "DRM: Failed to initialize /proc/dri.\n");
-                               goto err_g1;
-                       }
-
-                       ret = drm_sysfs_device_add(dev, head);
-                       if (ret) {
-                               printk(KERN_ERR
-                                      "DRM: Error sysfs_device_add.\n");
-                               goto err_g2;
-                       }
-                       *heads = head;
-
-                       DRM_DEBUG("new minor assigned %d\n", minor);
-                       return 0;
+       minor_id = drm_minor_get_id(dev, type);
+       if (minor_id < 0)
+               return minor_id;
+
+       new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL);
+       if (!new_minor) {
+               ret = -ENOMEM;
+               goto err_idr;
+       }
+
+       new_minor->type = type;
+       new_minor->device = MKDEV(DRM_MAJOR, minor_id);
+       new_minor->dev = dev;
+       new_minor->index = minor_id;
+
+       idr_replace(&drm_minors_idr, new_minor, minor_id);
+
+       if (type == DRM_MINOR_LEGACY) {
+               ret = drm_proc_init(new_minor, minor_id, drm_proc_root);
+               if (ret) {
+                       DRM_ERROR("DRM: Failed to initialize /proc/dri.\n");
+                       goto err_mem;
                }
+       } else
+               new_minor->dev_root = NULL;
+
+       ret = drm_sysfs_device_add(new_minor);
+       if (ret) {
+               printk(KERN_ERR
+                      "DRM: Error sysfs_device_add.\n");
+               goto err_g2;
        }
-       DRM_ERROR("out of minors\n");
-       return -ENOMEM;
-      err_g2:
-       drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
-      err_g1:
-       *head = (struct drm_head) {
-       .dev = NULL};
+       *minor = new_minor;
+
+       DRM_DEBUG("new minor assigned %d\n", minor_id);
+       return 0;
+
+
+err_g2:
+       if (new_minor->type == DRM_MINOR_LEGACY)
+               drm_proc_cleanup(new_minor, drm_proc_root);
+err_mem:
+       kfree(new_minor);
+err_idr:
+       idr_remove(&drm_minors_idr, minor_id);
+       *minor = NULL;
        return ret;
 }
 
@@ -222,12 +260,12 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
                printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
                goto err_g2;
        }
-       if ((ret = drm_get_head(dev, &dev->primary)))
+       if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
                goto err_g2;
 
        DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
                 driver->name, driver->major, driver->minor, driver->patchlevel,
-                driver->date, dev->primary.minor);
+                driver->date, dev->primary->index);
 
        return 0;
 
@@ -276,18 +314,18 @@ int drm_put_dev(struct drm_device * dev)
  * last minor released.
  *
  */
-int drm_put_head(struct drm_head * head)
+int drm_put_minor(struct drm_minor **minor_p)
 {
-       int minor = head->minor;
-
-       DRM_DEBUG("release secondary minor %d\n", minor);
-
-       drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
-       drm_sysfs_device_remove(head->dev);
+       struct drm_minor *minor = *minor_p;
+       DRM_DEBUG("release secondary minor %d\n", minor->index);
 
-       *head = (struct drm_head) {.dev = NULL};
+       if (minor->type == DRM_MINOR_LEGACY)
+               drm_proc_cleanup(minor, drm_proc_root);
+       drm_sysfs_device_remove(minor);
 
-       drm_heads[minor] = NULL;
+       idr_remove(&drm_minors_idr, minor->index);
 
+       kfree(minor);
+       *minor_p = NULL;
        return 0;
 }
index 05ed5043254fa4212fc6b36475902516b9c0954a..7a1d9a782ddb3469a3e5105a6dc0841bd468b2a3 100644 (file)
@@ -19,7 +19,7 @@
 #include "drm_core.h"
 #include "drmP.h"
 
-#define to_drm_device(d) container_of(d, struct drm_device, dev)
+#define to_drm_minor(d) container_of(d, struct drm_minor, kdev)
 
 /**
  * drm_sysfs_suspend - DRM class suspend hook
@@ -31,7 +31,8 @@
  */
 static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
 {
-       struct drm_device *drm_dev = to_drm_device(dev);
+       struct drm_minor *drm_minor = to_drm_minor(dev);
+       struct drm_device *drm_dev = drm_minor->dev;
 
        printk(KERN_ERR "%s\n", __FUNCTION__);
 
@@ -50,7 +51,8 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
  */
 static int drm_sysfs_resume(struct device *dev)
 {
-       struct drm_device *drm_dev = to_drm_device(dev);
+       struct drm_minor *drm_minor = to_drm_minor(dev);
+       struct drm_device *drm_dev = drm_minor->dev;
 
        if (drm_dev->driver->resume)
                return drm_dev->driver->resume(drm_dev);
@@ -120,10 +122,11 @@ void drm_sysfs_destroy(void)
 static ssize_t show_dri(struct device *device, struct device_attribute *attr,
                        char *buf)
 {
-       struct drm_device *dev = to_drm_device(device);
-       if (dev->driver->dri_library_name)
-               return dev->driver->dri_library_name(dev, buf);
-       return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name);
+       struct drm_minor *drm_minor = to_drm_minor(device);
+       struct drm_device *drm_dev = drm_minor->dev;
+       if (drm_dev->driver->dri_library_name)
+               return drm_dev->driver->dri_library_name(drm_dev, buf);
+       return snprintf(buf, PAGE_SIZE, "%s\n", drm_dev->driver->pci_driver.name);
 }
 
 static struct device_attribute device_attrs[] = {
@@ -152,25 +155,28 @@ static void drm_sysfs_device_release(struct device *dev)
  * as the parent for the Linux device, and make sure it has a file containing
  * the driver we're using (for userspace compatibility).
  */
-int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head)
+int drm_sysfs_device_add(struct drm_minor *minor)
 {
        int err;
        int i, j;
+       char *minor_str;
 
-       dev->dev.parent = &dev->pdev->dev;
-       dev->dev.class = drm_class;
-       dev->dev.release = drm_sysfs_device_release;
-       dev->dev.devt = head->device;
-       snprintf(dev->dev.bus_id, BUS_ID_SIZE, "card%d", head->minor);
+       minor->kdev.parent = &minor->dev->pdev->dev;
+       minor->kdev.class = drm_class;
+       minor->kdev.release = drm_sysfs_device_release;
+       minor->kdev.devt = minor->device;
+       minor_str = "card%d";
 
-       err = device_register(&dev->dev);
+       snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index);
+
+       err = device_register(&minor->kdev);
        if (err) {
                DRM_ERROR("device add failed: %d\n", err);
                goto err_out;
        }
 
        for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
-               err = device_create_file(&dev->dev, &device_attrs[i]);
+               err = device_create_file(&minor->kdev, &device_attrs[i]);
                if (err)
                        goto err_out_files;
        }
@@ -180,8 +186,8 @@ int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head)
 err_out_files:
        if (i > 0)
                for (j = 0; j < i; j++)
-                       device_remove_file(&dev->dev, &device_attrs[i]);
-       device_unregister(&dev->dev);
+                       device_remove_file(&minor->kdev, &device_attrs[i]);
+       device_unregister(&minor->kdev);
 err_out:
 
        return err;
@@ -194,11 +200,11 @@ err_out:
  * This call unregisters and cleans up a class device that was created with a
  * call to drm_sysfs_device_add()
  */
-void drm_sysfs_device_remove(struct drm_device *dev)
+void drm_sysfs_device_remove(struct drm_minor *minor)
 {
        int i;
 
        for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
-               device_remove_file(&dev->dev, &device_attrs[i]);
-       device_unregister(&dev->dev);
+               device_remove_file(&minor->kdev, &device_attrs[i]);
+       device_unregister(&minor->kdev);
 }
index 945df72a51a9f2df78aac8f9a1c128ac85016a0e..c234c6f24a8d8fd157a1af029d530d5bbc09bd84 100644 (file)
@@ -90,7 +90,7 @@ static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma)
 static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        struct drm_map *map = NULL;
        struct drm_map_list *r_list;
        struct drm_hash_item *hash;
@@ -207,7 +207,7 @@ static int drm_do_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 static void drm_vm_shm_close(struct vm_area_struct *vma)
 {
        struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        struct drm_vma_entry *pt, *temp;
        struct drm_map *map;
        struct drm_map_list *r_list;
@@ -286,7 +286,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
 static int drm_do_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        struct drm_device_dma *dma = dev->dma;
        unsigned long offset;
        unsigned long page_nr;
@@ -321,7 +321,7 @@ static int drm_do_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct drm_map *map = (struct drm_map *) vma->vm_private_data;
        struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        struct drm_sg_mem *entry = dev->sg;
        unsigned long offset;
        unsigned long map_offset;
@@ -402,7 +402,7 @@ static struct vm_operations_struct drm_vm_sg_ops = {
 static void drm_vm_open_locked(struct vm_area_struct *vma)
 {
        struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        struct drm_vma_entry *vma_entry;
 
        DRM_DEBUG("0x%08lx,0x%08lx\n",
@@ -420,7 +420,7 @@ static void drm_vm_open_locked(struct vm_area_struct *vma)
 static void drm_vm_open(struct vm_area_struct *vma)
 {
        struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
 
        mutex_lock(&dev->struct_mutex);
        drm_vm_open_locked(vma);
@@ -438,7 +438,7 @@ static void drm_vm_open(struct vm_area_struct *vma)
 static void drm_vm_close(struct vm_area_struct *vma)
 {
        struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        struct drm_vma_entry *pt, *temp;
 
        DRM_DEBUG("0x%08lx,0x%08lx\n",
@@ -473,7 +473,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
        struct drm_device_dma *dma;
        unsigned long length = vma->vm_end - vma->vm_start;
 
-       dev = priv->head->dev;
+       dev = priv->minor->dev;
        dma = dev->dma;
        DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
                  vma->vm_start, vma->vm_end, vma->vm_pgoff);
@@ -543,7 +543,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
 static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
 {
        struct drm_file *priv = filp->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        struct drm_map *map = NULL;
        unsigned long offset = 0;
        struct drm_hash_item *hash;
@@ -640,12 +640,12 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
                /* Don't let this area swap.  Change when
                   DRM_KERNEL advisory is supported. */
                vma->vm_flags |= VM_RESERVED;
-               vma->vm_page_prot = drm_dma_prot(map->type, vma);
                break;
        case _DRM_SCATTER_GATHER:
                vma->vm_ops = &drm_vm_sg_ops;
                vma->vm_private_data = (void *)map;
                vma->vm_flags |= VM_RESERVED;
+               vma->vm_page_prot = drm_dma_prot(map->type, vma);
                break;
        default:
                return -EINVAL; /* This should never happen. */
@@ -661,7 +661,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
 int drm_mmap(struct file *filp, struct vm_area_struct *vma)
 {
        struct drm_file *priv = filp->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
index 8d7ea81c4b66b3f70b242b02d2778f3c6052a9fc..e5de8ea4154460cabe658240798ffd288570be78 100644 (file)
@@ -94,7 +94,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
        drm_i810_buf_priv_t *buf_priv;
 
        lock_kernel();
-       dev = priv->head->dev;
+       dev = priv->minor->dev;
        dev_priv = dev->dev_private;
        buf = dev_priv->mmap_buffer;
        buf_priv = buf->dev_private;
@@ -122,7 +122,7 @@ static const struct file_operations i810_buffer_fops = {
 
 static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
 {
-       struct drm_device *dev = file_priv->head->dev;
+       struct drm_device *dev = file_priv->minor->dev;
        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
        drm_i810_private_t *dev_priv = dev->dev_private;
        const struct file_operations *old_fops;
index 9df08105f4f3676b86595753badca719ad433e50..60c9376be486635e9ab902c64af5acb06d3ad339 100644 (file)
@@ -96,7 +96,7 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
        drm_i830_buf_priv_t *buf_priv;
 
        lock_kernel();
-       dev = priv->head->dev;
+       dev = priv->minor->dev;
        dev_priv = dev->dev_private;
        buf = dev_priv->mmap_buffer;
        buf_priv = buf->dev_private;
@@ -124,7 +124,7 @@ static const struct file_operations i830_buffer_fops = {
 
 static int i830_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
 {
-       struct drm_device *dev = file_priv->head->dev;
+       struct drm_device *dev = file_priv->minor->dev;
        drm_i830_buf_priv_t *buf_priv = buf->dev_private;
        drm_i830_private_t *dev_priv = dev->dev_private;
        const struct file_operations *old_fops;
index a043bb12301acd9c1cf087663659c775316dd9f2..ef7bf143a80c632a9c8044fa7e0d77f4fbc3a57f 100644 (file)
@@ -415,10 +415,13 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        RING_LOCALS;
 
-       dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
+       if (++dev_priv->counter > BREADCRUMB_MASK) {
+                dev_priv->counter = 1;
+                DRM_DEBUG("Breadcrumb counter wrapped around\n");
+       }
 
-       if (dev_priv->counter > 0x7FFFFFFFUL)
-               dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
+       if (dev_priv->sarea_priv)
+               dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
 
        BEGIN_LP_RING(4);
        OUT_RING(CMD_STORE_DWORD_IDX);
@@ -428,6 +431,26 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
        ADVANCE_LP_RING();
 }
 
+int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       uint32_t flush_cmd = CMD_MI_FLUSH;
+       RING_LOCALS;
+
+       flush_cmd |= flush;
+
+       i915_kernel_lost_context(dev);
+
+       BEGIN_LP_RING(4);
+       OUT_RING(flush_cmd);
+       OUT_RING(0);
+       OUT_RING(0);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       return 0;
+}
+
 static int i915_dispatch_cmdbuffer(struct drm_device * dev,
                                   drm_i915_cmdbuffer_t * cmd)
 {
@@ -511,52 +534,74 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
        return 0;
 }
 
-static int i915_dispatch_flip(struct drm_device * dev)
+static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
+       u32 num_pages, current_page, next_page, dspbase;
+       int shift = 2 * plane, x, y;
        RING_LOCALS;
 
-       DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
-                 __FUNCTION__,
-                 dev_priv->current_page,
-                 dev_priv->sarea_priv->pf_current_page);
+       /* Calculate display base offset */
+       num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2;
+       current_page = (dev_priv->sarea_priv->pf_current_page >> shift) & 0x3;
+       next_page = (current_page + 1) % num_pages;
 
-       i915_kernel_lost_context(dev);
-
-       BEGIN_LP_RING(2);
-       OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
+       switch (next_page) {
+       default:
+       case 0:
+               dspbase = dev_priv->sarea_priv->front_offset;
+               break;
+       case 1:
+               dspbase = dev_priv->sarea_priv->back_offset;
+               break;
+       case 2:
+               dspbase = dev_priv->sarea_priv->third_offset;
+               break;
+       }
 
-       BEGIN_LP_RING(6);
-       OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
-       OUT_RING(0);
-       if (dev_priv->current_page == 0) {
-               OUT_RING(dev_priv->back_offset);
-               dev_priv->current_page = 1;
+       if (plane == 0) {
+               x = dev_priv->sarea_priv->planeA_x;
+               y = dev_priv->sarea_priv->planeA_y;
        } else {
-               OUT_RING(dev_priv->front_offset);
-               dev_priv->current_page = 0;
+               x = dev_priv->sarea_priv->planeB_x;
+               y = dev_priv->sarea_priv->planeB_y;
        }
-       OUT_RING(0);
-       ADVANCE_LP_RING();
 
-       BEGIN_LP_RING(2);
-       OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
+       dspbase += (y * dev_priv->sarea_priv->pitch + x) * dev_priv->cpp;
 
-       dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
+       DRM_DEBUG("plane=%d current_page=%d dspbase=0x%x\n", plane, current_page,
+                 dspbase);
 
        BEGIN_LP_RING(4);
-       OUT_RING(CMD_STORE_DWORD_IDX);
-       OUT_RING(20);
-       OUT_RING(dev_priv->counter);
-       OUT_RING(0);
+       OUT_RING(sync ? 0 :
+                (MI_WAIT_FOR_EVENT | (plane ? MI_WAIT_FOR_PLANE_B_FLIP :
+                                      MI_WAIT_FOR_PLANE_A_FLIP)));
+       OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | (sync ? 0 : ASYNC_FLIP) |
+                (plane ? DISPLAY_PLANE_B : DISPLAY_PLANE_A));
+       OUT_RING(dev_priv->sarea_priv->pitch * dev_priv->cpp);
+       OUT_RING(dspbase);
        ADVANCE_LP_RING();
 
-       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
-       return 0;
+       dev_priv->sarea_priv->pf_current_page &= ~(0x3 << shift);
+       dev_priv->sarea_priv->pf_current_page |= next_page << shift;
+}
+
+void i915_dispatch_flip(struct drm_device * dev, int planes, int sync)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       int i;
+
+       DRM_DEBUG("planes=0x%x pfCurrentPage=%d\n",
+                 planes, dev_priv->sarea_priv->pf_current_page);
+
+       i915_emit_mi_flush(dev, MI_READ_FLUSH | MI_EXE_FLUSH);
+
+       for (i = 0; i < 2; i++)
+               if (planes & (1 << i))
+                       i915_do_dispatch_flip(dev, i, sync);
+
+       i915_emit_breadcrumb(dev);
+
 }
 
 static int i915_quiescent(struct drm_device * dev)
@@ -579,7 +624,6 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
                            struct drm_file *file_priv)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u32 *hw_status = dev_priv->hw_status_page;
        drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
            dev_priv->sarea_priv;
        drm_i915_batchbuffer_t *batch = data;
@@ -602,7 +646,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
 
        ret = i915_dispatch_batchbuffer(dev, batch);
 
-       sarea_priv->last_dispatch = (int)hw_status[5];
+       sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
        return ret;
 }
 
@@ -610,7 +654,6 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u32 *hw_status = dev_priv->hw_status_page;
        drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
            dev_priv->sarea_priv;
        drm_i915_cmdbuffer_t *cmdbuf = data;
@@ -635,18 +678,51 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
                return ret;
        }
 
-       sarea_priv->last_dispatch = (int)hw_status[5];
+       sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+       return 0;
+}
+
+static int i915_do_cleanup_pageflip(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       int i, planes, num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2;
+
+       DRM_DEBUG("\n");
+
+       for (i = 0, planes = 0; i < 2; i++)
+               if (dev_priv->sarea_priv->pf_current_page & (0x3 << (2 * i))) {
+                       dev_priv->sarea_priv->pf_current_page =
+                               (dev_priv->sarea_priv->pf_current_page &
+                                ~(0x3 << (2 * i))) | ((num_pages - 1) << (2 * i));
+
+                       planes |= 1 << i;
+               }
+
+       if (planes)
+               i915_dispatch_flip(dev, planes, 0);
+
        return 0;
 }
 
 static int i915_flip_bufs(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
 {
-       DRM_DEBUG("%s\n", __FUNCTION__);
+       drm_i915_flip_t *param = data;
+
+       DRM_DEBUG("\n");
 
        LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       return i915_dispatch_flip(dev);
+       /* This is really planes */
+       if (param->pipes & ~0x3) {
+               DRM_ERROR("Invalid planes 0x%x, only <= 0x3 is valid\n",
+                         param->pipes);
+               return -EINVAL;
+       }
+
+       i915_dispatch_flip(dev, param->pipes, 0);
+
+       return 0;
 }
 
 static int i915_getparam(struct drm_device *dev, void *data,
@@ -807,6 +883,8 @@ void i915_driver_lastclose(struct drm_device * dev)
        if (!dev_priv)
                return;
 
+       if (drm_getsarea(dev) && dev_priv->sarea_priv)
+               i915_do_cleanup_pageflip(dev);
        if (dev_priv->agp_heap)
                i915_mem_takedown(&(dev_priv->agp_heap));
 
index 05c66cf03a9eb02a0da22304ab4d07d95209b16b..0431c00e2289b6e6fcf03db0c2e8d7c1107e3238 100644 (file)
@@ -105,14 +105,29 @@ typedef struct _drm_i915_sarea {
        unsigned int rotated_tiled;
        unsigned int rotated2_tiled;
 
-       int pipeA_x;
-       int pipeA_y;
-       int pipeA_w;
-       int pipeA_h;
-       int pipeB_x;
-       int pipeB_y;
-       int pipeB_w;
-       int pipeB_h;
+       int planeA_x;
+       int planeA_y;
+       int planeA_w;
+       int planeA_h;
+       int planeB_x;
+       int planeB_y;
+       int planeB_w;
+       int planeB_h;
+
+       /* Triple buffering */
+       drm_handle_t third_handle;
+       int third_offset;
+       int third_size;
+       unsigned int third_tiled;
+
+       /* buffer object handles for the static buffers.  May change
+        * over the lifetime of the client, though it doesn't in our current
+        * implementation.
+        */
+       unsigned int front_bo_handle;
+       unsigned int back_bo_handle;
+       unsigned int third_bo_handle;
+       unsigned int depth_bo_handle;
 } drm_i915_sarea_t;
 
 /* Flags for perf_boxes
@@ -146,7 +161,7 @@ typedef struct _drm_i915_sarea {
 
 #define DRM_IOCTL_I915_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
-#define DRM_IOCTL_I915_FLIP            DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP)
+#define DRM_IOCTL_I915_FLIP            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FLIP, drm_i915_flip_t)
 #define DRM_IOCTL_I915_BATCHBUFFER     DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t)
 #define DRM_IOCTL_I915_IRQ_EMIT         DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t)
 #define DRM_IOCTL_I915_IRQ_WAIT         DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t)
@@ -161,6 +176,18 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
 #define DRM_IOCTL_I915_VBLANK_SWAP     DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
 
+/* Asynchronous page flipping:
+ */
+typedef struct drm_i915_flip {
+       /*
+        * This is really talking about planes, and we could rename it
+        * except for the fact that some of the duplicated i915_drm.h files
+        * out there check for HAVE_I915_FLIP and so might pick up this
+        * version.
+        */
+       int pipes;
+} drm_i915_flip_t;
+
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
  */
index b2b451dc44608870a48cbfea56b7de522044aa40..bb8f1b2fb3835588026e00d1f961663e08e6c910 100644 (file)
@@ -533,8 +533,7 @@ static struct drm_driver driver = {
         */
        .driver_features =
            DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
-           DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
-           DRIVER_IRQ_VBL2,
+           DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
        .load = i915_driver_load,
        .unload = i915_driver_unload,
        .lastclose = i915_driver_lastclose,
@@ -542,8 +541,9 @@ static struct drm_driver driver = {
        .suspend = i915_suspend,
        .resume = i915_resume,
        .device_is_agp = i915_driver_device_is_agp,
-       .vblank_wait = i915_driver_vblank_wait,
-       .vblank_wait2 = i915_driver_vblank_wait2,
+       .get_vblank_counter = i915_get_vblank_counter,
+       .enable_vblank = i915_enable_vblank,
+       .disable_vblank = i915_disable_vblank,
        .irq_preinstall = i915_driver_irq_preinstall,
        .irq_postinstall = i915_driver_irq_postinstall,
        .irq_uninstall = i915_driver_irq_uninstall,
index 675d88bda066312f5092a8e9b5443b31e76910d4..c614d78b3dfdfca2a69ba4bc5ee8c85e376760f1 100644 (file)
@@ -76,8 +76,9 @@ struct mem_block {
 typedef struct _drm_i915_vbl_swap {
        struct list_head head;
        drm_drawable_t drw_id;
-       unsigned int pipe;
+       unsigned int plane;
        unsigned int sequence;
+       int flip;
 } drm_i915_vbl_swap_t;
 
 typedef struct drm_i915_private {
@@ -90,7 +91,7 @@ typedef struct drm_i915_private {
        drm_dma_handle_t *status_page_dmah;
        void *hw_status_page;
        dma_addr_t dma_status_page;
-       unsigned long counter;
+       uint32_t counter;
        unsigned int status_gfx_addr;
        drm_local_map_t hws_map;
 
@@ -103,13 +104,18 @@ typedef struct drm_i915_private {
 
        wait_queue_head_t irq_queue;
        atomic_t irq_received;
-       atomic_t irq_emitted;
+       atomic_t irq_emited;
 
        int tex_lru_log_granularity;
        int allow_batchbuffer;
        struct mem_block *agp_heap;
        unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
        int vblank_pipe;
+       spinlock_t user_irq_lock;
+       int user_irq_refcount;
+       int fence_irq_on;
+       uint32_t irq_enable_reg;
+       int irq_enabled;
 
        spinlock_t swaps_lock;
        drm_i915_vbl_swap_t vbl_swaps;
@@ -216,7 +222,7 @@ extern void i915_driver_preclose(struct drm_device *dev,
 extern int i915_driver_device_is_agp(struct drm_device * dev);
 extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
                              unsigned long arg);
-
+extern void i915_dispatch_flip(struct drm_device * dev, int pipes, int sync);
 /* i915_irq.c */
 extern int i915_irq_emit(struct drm_device *dev, void *data,
                         struct drm_file *file_priv);
@@ -227,7 +233,7 @@ extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequenc
 extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
 extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
 extern void i915_driver_irq_preinstall(struct drm_device * dev);
-extern void i915_driver_irq_postinstall(struct drm_device * dev);
+extern int i915_driver_irq_postinstall(struct drm_device * dev);
 extern void i915_driver_irq_uninstall(struct drm_device * dev);
 extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
                                struct drm_file *file_priv);
@@ -235,6 +241,9 @@ extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
                                struct drm_file *file_priv);
 extern int i915_vblank_swap(struct drm_device *dev, void *data,
                            struct drm_file *file_priv);
+extern int i915_enable_vblank(struct drm_device *dev, int crtc);
+extern void i915_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
 
 /* i915_mem.c */
 extern int i915_mem_alloc(struct drm_device *dev, void *data,
@@ -379,21 +388,91 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 
 /* Interrupt bits:
  */
-#define USER_INT_FLAG    (1<<1)
-#define VSYNC_PIPEB_FLAG (1<<5)
-#define VSYNC_PIPEA_FLAG (1<<7)
-#define HWB_OOM_FLAG     (1<<13) /* binner out of memory */
+#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT             (1<<18)
+#define I915_DISPLAY_PORT_INTERRUPT                    (1<<17)
+#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT     (1<<15)
+#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT       (1<<14)
+#define I915_HWB_OOM_INTERRUPT                         (1<<13) /* binner out of memory */
+#define I915_SYNC_STATUS_INTERRUPT                     (1<<12)
+#define I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT    (1<<11)
+#define I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT    (1<<10)
+#define I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT      (1<<9)
+#define I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT    (1<<8)
+#define I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT           (1<<7)
+#define I915_DISPLAY_PIPE_A_EVENT_INTERRUPT            (1<<6)
+#define I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT           (1<<5)
+#define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT            (1<<4)
+#define I915_DEBUG_INTERRUPT                           (1<<2)
+#define I915_USER_INTERRUPT                            (1<<1)
+
 
 #define I915REG_HWSTAM         0x02098
 #define I915REG_INT_IDENTITY_R 0x020a4
 #define I915REG_INT_MASK_R     0x020a8
 #define I915REG_INT_ENABLE_R   0x020a0
+#define I915REG_INSTPM         0x020c0
+
+#define PIPEADSL               0x70000
+#define PIPEBDSL               0x71000
 
 #define I915REG_PIPEASTAT      0x70024
 #define I915REG_PIPEBSTAT      0x71024
+/*
+ * The two pipe frame counter registers are not synchronized, so
+ * reading a stable value is somewhat tricky. The following code
+ * should work:
+ *
+ *  do {
+ *    high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
+ *             PIPE_FRAME_HIGH_SHIFT;
+ *    low1 =  ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >>
+ *             PIPE_FRAME_LOW_SHIFT);
+ *    high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
+ *             PIPE_FRAME_HIGH_SHIFT);
+ *  } while (high1 != high2);
+ *  frame = (high1 << 8) | low1;
+ */
+#define PIPEAFRAMEHIGH          0x70040
+#define PIPEBFRAMEHIGH         0x71040
+#define PIPE_FRAME_HIGH_MASK    0x0000ffff
+#define PIPE_FRAME_HIGH_SHIFT   0
+#define PIPEAFRAMEPIXEL         0x70044
+#define PIPEBFRAMEPIXEL                0x71044
 
-#define I915_VBLANK_INTERRUPT_ENABLE   (1UL<<17)
-#define I915_VBLANK_CLEAR              (1UL<<1)
+#define PIPE_FRAME_LOW_MASK     0xff000000
+#define PIPE_FRAME_LOW_SHIFT    24
+/*
+ * Pixel within the current frame is counted in the PIPEAFRAMEPIXEL register
+ * and is 24 bits wide.
+ */
+#define PIPE_PIXEL_MASK         0x00ffffff
+#define PIPE_PIXEL_SHIFT        0
+
+#define I915_FIFO_UNDERRUN_STATUS              (1UL<<31)
+#define I915_CRC_ERROR_ENABLE                  (1UL<<29)
+#define I915_CRC_DONE_ENABLE                   (1UL<<28)
+#define I915_GMBUS_EVENT_ENABLE                        (1UL<<27)
+#define I915_VSYNC_INTERRUPT_ENABLE            (1UL<<25)
+#define I915_DISPLAY_LINE_COMPARE_ENABLE       (1UL<<24)
+#define I915_DPST_EVENT_ENABLE                 (1UL<<23)
+#define I915_LEGACY_BLC_EVENT_ENABLE           (1UL<<22)
+#define I915_ODD_FIELD_INTERRUPT_ENABLE                (1UL<<21)
+#define I915_EVEN_FIELD_INTERRUPT_ENABLE       (1UL<<20)
+#define I915_START_VBLANK_INTERRUPT_ENABLE     (1UL<<18)       /* 965 or later */
+#define I915_VBLANK_INTERRUPT_ENABLE           (1UL<<17)
+#define I915_OVERLAY_UPDATED_ENABLE            (1UL<<16)
+#define I915_CRC_ERROR_INTERRUPT_STATUS                (1UL<<13)
+#define I915_CRC_DONE_INTERRUPT_STATUS         (1UL<<12)
+#define I915_GMBUS_INTERRUPT_STATUS            (1UL<<11)
+#define I915_VSYNC_INTERRUPT_STATUS            (1UL<<9)
+#define I915_DISPLAY_LINE_COMPARE_STATUS       (1UL<<8)
+#define I915_DPST_EVENT_STATUS                 (1UL<<7)
+#define I915_LEGACY_BLC_EVENT_STATUS           (1UL<<6)
+#define I915_ODD_FIELD_INTERRUPT_STATUS                (1UL<<5)
+#define I915_EVEN_FIELD_INTERRUPT_STATUS       (1UL<<4)
+#define I915_START_VBLANK_INTERRUPT_STATUS     (1UL<<2)        /* 965 or later */
+#define I915_VBLANK_INTERRUPT_STATUS           (1UL<<1)
+#define I915_OVERLAY_UPDATED_STATUS            (1UL<<0)
 
 #define SRX_INDEX              0x3c4
 #define SRX_DATA               0x3c5
@@ -566,6 +645,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 #define XY_SRC_COPY_BLT_CMD            ((2<<29)|(0x53<<22)|6)
 #define XY_SRC_COPY_BLT_WRITE_ALPHA    (1<<21)
 #define XY_SRC_COPY_BLT_WRITE_RGB      (1<<20)
+#define XY_SRC_COPY_BLT_SRC_TILED      (1<<15)
+#define XY_SRC_COPY_BLT_DST_TILED      (1<<11)
 
 #define MI_BATCH_BUFFER                ((0x30<<23)|1)
 #define MI_BATCH_BUFFER_START  (0x31<<23)
index 92653b38e64c5e26b5306811f6e32be1d54e16a1..023ce66ef3ab2f8858b3946f9777484836c8a799 100644 (file)
 
 #define MAX_NOPID ((u32)~0)
 
+/**
+ * i915_get_pipe - return the the pipe associated with a given plane
+ * @dev: DRM device
+ * @plane: plane to look for
+ *
+ * The Intel Mesa & 2D drivers call the vblank routines with a plane number
+ * rather than a pipe number, since they may not always be equal.  This routine
+ * maps the given @plane back to a pipe number.
+ */
+static int
+i915_get_pipe(struct drm_device *dev, int plane)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       u32 dspcntr;
+
+       dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR);
+
+       return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0;
+}
+
+/**
+ * i915_get_plane - return the the plane associated with a given pipe
+ * @dev: DRM device
+ * @pipe: pipe to look for
+ *
+ * The Intel Mesa & 2D drivers call the vblank routines with a plane number
+ * rather than a plane number, since they may not always be equal.  This routine
+ * maps the given @pipe back to a plane number.
+ */
+static int
+i915_get_plane(struct drm_device *dev, int pipe)
+{
+       if (i915_get_pipe(dev, 0) == pipe)
+               return 0;
+       return 1;
+}
+
+/**
+ * i915_pipe_enabled - check if a pipe is enabled
+ * @dev: DRM device
+ * @pipe: pipe to check
+ *
+ * Reading certain registers when the pipe is disabled can hang the chip.
+ * Use this routine to make sure the PLL is running and the pipe is active
+ * before reading such registers if unsure.
+ */
+static int
+i915_pipe_enabled(struct drm_device *dev, int pipe)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;
+
+       if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
+               return 1;
+
+       return 0;
+}
+
+/**
+ * Emit a synchronous flip.
+ *
+ * This function must be called with the drawable spinlock held.
+ */
+static void
+i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw,
+                        int plane)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       u16 x1, y1, x2, y2;
+       int pf_planes = 1 << plane;
+
+       /* If the window is visible on the other plane, we have to flip on that
+        * plane as well.
+        */
+       if (plane == 1) {
+               x1 = sarea_priv->planeA_x;
+               y1 = sarea_priv->planeA_y;
+               x2 = x1 + sarea_priv->planeA_w;
+               y2 = y1 + sarea_priv->planeA_h;
+       } else {
+               x1 = sarea_priv->planeB_x;
+               y1 = sarea_priv->planeB_y;
+               x2 = x1 + sarea_priv->planeB_w;
+               y2 = y1 + sarea_priv->planeB_h;
+       }
+
+       if (x2 > 0 && y2 > 0) {
+               int i, num_rects = drw->num_rects;
+               struct drm_clip_rect *rect = drw->rects;
+
+               for (i = 0; i < num_rects; i++)
+                       if (!(rect[i].x1 >= x2 || rect[i].y1 >= y2 ||
+                             rect[i].x2 <= x1 || rect[i].y2 <= y1)) {
+                               pf_planes = 0x3;
+
+                               break;
+                       }
+       }
+
+       i915_dispatch_flip(dev, pf_planes, 1);
+}
+
 /**
  * Emit blits for scheduled buffer swaps.
  *
 static void i915_vblank_tasklet(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       unsigned long irqflags;
        struct list_head *list, *tmp, hits, *hit;
-       int nhits, nrects, slice[2], upper[2], lower[2], i;
-       unsigned counter[2] = { atomic_read(&dev->vbl_received),
-                               atomic_read(&dev->vbl_received2) };
+       int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages;
+       unsigned counter[2];
        struct drm_drawable_info *drw;
        drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       u32 cpp = dev_priv->cpp;
+       u32 cpp = dev_priv->cpp,  offsets[3];
        u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
                                XY_SRC_COPY_BLT_WRITE_ALPHA |
                                XY_SRC_COPY_BLT_WRITE_RGB)
                             : XY_SRC_COPY_BLT_CMD;
-       u32 pitchropcpp = (sarea_priv->pitch * cpp) | (0xcc << 16) |
-                         (cpp << 23) | (1 << 24);
+       u32 src_pitch = sarea_priv->pitch * cpp;
+       u32 dst_pitch = sarea_priv->pitch * cpp;
+       /* COPY rop (0xcc), map cpp to magic color depth constants */
+       u32 ropcpp = (0xcc << 16) | ((cpp - 1) << 24);
        RING_LOCALS;
 
+       if (sarea_priv->front_tiled) {
+               cmd |= XY_SRC_COPY_BLT_DST_TILED;
+               dst_pitch >>= 2;
+       }
+       if (sarea_priv->back_tiled) {
+               cmd |= XY_SRC_COPY_BLT_SRC_TILED;
+               src_pitch >>= 2;
+       }
+
+       counter[0] = drm_vblank_count(dev, 0);
+       counter[1] = drm_vblank_count(dev, 1);
+
        DRM_DEBUG("\n");
 
        INIT_LIST_HEAD(&hits);
 
        nhits = nrects = 0;
 
-       spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+       /* No irqsave/restore necessary.  This tasklet may be run in an
+        * interrupt context or normal context, but we don't have to worry
+        * about getting interrupted by something acquiring the lock, because
+        * we are the interrupt context thing that acquires the lock.
+        */
+       spin_lock(&dev_priv->swaps_lock);
 
        /* Find buffer swaps scheduled for this vertical blank */
        list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
                drm_i915_vbl_swap_t *vbl_swap =
                        list_entry(list, drm_i915_vbl_swap_t, head);
+               int pipe = i915_get_pipe(dev, vbl_swap->plane);
 
-               if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23))
+               if ((counter[pipe] - vbl_swap->sequence) > (1<<23))
                        continue;
 
                list_del(list);
                dev_priv->swaps_pending--;
+               drm_vblank_put(dev, pipe);
 
                spin_unlock(&dev_priv->swaps_lock);
                spin_lock(&dev->drw_lock);
@@ -116,33 +238,23 @@ static void i915_vblank_tasklet(struct drm_device *dev)
                spin_lock(&dev_priv->swaps_lock);
        }
 
-       if (nhits == 0) {
-               spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
-               return;
-       }
-
        spin_unlock(&dev_priv->swaps_lock);
 
-       i915_kernel_lost_context(dev);
-
-       BEGIN_LP_RING(6);
-
-       OUT_RING(GFX_OP_DRAWRECT_INFO);
-       OUT_RING(0);
-       OUT_RING(0);
-       OUT_RING(sarea_priv->width | sarea_priv->height << 16);
-       OUT_RING(sarea_priv->width | sarea_priv->height << 16);
-       OUT_RING(0);
-
-       ADVANCE_LP_RING();
+       if (nhits == 0)
+               return;
 
-       sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
+       i915_kernel_lost_context(dev);
 
        upper[0] = upper[1] = 0;
-       slice[0] = max(sarea_priv->pipeA_h / nhits, 1);
-       slice[1] = max(sarea_priv->pipeB_h / nhits, 1);
-       lower[0] = sarea_priv->pipeA_y + slice[0];
-       lower[1] = sarea_priv->pipeB_y + slice[0];
+       slice[0] = max(sarea_priv->planeA_h / nhits, 1);
+       slice[1] = max(sarea_priv->planeB_h / nhits, 1);
+       lower[0] = sarea_priv->planeA_y + slice[0];
+       lower[1] = sarea_priv->planeB_y + slice[0];
+
+       offsets[0] = sarea_priv->front_offset;
+       offsets[1] = sarea_priv->back_offset;
+       offsets[2] = sarea_priv->third_offset;
+       num_pages = sarea_priv->third_handle ? 3 : 2;
 
        spin_lock(&dev->drw_lock);
 
@@ -154,6 +266,8 @@ static void i915_vblank_tasklet(struct drm_device *dev)
        for (i = 0; i++ < nhits;
             upper[0] = lower[0], lower[0] += slice[0],
             upper[1] = lower[1], lower[1] += slice[1]) {
+               int init_drawrect = 1;
+
                if (i == nhits)
                        lower[0] = lower[1] = sarea_priv->height;
 
@@ -161,7 +275,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
                        drm_i915_vbl_swap_t *swap_hit =
                                list_entry(hit, drm_i915_vbl_swap_t, head);
                        struct drm_clip_rect *rect;
-                       int num_rects, pipe;
+                       int num_rects, plane, front, back;
                        unsigned short top, bottom;
 
                        drw = drm_get_drawable_info(dev, swap_hit->drw_id);
@@ -169,10 +283,50 @@ static void i915_vblank_tasklet(struct drm_device *dev)
                        if (!drw)
                                continue;
 
+                       plane = swap_hit->plane;
+
+                       if (swap_hit->flip) {
+                               i915_dispatch_vsync_flip(dev, drw, plane);
+                               continue;
+                       }
+
+                       if (init_drawrect) {
+                               int width  = sarea_priv->width;
+                               int height = sarea_priv->height;
+                               if (IS_I965G(dev)) {
+                                       BEGIN_LP_RING(4);
+
+                                       OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
+                                       OUT_RING(0);
+                                       OUT_RING(((width - 1) & 0xffff) | ((height - 1) << 16));
+                                       OUT_RING(0);
+
+                                       ADVANCE_LP_RING();
+                               } else {
+                                       BEGIN_LP_RING(6);
+
+                                       OUT_RING(GFX_OP_DRAWRECT_INFO);
+                                       OUT_RING(0);
+                                       OUT_RING(0);
+                                       OUT_RING(((width - 1) & 0xffff) | ((height - 1) << 16));
+                                       OUT_RING(0);
+                                       OUT_RING(0);
+
+                                       ADVANCE_LP_RING();
+                               }
+
+                               sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
+
+                               init_drawrect = 0;
+                       }
+
                        rect = drw->rects;
-                       pipe = swap_hit->pipe;
-                       top = upper[pipe];
-                       bottom = lower[pipe];
+                       top = upper[plane];
+                       bottom = lower[plane];
+
+                       front = (dev_priv->sarea_priv->pf_current_page >>
+                                (2 * plane)) & 0x3;
+                       back = (front + 1) % num_pages;
 
                        for (num_rects = drw->num_rects; num_rects--; rect++) {
                                int y1 = max(rect->y1, top);
@@ -184,20 +338,20 @@ static void i915_vblank_tasklet(struct drm_device *dev)
                                BEGIN_LP_RING(8);
 
                                OUT_RING(cmd);
-                               OUT_RING(pitchropcpp);
+                               OUT_RING(ropcpp | dst_pitch);
                                OUT_RING((y1 << 16) | rect->x1);
                                OUT_RING((y2 << 16) | rect->x2);
-                               OUT_RING(sarea_priv->front_offset);
+                               OUT_RING(offsets[front]);
                                OUT_RING((y1 << 16) | rect->x1);
-                               OUT_RING(pitchropcpp & 0xffff);
-                               OUT_RING(sarea_priv->back_offset);
+                               OUT_RING(src_pitch);
+                               OUT_RING(offsets[back]);
 
                                ADVANCE_LP_RING();
                        }
                }
        }
 
-       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+       spin_unlock(&dev->drw_lock);
 
        list_for_each_safe(hit, tmp, &hits) {
                drm_i915_vbl_swap_t *swap_hit =
@@ -209,67 +363,112 @@ static void i915_vblank_tasklet(struct drm_device *dev)
        }
 }
 
+u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       unsigned long high_frame;
+       unsigned long low_frame;
+       u32 high1, high2, low, count;
+       int pipe;
+
+       pipe = i915_get_pipe(dev, plane);
+       high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
+       low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
+
+       if (!i915_pipe_enabled(dev, pipe)) {
+           printk(KERN_ERR "trying to get vblank count for disabled "
+                  "pipe %d\n", pipe);
+           return 0;
+       }
+
+       /*
+        * High & low register fields aren't synchronized, so make sure
+        * we get a low value that's stable across two reads of the high
+        * register.
+        */
+       do {
+               high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+                        PIPE_FRAME_HIGH_SHIFT);
+               low =  ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
+                       PIPE_FRAME_LOW_SHIFT);
+               high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+                        PIPE_FRAME_HIGH_SHIFT);
+       } while (high1 != high2);
+
+       count = (high1 << 8) | low;
+
+       /* count may be reset by other driver(e.g. 2D driver),
+          we have no way to know if it is wrapped or resetted
+          when count is zero. do a rough guess.
+       */
+       if (count == 0 && dev->last_vblank[pipe] < dev->max_vblank_count/2)
+               dev->last_vblank[pipe] = 0;
+
+       return count;
+}
+
 irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u16 temp;
+       u32 iir;
        u32 pipea_stats, pipeb_stats;
-
-       pipea_stats = I915_READ(I915REG_PIPEASTAT);
-       pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
-
-       temp = I915_READ16(I915REG_INT_IDENTITY_R);
-
-       temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG);
-
-       DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
-
-       if (temp == 0)
+       int vblank = 0;
+
+       iir = I915_READ(I915REG_INT_IDENTITY_R);
+       if (iir == 0) {
+               DRM_DEBUG ("iir 0x%08x im 0x%08x ie 0x%08x pipea 0x%08x pipeb 0x%08x\n",
+                          iir,
+                          I915_READ(I915REG_INT_MASK_R),
+                          I915_READ(I915REG_INT_ENABLE_R),
+                          I915_READ(I915REG_PIPEASTAT),
+                          I915_READ(I915REG_PIPEBSTAT));
                return IRQ_NONE;
+       }
 
-       I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
-       (void) I915_READ16(I915REG_INT_IDENTITY_R);
-       DRM_READMEMORYBARRIER();
-
-       dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+       /*
+        * Clear the PIPE(A|B)STAT regs before the IIR otherwise
+        * we may get extra interrupts.
+        */
+       if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
+               pipea_stats = I915_READ(I915REG_PIPEASTAT);
+               if (pipea_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
+                                  I915_VBLANK_INTERRUPT_STATUS))
+               {
+                       vblank++;
+                       drm_handle_vblank(dev, i915_get_plane(dev, 0));
+               }
+               I915_WRITE(I915REG_PIPEASTAT, pipea_stats);
+       }
+       if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
+               pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
+               if (pipeb_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
+                                  I915_VBLANK_INTERRUPT_STATUS))
+               {
+                       vblank++;
+                       drm_handle_vblank(dev, i915_get_plane(dev, 1));
+               }
+               I915_WRITE(I915REG_PIPEBSTAT, pipeb_stats);
+       }
 
-       if (temp & USER_INT_FLAG)
-               DRM_WAKEUP(&dev_priv->irq_queue);
+       if (dev_priv->sarea_priv)
+           dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
 
-       if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
-               int vblank_pipe = dev_priv->vblank_pipe;
-
-               if ((vblank_pipe &
-                    (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
-                   == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
-                       if (temp & VSYNC_PIPEA_FLAG)
-                               atomic_inc(&dev->vbl_received);
-                       if (temp & VSYNC_PIPEB_FLAG)
-                               atomic_inc(&dev->vbl_received2);
-               } else if (((temp & VSYNC_PIPEA_FLAG) &&
-                           (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
-                          ((temp & VSYNC_PIPEB_FLAG) &&
-                           (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
-                       atomic_inc(&dev->vbl_received);
-
-               DRM_WAKEUP(&dev->vbl_queue);
-               drm_vbl_send_signals(dev);
+       I915_WRITE(I915REG_INT_IDENTITY_R, iir);
+       (void) I915_READ(I915REG_INT_IDENTITY_R); /* Flush posted write */
 
+       if (iir & I915_USER_INTERRUPT) {
+               DRM_WAKEUP(&dev_priv->irq_queue);
+       }
+       if (vblank) {
                if (dev_priv->swaps_pending > 0)
                        drm_locked_tasklet(dev, i915_vblank_tasklet);
-               I915_WRITE(I915REG_PIPEASTAT,
-                       pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
-                       I915_VBLANK_CLEAR);
-               I915_WRITE(I915REG_PIPEBSTAT,
-                       pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
-                       I915_VBLANK_CLEAR);
        }
 
        return IRQ_HANDLED;
 }
 
-static int i915_emit_irq(struct drm_device * dev)
+static int i915_emit_irq(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        RING_LOCALS;
@@ -316,42 +515,12 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
                          READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
        }
 
-       dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-       return ret;
-}
-
-static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequence,
-                                     atomic_t *counter)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       unsigned int cur_vblank;
-       int ret = 0;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(counter))
-                       - *sequence) <= (1<<23)));
-
-       *sequence = cur_vblank;
-
+       if (dev_priv->sarea_priv)
+               dev_priv->sarea_priv->last_dispatch =
+                       READ_BREADCRUMB(dev_priv);
        return ret;
 }
 
-
-int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
-{
-       return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
-}
-
-int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
-{
-       return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
-}
-
 /* Needs the lock as it touches the ring.
  */
 int i915_irq_emit(struct drm_device *dev, void *data,
@@ -394,18 +563,96 @@ int i915_irq_wait(struct drm_device *dev, void *data,
        return i915_wait_irq(dev, irqwait->irq_seq);
 }
 
+int i915_enable_vblank(struct drm_device *dev, int plane)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       int pipe = i915_get_pipe(dev, plane);
+       u32     pipestat_reg = 0;
+       u32     pipestat;
+
+       switch (pipe) {
+       case 0:
+               pipestat_reg = I915REG_PIPEASTAT;
+               dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
+               break;
+       case 1:
+               pipestat_reg = I915REG_PIPEBSTAT;
+               dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
+               break;
+       default:
+               DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
+                         pipe);
+               break;
+       }
+
+       if (pipestat_reg)
+       {
+               pipestat = I915_READ (pipestat_reg);
+               /*
+                * Older chips didn't have the start vblank interrupt,
+                * but
+                */
+               if (IS_I965G (dev))
+                       pipestat |= I915_START_VBLANK_INTERRUPT_ENABLE;
+               else
+                       pipestat |= I915_VBLANK_INTERRUPT_ENABLE;
+               /*
+                * Clear any pending status
+                */
+               pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
+                            I915_VBLANK_INTERRUPT_STATUS);
+               I915_WRITE(pipestat_reg, pipestat);
+       }
+       I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+
+       return 0;
+}
+
+void i915_disable_vblank(struct drm_device *dev, int plane)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       int pipe = i915_get_pipe(dev, plane);
+       u32     pipestat_reg = 0;
+       u32     pipestat;
+
+       switch (pipe) {
+       case 0:
+               pipestat_reg = I915REG_PIPEASTAT;
+               dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
+               break;
+       case 1:
+               pipestat_reg = I915REG_PIPEBSTAT;
+               dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
+               break;
+       default:
+               DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
+                         pipe);
+               break;
+       }
+
+       I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+       if (pipestat_reg)
+       {
+               pipestat = I915_READ (pipestat_reg);
+               pipestat &= ~(I915_START_VBLANK_INTERRUPT_ENABLE |
+                             I915_VBLANK_INTERRUPT_ENABLE);
+               /*
+                * Clear any pending status
+                */
+               pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
+                            I915_VBLANK_INTERRUPT_STATUS);
+               I915_WRITE(pipestat_reg, pipestat);
+       }
+}
+
 static void i915_enable_interrupt (struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u16 flag;
 
-       flag = 0;
-       if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
-               flag |= VSYNC_PIPEA_FLAG;
-       if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
-               flag |= VSYNC_PIPEB_FLAG;
+       dev_priv->irq_enable_reg |= I915_USER_INTERRUPT;
 
-       I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag);
+       I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+       dev_priv->irq_enabled = 1;
 }
 
 /* Set the vblank monitor pipe
@@ -428,8 +675,6 @@ int i915_vblank_pipe_set(struct drm_device *dev, void *data,
 
        dev_priv->vblank_pipe = pipe->pipe;
 
-       i915_enable_interrupt (dev);
-
        return 0;
 }
 
@@ -447,9 +692,9 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data,
 
        flag = I915_READ(I915REG_INT_ENABLE_R);
        pipe->pipe = 0;
-       if (flag & VSYNC_PIPEA_FLAG)
+       if (flag & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT)
                pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
-       if (flag & VSYNC_PIPEB_FLAG)
+       if (flag & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
                pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
 
        return 0;
@@ -464,27 +709,30 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
        drm_i915_private_t *dev_priv = dev->dev_private;
        drm_i915_vblank_swap_t *swap = data;
        drm_i915_vbl_swap_t *vbl_swap;
-       unsigned int pipe, seqtype, curseq;
+       unsigned int pipe, seqtype, curseq, plane;
        unsigned long irqflags;
        struct list_head *list;
+       int ret;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __func__);
                return -EINVAL;
        }
 
-       if (dev_priv->sarea_priv->rotation) {
+       if (!dev_priv->sarea_priv || dev_priv->sarea_priv->rotation) {
                DRM_DEBUG("Rotation not supported\n");
                return -EINVAL;
        }
 
        if (swap->seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
-                            _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) {
+                            _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS |
+                            _DRM_VBLANK_FLIP)) {
                DRM_ERROR("Invalid sequence type 0x%x\n", swap->seqtype);
                return -EINVAL;
        }
 
-       pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
+       plane = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
+       pipe = i915_get_pipe(dev, plane);
 
        seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
 
@@ -495,6 +743,11 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
 
        spin_lock_irqsave(&dev->drw_lock, irqflags);
 
+       /* It makes no sense to schedule a swap for a drawable that doesn't have
+        * valid information at this point. E.g. this could mean that the X
+        * server is too old to push drawable information to the DRM, in which
+        * case all such swaps would become ineffective.
+        */
        if (!drm_get_drawable_info(dev, swap->drawable)) {
                spin_unlock_irqrestore(&dev->drw_lock, irqflags);
                DRM_DEBUG("Invalid drawable ID %d\n", swap->drawable);
@@ -503,7 +756,8 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
 
        spin_unlock_irqrestore(&dev->drw_lock, irqflags);
 
-       curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
+       drm_update_vblank_count(dev, pipe);
+       curseq = drm_vblank_count(dev, pipe);
 
        if (seqtype == _DRM_VBLANK_RELATIVE)
                swap->sequence += curseq;
@@ -517,14 +771,43 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
                }
        }
 
+       if (swap->seqtype & _DRM_VBLANK_FLIP) {
+               swap->sequence--;
+
+               if ((curseq - swap->sequence) <= (1<<23)) {
+                       struct drm_drawable_info *drw;
+
+                       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+                       spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+                       drw = drm_get_drawable_info(dev, swap->drawable);
+
+                       if (!drw) {
+                               spin_unlock_irqrestore(&dev->drw_lock,
+                                   irqflags);
+                               DRM_DEBUG("Invalid drawable ID %d\n",
+                                         swap->drawable);
+                               return -EINVAL;
+                       }
+
+                       i915_dispatch_vsync_flip(dev, drw, plane);
+
+                       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+                       return 0;
+               }
+       }
+
        spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
 
        list_for_each(list, &dev_priv->vbl_swaps.head) {
                vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
 
                if (vbl_swap->drw_id == swap->drawable &&
-                   vbl_swap->pipe == pipe &&
+                   vbl_swap->plane == plane &&
                    vbl_swap->sequence == swap->sequence) {
+                       vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
                        spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
                        DRM_DEBUG("Already scheduled\n");
                        return 0;
@@ -547,9 +830,19 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
 
        DRM_DEBUG("\n");
 
+       ret = drm_vblank_get(dev, pipe);
+       if (ret) {
+               drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
+               return ret;
+       }
+
        vbl_swap->drw_id = swap->drawable;
-       vbl_swap->pipe = pipe;
+       vbl_swap->plane = plane;
        vbl_swap->sequence = swap->sequence;
+       vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
+
+       if (vbl_swap->flip)
+               swap->sequence++;
 
        spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
 
@@ -567,37 +860,57 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
-       I915_WRITE16(I915REG_HWSTAM, 0xfffe);
+       I915_WRITE16(I915REG_HWSTAM, 0xeffe);
        I915_WRITE16(I915REG_INT_MASK_R, 0x0);
        I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
 }
 
-void i915_driver_irq_postinstall(struct drm_device * dev)
+int i915_driver_irq_postinstall(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       int ret, num_pipes = 2;
 
        spin_lock_init(&dev_priv->swaps_lock);
        INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
        dev_priv->swaps_pending = 0;
 
-       if (!dev_priv->vblank_pipe)
-               dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
+       dev_priv->user_irq_refcount = 0;
+       dev_priv->irq_enable_reg = 0;
+
+       ret = drm_vblank_init(dev, num_pipes);
+       if (ret)
+               return ret;
+
+       dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
+
        i915_enable_interrupt(dev);
        DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
+
+       /*
+        * Initialize the hardware status page IRQ location.
+        */
+
+       I915_WRITE(I915REG_INSTPM, (1 << 5) | (1 << 21));
+       return 0;
 }
 
 void i915_driver_irq_uninstall(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u16 temp;
+       u32 temp;
 
        if (!dev_priv)
                return;
 
-       I915_WRITE16(I915REG_HWSTAM, 0xffff);
-       I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
-       I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
-
-       temp = I915_READ16(I915REG_INT_IDENTITY_R);
-       I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+       dev_priv->irq_enabled = 0;
+       I915_WRITE(I915REG_HWSTAM, 0xffffffff);
+       I915_WRITE(I915REG_INT_MASK_R, 0xffffffff);
+       I915_WRITE(I915REG_INT_ENABLE_R, 0x0);
+
+       temp = I915_READ(I915REG_PIPEASTAT);
+       I915_WRITE(I915REG_PIPEASTAT, temp);
+       temp = I915_READ(I915REG_PIPEBSTAT);
+       I915_WRITE(I915REG_PIPEBSTAT, temp);
+       temp = I915_READ(I915REG_INT_IDENTITY_R);
+       I915_WRITE(I915REG_INT_IDENTITY_R, temp);
 }
index 5572939fc7d19cb1f986833a22ce79a21ad1da0a..6b3790939e762d91e7ed4c7a8bcb4d6ac6eb7f9e 100644 (file)
@@ -45,15 +45,16 @@ static struct pci_device_id pciidlist[] = {
 static struct drm_driver driver = {
        .driver_features =
            DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
-           DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
-           DRIVER_IRQ_VBL,
+           DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
        .dev_priv_size = sizeof(drm_mga_buf_priv_t),
        .load = mga_driver_load,
        .unload = mga_driver_unload,
        .lastclose = mga_driver_lastclose,
        .dma_quiescent = mga_driver_dma_quiescent,
        .device_is_agp = mga_driver_device_is_agp,
-       .vblank_wait = mga_driver_vblank_wait,
+       .get_vblank_counter = mga_get_vblank_counter,
+       .enable_vblank = mga_enable_vblank,
+       .disable_vblank = mga_disable_vblank,
        .irq_preinstall = mga_driver_irq_preinstall,
        .irq_postinstall = mga_driver_irq_postinstall,
        .irq_uninstall = mga_driver_irq_uninstall,
index f6ebd24bd5871ebad2204c64195e3e3e31219401..8f7291f36363590c3431570d78c364b81cb4bbea 100644 (file)
@@ -120,6 +120,7 @@ typedef struct drm_mga_private {
        u32 clear_cmd;
        u32 maccess;
 
+       atomic_t vbl_received;          /**< Number of vblanks received. */
        wait_queue_head_t fence_queue;
        atomic_t last_fence_retired;
        u32 next_fence_to_post;
@@ -181,11 +182,14 @@ extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
 extern int mga_warp_init(drm_mga_private_t * dev_priv);
 
                                /* mga_irq.c */
+extern int mga_enable_vblank(struct drm_device *dev, int crtc);
+extern void mga_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
 extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
 extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
 extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
 extern void mga_driver_irq_preinstall(struct drm_device * dev);
-extern void mga_driver_irq_postinstall(struct drm_device * dev);
+extern int mga_driver_irq_postinstall(struct drm_device * dev);
 extern void mga_driver_irq_uninstall(struct drm_device * dev);
 extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
                             unsigned long arg);
index 9302cb8f0f83bef1e99be219a9b977884d3f6d28..06852fb4b278fd0c5b0f3d84ff0d915858135913 100644 (file)
 #include "mga_drm.h"
 #include "mga_drv.h"
 
+u32 mga_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+       const drm_mga_private_t *const dev_priv =
+               (drm_mga_private_t *) dev->dev_private;
+
+       if (crtc != 0) {
+               return 0;
+       }
+
+
+       return atomic_read(&dev_priv->vbl_received);
+}
+
+
 irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
 {
        struct drm_device *dev = (struct drm_device *) arg;
@@ -47,9 +61,8 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
        /* VBLANK interrupt */
        if (status & MGA_VLINEPEN) {
                MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
-               atomic_inc(&dev->vbl_received);
-               DRM_WAKEUP(&dev->vbl_queue);
-               drm_vbl_send_signals(dev);
+               atomic_inc(&dev_priv->vbl_received);
+               drm_handle_vblank(dev, 0);
                handled = 1;
        }
 
@@ -78,22 +91,34 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
        return IRQ_NONE;
 }
 
-int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+int mga_enable_vblank(struct drm_device *dev, int crtc)
 {
-       unsigned int cur_vblank;
-       int ret = 0;
+       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 
-       /* Assume that the user has missed the current sequence number
-        * by about a day rather than she wants to wait for years
-        * using vertical blanks...
-        */
-       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(&dev->vbl_received))
-                     - *sequence) <= (1 << 23)));
+       if (crtc != 0) {
+               DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+                         crtc);
+               return 0;
+       }
 
-       *sequence = cur_vblank;
+       MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
+       return 0;
+}
 
-       return ret;
+
+void mga_disable_vblank(struct drm_device *dev, int crtc)
+{
+       if (crtc != 0) {
+               DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
+                         crtc);
+       }
+
+       /* Do *NOT* disable the vertical refresh interrupt.  MGA doesn't have
+        * a nice hardware counter that tracks the number of refreshes when
+        * the interrupt is disabled, and the kernel doesn't know the refresh
+        * rate to calculate an estimate.
+        */
+       /* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */
 }
 
 int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
@@ -125,14 +150,22 @@ void mga_driver_irq_preinstall(struct drm_device * dev)
        MGA_WRITE(MGA_ICLEAR, ~0);
 }
 
-void mga_driver_irq_postinstall(struct drm_device * dev)
+int mga_driver_irq_postinstall(struct drm_device * dev)
 {
        drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+       int ret;
+
+       ret = drm_vblank_init(dev, 1);
+       if (ret)
+               return ret;
 
        DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
 
-       /* Turn on vertical blank interrupt and soft trap interrupt. */
-       MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
+       /* Turn on soft trap interrupt.  Vertical blank interrupts are enabled
+        * in mga_enable_vblank.
+        */
+       MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN);
+       return 0;
 }
 
 void mga_driver_irq_uninstall(struct drm_device * dev)
index 6108e7587e12470daba9576ef185458f5fc545c1..2888aa01ebc78779c28a63a63a1382108d33e8e4 100644 (file)
@@ -43,12 +43,13 @@ static struct pci_device_id pciidlist[] = {
 static struct drm_driver driver = {
        .driver_features =
            DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
-           DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
-           DRIVER_IRQ_VBL,
+           DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
        .dev_priv_size = sizeof(drm_r128_buf_priv_t),
        .preclose = r128_driver_preclose,
        .lastclose = r128_driver_lastclose,
-       .vblank_wait = r128_driver_vblank_wait,
+       .get_vblank_counter = r128_get_vblank_counter,
+       .enable_vblank = r128_enable_vblank,
+       .disable_vblank = r128_disable_vblank,
        .irq_preinstall = r128_driver_irq_preinstall,
        .irq_postinstall = r128_driver_irq_postinstall,
        .irq_uninstall = r128_driver_irq_uninstall,
index 011105e51ac660117c88a1e1a3d9db860702b325..80af9e09e75da49610fb54b1539022df20d789bd 100644 (file)
@@ -97,6 +97,8 @@ typedef struct drm_r128_private {
        u32 crtc_offset;
        u32 crtc_offset_cntl;
 
+       atomic_t vbl_received;
+
        u32 color_fmt;
        unsigned int front_offset;
        unsigned int front_pitch;
@@ -149,11 +151,12 @@ extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
 extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
 extern int r128_do_cleanup_cce(struct drm_device * dev);
 
-extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
-
+extern int r128_enable_vblank(struct drm_device *dev, int crtc);
+extern void r128_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 r128_get_vblank_counter(struct drm_device *dev, int crtc);
 extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
 extern void r128_driver_irq_preinstall(struct drm_device * dev);
-extern void r128_driver_irq_postinstall(struct drm_device * dev);
+extern int r128_driver_irq_postinstall(struct drm_device * dev);
 extern void r128_driver_irq_uninstall(struct drm_device * dev);
 extern void r128_driver_lastclose(struct drm_device * dev);
 extern void r128_driver_preclose(struct drm_device * dev,
index c76fdca7662d78bcdb0cb83684ce2c9005a471c2..5b95bd898f95c54128d6238e34a68b7a7b713865 100644 (file)
 #include "r128_drm.h"
 #include "r128_drv.h"
 
+u32 r128_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+       const drm_r128_private_t *dev_priv = dev->dev_private;
+
+       if (crtc != 0)
+               return 0;
+
+       return atomic_read(&dev_priv->vbl_received);
+}
+
 irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
 {
        struct drm_device *dev = (struct drm_device *) arg;
@@ -46,30 +56,38 @@ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
        /* VBLANK interrupt */
        if (status & R128_CRTC_VBLANK_INT) {
                R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
-               atomic_inc(&dev->vbl_received);
-               DRM_WAKEUP(&dev->vbl_queue);
-               drm_vbl_send_signals(dev);
+               atomic_inc(&dev_priv->vbl_received);
+               drm_handle_vblank(dev, 0);
                return IRQ_HANDLED;
        }
        return IRQ_NONE;
 }
 
-int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+int r128_enable_vblank(struct drm_device *dev, int crtc)
 {
-       unsigned int cur_vblank;
-       int ret = 0;
+       drm_r128_private_t *dev_priv = dev->dev_private;
 
-       /* Assume that the user has missed the current sequence number
-        * by about a day rather than she wants to wait for years
-        * using vertical blanks...
-        */
-       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(&dev->vbl_received))
-                     - *sequence) <= (1 << 23)));
+       if (crtc != 0) {
+               DRM_ERROR("%s:  bad crtc %d\n", __FUNCTION__, crtc);
+               return -EINVAL;
+       }
 
-       *sequence = cur_vblank;
+       R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
+       return 0;
+}
+
+void r128_disable_vblank(struct drm_device *dev, int crtc)
+{
+       if (crtc != 0)
+               DRM_ERROR("%s:  bad crtc %d\n", __FUNCTION__, crtc);
 
-       return ret;
+       /*
+        * FIXME: implement proper interrupt disable by using the vblank
+        * counter register (if available)
+        *
+        * R128_WRITE(R128_GEN_INT_CNTL,
+        *            R128_READ(R128_GEN_INT_CNTL) & ~R128_CRTC_VBLANK_INT_EN);
+        */
 }
 
 void r128_driver_irq_preinstall(struct drm_device * dev)
@@ -82,12 +100,9 @@ void r128_driver_irq_preinstall(struct drm_device * dev)
        R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
 }
 
-void r128_driver_irq_postinstall(struct drm_device * dev)
+int r128_driver_irq_postinstall(struct drm_device * dev)
 {
-       drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
-
-       /* Turn on VBL interrupt */
-       R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
+       return drm_vblank_init(dev, 1);
 }
 
 void r128_driver_irq_uninstall(struct drm_device * dev)
index 349ac3d3b8480c13d91c850f917819774f92edbf..a2610319624d3509fe98d9e1c93215357b586160 100644 (file)
@@ -59,8 +59,7 @@ static struct pci_device_id pciidlist[] = {
 static struct drm_driver driver = {
        .driver_features =
            DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
-           DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
-           DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
+           DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED,
        .dev_priv_size = sizeof(drm_radeon_buf_priv_t),
        .load = radeon_driver_load,
        .firstopen = radeon_driver_firstopen,
@@ -69,8 +68,9 @@ static struct drm_driver driver = {
        .postclose = radeon_driver_postclose,
        .lastclose = radeon_driver_lastclose,
        .unload = radeon_driver_unload,
-       .vblank_wait = radeon_driver_vblank_wait,
-       .vblank_wait2 = radeon_driver_vblank_wait2,
+       .get_vblank_counter = radeon_get_vblank_counter,
+       .enable_vblank = radeon_enable_vblank,
+       .disable_vblank = radeon_disable_vblank,
        .dri_library_name = dri_library_name,
        .irq_preinstall = radeon_driver_irq_preinstall,
        .irq_postinstall = radeon_driver_irq_postinstall,
index 173ae620223a052238a0a212711e25290bff4f0c..b791420bd3d98f4886a1d95e3ebf863282133f13 100644 (file)
@@ -304,6 +304,9 @@ typedef struct drm_radeon_private {
 
        u32 scratch_ages[5];
 
+       unsigned int crtc_last_cnt;
+       unsigned int crtc2_last_cnt;
+
        /* starting from here on, data is preserved accross an open */
        uint32_t flags;         /* see radeon_chip_flags */
        unsigned long fb_aper_offset;
@@ -374,13 +377,13 @@ extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *
 extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv);
 
 extern void radeon_do_release(struct drm_device * dev);
-extern int radeon_driver_vblank_wait(struct drm_device * dev,
-                                    unsigned int *sequence);
-extern int radeon_driver_vblank_wait2(struct drm_device * dev,
-                                     unsigned int *sequence);
+extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc);
+extern int radeon_enable_vblank(struct drm_device *dev, int crtc);
+extern void radeon_disable_vblank(struct drm_device *dev, int crtc);
+extern void radeon_do_release(struct drm_device * dev);
 extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
 extern void radeon_driver_irq_preinstall(struct drm_device * dev);
-extern void radeon_driver_irq_postinstall(struct drm_device * dev);
+extern int radeon_driver_irq_postinstall(struct drm_device * dev);
 extern void radeon_driver_irq_uninstall(struct drm_device * dev);
 extern int radeon_vblank_crtc_get(struct drm_device *dev);
 extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
@@ -558,6 +561,12 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev,
                                ? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \
                                : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
 
+#define RADEON_CRTC_CRNT_FRAME 0x0214
+#define RADEON_CRTC2_CRNT_FRAME 0x0314
+
+#define RADEON_CRTC_STATUS             0x005c
+#define RADEON_CRTC2_STATUS            0x03fc
+
 #define RADEON_GEN_INT_CNTL            0x0040
 #      define RADEON_CRTC_VBLANK_MASK          (1 << 0)
 #      define RADEON_CRTC2_VBLANK_MASK         (1 << 9)
index 009af3814b6f12ec4dcf34aff23cffff79e0d5db..507d6b747a13139cf3aeeb8e0a4f8339a950eaab 100644 (file)
 #include "radeon_drm.h"
 #include "radeon_drv.h"
 
-static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
-                                             u32 mask)
+static void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state)
 {
-       u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+
+       if (state)
+               dev_priv->irq_enable_reg |= mask;
+       else
+               dev_priv->irq_enable_reg &= ~mask;
+
+       RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
+}
+
+int radeon_enable_vblank(struct drm_device *dev, int crtc)
+{
+       switch (crtc) {
+       case 0:
+               radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1);
+               break;
+       case 1:
+               radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1);
+               break;
+       default:
+               DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+                         crtc);
+               return EINVAL;
+       }
+
+       return 0;
+}
+
+void radeon_disable_vblank(struct drm_device *dev, int crtc)
+{
+       switch (crtc) {
+       case 0:
+               radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0);
+               break;
+       case 1:
+               radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0);
+               break;
+       default:
+               DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+                         crtc);
+               break;
+       }
+}
+
+static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv)
+{
+       u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) &
+               (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT |
+                RADEON_CRTC2_VBLANK_STAT);
+
        if (irqs)
                RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
+
        return irqs;
 }
 
@@ -72,39 +121,21 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
        /* Only consider the bits we're interested in - others could be used
         * outside the DRM
         */
-       stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
-                                                 RADEON_CRTC_VBLANK_STAT |
-                                                 RADEON_CRTC2_VBLANK_STAT));
+       stat = radeon_acknowledge_irqs(dev_priv);
        if (!stat)
                return IRQ_NONE;
 
        stat &= dev_priv->irq_enable_reg;
 
        /* SW interrupt */
-       if (stat & RADEON_SW_INT_TEST) {
+       if (stat & RADEON_SW_INT_TEST)
                DRM_WAKEUP(&dev_priv->swi_queue);
-       }
 
        /* VBLANK interrupt */
-       if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
-               int vblank_crtc = dev_priv->vblank_crtc;
-
-               if ((vblank_crtc &
-                    (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
-                   (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
-                       if (stat & RADEON_CRTC_VBLANK_STAT)
-                               atomic_inc(&dev->vbl_received);
-                       if (stat & RADEON_CRTC2_VBLANK_STAT)
-                               atomic_inc(&dev->vbl_received2);
-               } else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
-                          (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
-                          ((stat & RADEON_CRTC2_VBLANK_STAT) &&
-                           (vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
-                       atomic_inc(&dev->vbl_received);
-
-               DRM_WAKEUP(&dev->vbl_queue);
-               drm_vbl_send_signals(dev);
-       }
+       if (stat & RADEON_CRTC_VBLANK_STAT)
+               drm_handle_vblank(dev, 0);
+       if (stat & RADEON_CRTC2_VBLANK_STAT)
+               drm_handle_vblank(dev, 1);
 
        return IRQ_HANDLED;
 }
@@ -144,54 +175,27 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
        return ret;
 }
 
-static int radeon_driver_vblank_do_wait(struct drm_device * dev,
-                                       unsigned int *sequence, int crtc)
+u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc)
 {
-       drm_radeon_private_t *dev_priv =
-           (drm_radeon_private_t *) dev->dev_private;
-       unsigned int cur_vblank;
-       int ret = 0;
-       int ack = 0;
-       atomic_t *counter;
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       u32 crtc_cnt_reg, crtc_status_reg;
+
        if (!dev_priv) {
                DRM_ERROR("called with no initialization\n");
                return -EINVAL;
        }
 
-       if (crtc == DRM_RADEON_VBLANK_CRTC1) {
-               counter = &dev->vbl_received;
-               ack |= RADEON_CRTC_VBLANK_STAT;
-       } else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
-               counter = &dev->vbl_received2;
-               ack |= RADEON_CRTC2_VBLANK_STAT;
-       } else
+       if (crtc == 0) {
+               crtc_cnt_reg = RADEON_CRTC_CRNT_FRAME;
+               crtc_status_reg = RADEON_CRTC_STATUS;
+       } else if (crtc == 1) {
+               crtc_cnt_reg = RADEON_CRTC2_CRNT_FRAME;
+               crtc_status_reg = RADEON_CRTC2_STATUS;
+       } else {
                return -EINVAL;
+       }
 
-       radeon_acknowledge_irqs(dev_priv, ack);
-
-       dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
-       /* Assume that the user has missed the current sequence number
-        * by about a day rather than she wants to wait for years
-        * using vertical blanks...
-        */
-       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(counter))
-                     - *sequence) <= (1 << 23)));
-
-       *sequence = cur_vblank;
-
-       return ret;
-}
-
-int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
-{
-       return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
-}
-
-int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
-{
-       return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
+       return RADEON_READ(crtc_cnt_reg) + (RADEON_READ(crtc_status_reg) & 1);
 }
 
 /* Needs the lock as it touches the ring.
@@ -234,21 +238,6 @@ int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_pr
        return radeon_wait_irq(dev, irqwait->irq_seq);
 }
 
-static void radeon_enable_interrupt(struct drm_device *dev)
-{
-       drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
-
-       dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
-       if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
-               dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
-
-       if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
-               dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
-
-       RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
-       dev_priv->irq_enabled = 1;
-}
-
 /* drm_dma.h hooks
 */
 void radeon_driver_irq_preinstall(struct drm_device * dev)
@@ -260,20 +249,27 @@ void radeon_driver_irq_preinstall(struct drm_device * dev)
        RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
 
        /* Clear bits if they're already high */
-       radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
-                                          RADEON_CRTC_VBLANK_STAT |
-                                          RADEON_CRTC2_VBLANK_STAT));
+       radeon_acknowledge_irqs(dev_priv);
 }
 
-void radeon_driver_irq_postinstall(struct drm_device * dev)
+int radeon_driver_irq_postinstall(struct drm_device * dev)
 {
        drm_radeon_private_t *dev_priv =
            (drm_radeon_private_t *) dev->dev_private;
+       int ret;
 
        atomic_set(&dev_priv->swi_emitted, 0);
        DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
 
-       radeon_enable_interrupt(dev);
+       ret = drm_vblank_init(dev, 2);
+       if (ret)
+               return ret;
+
+       dev->max_vblank_count = 0x001fffff;
+
+       radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
+
+       return 0;
 }
 
 void radeon_driver_irq_uninstall(struct drm_device * dev)
@@ -315,6 +311,5 @@ int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
                return -EINVAL;
        }
        dev_priv->vblank_crtc = (unsigned int)value;
-       radeon_enable_interrupt(dev);
        return 0;
 }
index 80c01cdfa37d54db94ec5a382f83ec4e6b026432..37870a4a3dc729877a4d659018260778783982ce 100644 (file)
@@ -40,11 +40,13 @@ static struct pci_device_id pciidlist[] = {
 static struct drm_driver driver = {
        .driver_features =
            DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
-           DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+           DRIVER_IRQ_SHARED,
        .load = via_driver_load,
        .unload = via_driver_unload,
        .context_dtor = via_final_context,
-       .vblank_wait = via_driver_vblank_wait,
+       .get_vblank_counter = via_get_vblank_counter,
+       .enable_vblank = via_enable_vblank,
+       .disable_vblank = via_disable_vblank,
        .irq_preinstall = via_driver_irq_preinstall,
        .irq_postinstall = via_driver_irq_postinstall,
        .irq_uninstall = via_driver_irq_uninstall,
index 2daae81874cdd049fdcd2ff9f0783eb15994fb53..fe67030e39ac6b8f3dadb3624fe23a6bed7a958a 100644 (file)
@@ -75,6 +75,7 @@ typedef struct drm_via_private {
        struct timeval last_vblank;
        int last_vblank_valid;
        unsigned usec_per_vblank;
+       atomic_t vbl_received;
        drm_via_state_t hc_state;
        char pci_buf[VIA_PCI_BUF_SIZE];
        const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
@@ -130,11 +131,13 @@ extern int via_init_context(struct drm_device * dev, int context);
 extern int via_final_context(struct drm_device * dev, int context);
 
 extern int via_do_cleanup_map(struct drm_device * dev);
-extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
+extern u32 via_get_vblank_counter(struct drm_device *dev, int crtc);
+extern int via_enable_vblank(struct drm_device *dev, int crtc);
+extern void via_disable_vblank(struct drm_device *dev, int crtc);
 
 extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
 extern void via_driver_irq_preinstall(struct drm_device * dev);
-extern void via_driver_irq_postinstall(struct drm_device * dev);
+extern int via_driver_irq_postinstall(struct drm_device * dev);
 extern void via_driver_irq_uninstall(struct drm_device * dev);
 
 extern int via_dma_cleanup(struct drm_device * dev);
index c6bb978a110673821a3aa6db6e3cefd32bcc20ce..f1ab6fc7c07e8a32227ae7516bc65add4c61d030 100644 (file)
@@ -92,8 +92,17 @@ static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
 static unsigned time_diff(struct timeval *now, struct timeval *then)
 {
        return (now->tv_usec >= then->tv_usec) ?
-           now->tv_usec - then->tv_usec :
-           1000000 - (then->tv_usec - now->tv_usec);
+               now->tv_usec - then->tv_usec :
+               1000000 - (then->tv_usec - now->tv_usec);
+}
+
+u32 via_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+       if (crtc != 0)
+               return 0;
+
+       return atomic_read(&dev_priv->vbl_received);
 }
 
 irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
@@ -108,8 +117,8 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
 
        status = VIA_READ(VIA_REG_INTERRUPT);
        if (status & VIA_IRQ_VBLANK_PENDING) {
-               atomic_inc(&dev->vbl_received);
-               if (!(atomic_read(&dev->vbl_received) & 0x0F)) {
+               atomic_inc(&dev_priv->vbl_received);
+               if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) {
                        do_gettimeofday(&cur_vblank);
                        if (dev_priv->last_vblank_valid) {
                                dev_priv->usec_per_vblank =
@@ -119,12 +128,11 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
                        dev_priv->last_vblank = cur_vblank;
                        dev_priv->last_vblank_valid = 1;
                }
-               if (!(atomic_read(&dev->vbl_received) & 0xFF)) {
+               if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) {
                        DRM_DEBUG("US per vblank is: %u\n",
                                  dev_priv->usec_per_vblank);
                }
-               DRM_WAKEUP(&dev->vbl_queue);
-               drm_vbl_send_signals(dev);
+               drm_handle_vblank(dev, 0);
                handled = 1;
        }
 
@@ -163,31 +171,34 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
        }
 }
 
-int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+int via_enable_vblank(struct drm_device *dev, int crtc)
 {
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       unsigned int cur_vblank;
-       int ret = 0;
+       drm_via_private_t *dev_priv = dev->dev_private;
+       u32 status;
 
-       DRM_DEBUG("\n");
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
+       if (crtc != 0) {
+               DRM_ERROR("%s:  bad crtc %d\n", __FUNCTION__, crtc);
                return -EINVAL;
        }
 
-       viadrv_acknowledge_irqs(dev_priv);
+       status = VIA_READ(VIA_REG_INTERRUPT);
+       VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE);
 
-       /* Assume that the user has missed the current sequence number
-        * by about a day rather than she wants to wait for years
-        * using vertical blanks...
-        */
+       VIA_WRITE8(0x83d4, 0x11);
+       VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
 
-       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(&dev->vbl_received)) -
-                     *sequence) <= (1 << 23)));
+       return 0;
+}
 
-       *sequence = cur_vblank;
-       return ret;
+void via_disable_vblank(struct drm_device *dev, int crtc)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+
+       VIA_WRITE8(0x83d4, 0x11);
+       VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
+
+       if (crtc != 0)
+               DRM_ERROR("%s:  bad crtc %d\n", __FUNCTION__, crtc);
 }
 
 static int
@@ -292,23 +303,25 @@ void via_driver_irq_preinstall(struct drm_device * dev)
        }
 }
 
-void via_driver_irq_postinstall(struct drm_device * dev)
+int via_driver_irq_postinstall(struct drm_device * dev)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
        u32 status;
 
-       DRM_DEBUG("\n");
-       if (dev_priv) {
-               status = VIA_READ(VIA_REG_INTERRUPT);
-               VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
-                         | dev_priv->irq_enable_mask);
+       DRM_DEBUG("via_driver_irq_postinstall\n");
+       if (!dev_priv)
+               return -EINVAL;
 
-               /* Some magic, oh for some data sheets ! */
+       drm_vblank_init(dev, 1);
+       status = VIA_READ(VIA_REG_INTERRUPT);
+       VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
+                 | dev_priv->irq_enable_mask);
 
-               VIA_WRITE8(0x83d4, 0x11);
-               VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
+       /* Some magic, oh for some data sheets ! */
+       VIA_WRITE8(0x83d4, 0x11);
+       VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
 
-       }
+       return 0;
 }
 
 void via_driver_irq_uninstall(struct drm_device * dev)
index 9769bf8279a6adff8d39a13fd31611bce42f0a49..60b934adea65139c5c802b995e6be28950cc6e2e 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/input.h>
 #include <linux/reboot.h>
 #include <linux/notifier.h>
+#include <linux/jiffies.h>
 
 extern void ctrl_alt_del(void);
 
@@ -928,7 +929,8 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
        if (up_flag) {
                if (brl_timeout) {
                        if (!committing ||
-                           jiffies - releasestart > (brl_timeout * HZ) / 1000) {
+                           time_after(jiffies,
+                                      releasestart + msecs_to_jiffies(brl_timeout))) {
                                committing = pressed;
                                releasestart = jiffies;
                        }
@@ -1238,6 +1240,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
        }
 
        param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
+       param.ledstate = kbd->ledflagstate;
        key_map = key_maps[shift_final];
 
        if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYCODE, &param) == NOTIFY_STOP || !key_map) {
@@ -1286,6 +1289,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
 
        (*k_handler[type])(vc, keysym & 0xff, !down);
 
+       param.ledstate = kbd->ledflagstate;
        atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, &param);
 
        if (type != KT_SLOCK)
index 20070b7c573d0087416213cec1fd16bf6ba825d7..e83623ead4414efaf02a8d7e124f5719b18479c4 100644 (file)
  */
 static inline int uncached_access(struct file *file, unsigned long addr)
 {
-#if defined(__i386__) && !defined(__arch_um__)
-       /*
-        * On the PPro and successors, the MTRRs are used to set
-        * memory types for physical addresses outside main memory,
-        * so blindly setting PCD or PWT on those pages is wrong.
-        * For Pentiums and earlier, the surround logic should disable
-        * caching for the high addresses through the KEN pin, but
-        * we maintain the tradition of paranoia in this code.
-        */
-       if (file->f_flags & O_SYNC)
-               return 1;
-       return !( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ||
-                 test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ||
-                 test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
-                 test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) )
-         && addr >= __pa(high_memory);
-#elif defined(__x86_64__) && !defined(__arch_um__)
-       /* 
-        * This is broken because it can generate memory type aliases,
-        * which can cause cache corruptions
-        * But it is only available for root and we have to be bug-to-bug
-        * compatible with i386.
-        */
-       if (file->f_flags & O_SYNC)
-               return 1;
-       /* same behaviour as i386. PAT always set to cached and MTRRs control the
-          caching behaviour. 
-          Hopefully a full PAT implementation will fix that soon. */      
-       return 0;
-#elif defined(CONFIG_IA64)
+#if defined(CONFIG_IA64)
        /*
         * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases.
         */
@@ -108,6 +79,36 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
 }
 #endif
 
+#ifdef CONFIG_NONPROMISC_DEVMEM
+static inline int range_is_allowed(unsigned long pfn, unsigned long size)
+{
+       u64 from = ((u64)pfn) << PAGE_SHIFT;
+       u64 to = from + size;
+       u64 cursor = from;
+
+       while (cursor < to) {
+               if (!devmem_is_allowed(pfn)) {
+                       printk(KERN_INFO
+               "Program %s tried to access /dev/mem between %Lx->%Lx.\n",
+                               current->comm, from, to);
+                       return 0;
+               }
+               cursor += PAGE_SIZE;
+               pfn++;
+       }
+       return 1;
+}
+#else
+static inline int range_is_allowed(unsigned long pfn, unsigned long size)
+{
+       return 1;
+}
+#endif
+
+void __attribute__((weak)) unxlate_dev_mem_ptr(unsigned long phys, void *addr)
+{
+}
+
 /*
  * This funcion reads the *physical* memory. The f_pos points directly to the 
  * memory location. 
@@ -150,15 +151,25 @@ static ssize_t read_mem(struct file * file, char __user * buf,
 
                sz = min_t(unsigned long, sz, count);
 
+               if (!range_is_allowed(p >> PAGE_SHIFT, count))
+                       return -EPERM;
+
                /*
                 * On ia64 if a page has been mapped somewhere as
                 * uncached, then it must also be accessed uncached
                 * by the kernel or data corruption may occur
                 */
                ptr = xlate_dev_mem_ptr(p);
+               if (!ptr)
+                       return -EFAULT;
 
-               if (copy_to_user(buf, ptr, sz))
+               if (copy_to_user(buf, ptr, sz)) {
+                       unxlate_dev_mem_ptr(p, ptr);
                        return -EFAULT;
+               }
+
+               unxlate_dev_mem_ptr(p, ptr);
+
                buf += sz;
                p += sz;
                count -= sz;
@@ -207,20 +218,32 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
 
                sz = min_t(unsigned long, sz, count);
 
+               if (!range_is_allowed(p >> PAGE_SHIFT, sz))
+                       return -EPERM;
+
                /*
                 * On ia64 if a page has been mapped somewhere as
                 * uncached, then it must also be accessed uncached
                 * by the kernel or data corruption may occur
                 */
                ptr = xlate_dev_mem_ptr(p);
+               if (!ptr) {
+                       if (written)
+                               break;
+                       return -EFAULT;
+               }
 
                copied = copy_from_user(ptr, buf, sz);
                if (copied) {
                        written += sz - copied;
+                       unxlate_dev_mem_ptr(p, ptr);
                        if (written)
                                break;
                        return -EFAULT;
                }
+
+               unxlate_dev_mem_ptr(p, ptr);
+
                buf += sz;
                p += sz;
                count -= sz;
@@ -231,6 +254,12 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
        return written;
 }
 
+int __attribute__((weak)) phys_mem_access_prot_allowed(struct file *file,
+       unsigned long pfn, unsigned long size, pgprot_t *vma_prot)
+{
+       return 1;
+}
+
 #ifndef __HAVE_PHYS_MEM_ACCESS_PROT
 static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
                                     unsigned long size, pgprot_t vma_prot)
@@ -271,6 +300,35 @@ static inline int private_mapping_ok(struct vm_area_struct *vma)
 }
 #endif
 
+void __attribute__((weak))
+map_devmem(unsigned long pfn, unsigned long len, pgprot_t prot)
+{
+       /* nothing. architectures can override. */
+}
+
+void __attribute__((weak))
+unmap_devmem(unsigned long pfn, unsigned long len, pgprot_t prot)
+{
+       /* nothing. architectures can override. */
+}
+
+static void mmap_mem_open(struct vm_area_struct *vma)
+{
+       map_devmem(vma->vm_pgoff,  vma->vm_end - vma->vm_start,
+                       vma->vm_page_prot);
+}
+
+static void mmap_mem_close(struct vm_area_struct *vma)
+{
+       unmap_devmem(vma->vm_pgoff,  vma->vm_end - vma->vm_start,
+                       vma->vm_page_prot);
+}
+
+static struct vm_operations_struct mmap_mem_ops = {
+       .open  = mmap_mem_open,
+       .close = mmap_mem_close
+};
+
 static int mmap_mem(struct file * file, struct vm_area_struct * vma)
 {
        size_t size = vma->vm_end - vma->vm_start;
@@ -281,17 +339,28 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
        if (!private_mapping_ok(vma))
                return -ENOSYS;
 
+       if (!range_is_allowed(vma->vm_pgoff, size))
+               return -EPERM;
+
+       if (!phys_mem_access_prot_allowed(file, vma->vm_pgoff, size,
+                                               &vma->vm_page_prot))
+               return -EINVAL;
+
        vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
                                                 size,
                                                 vma->vm_page_prot);
 
+       vma->vm_ops = &mmap_mem_ops;
+
        /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
        if (remap_pfn_range(vma,
                            vma->vm_start,
                            vma->vm_pgoff,
                            size,
-                           vma->vm_page_prot))
+                           vma->vm_page_prot)) {
+               unmap_devmem(vma->vm_pgoff, size, vma->vm_page_prot);
                return -EAGAIN;
+       }
        return 0;
 }
 
index 016f90567a5200eb27c7a3baf095972f68529cbb..dfe6907ae15be44641591f4c28fea94d1a4e66f6 100644 (file)
@@ -803,7 +803,7 @@ static int __devexit hwicap_of_remove(struct of_device *op)
 }
 
 /* Match table for of_platform binding */
-static const struct of_device_id __devinit hwicap_of_match[] = {
+static const struct of_device_id __devinitconst hwicap_of_match[] = {
        { .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config},
        { .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config},
        {},
index 28ddc3fdd3d1ffc717bd8735b813fc55a4c64a55..d3f8d9194f3026879319354a5254ae6a80bcf3c9 100644 (file)
 #define USB_VENDOR_ID_YEALINK          0x6993
 #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K      0xb001
 
+#define USB_VENDOR_ID_KYE              0x0458
+#define USB_DEVICE_ID_KYE_GPEN_560     0x5003
+
 /*
  * Alphabetically sorted blacklist by quirk type.
  */
@@ -698,6 +701,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_63, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_64, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560, HID_QUIRK_IGNORE },
 
        { 0, 0 }
 };
index 87532034d10571818f50d03ff891a6f68b11f17c..3f9e10001e19179706f219a9603f27261c80eb99 100644 (file)
@@ -1031,7 +1031,7 @@ comment "Other IDE chipsets support"
 comment "Note: most of these also require special kernel boot parameters"
 
 config BLK_DEV_4DRIVES
-       bool "Generic 4 drives/port support"
+       tristate "Generic 4 drives/port support"
        help
          Certain older chipsets, including the Tekram 690CD, use a single set
          of I/O ports at 0x1f0 to control up to four drives, instead of the
index ec46c44b061cfaa27342ce31e03ef7a2b9c2f9e4..713cef20622e986b3ff0e183861c9c0a8154c697 100644 (file)
@@ -21,6 +21,8 @@
 #include <asm/arch/bast-map.h>
 #include <asm/arch/bast-irq.h>
 
+#define DRV_NAME "bast-ide"
+
 static int __init bastide_register(unsigned int base, unsigned int aux, int irq)
 {
        ide_hwif_t *hwif;
@@ -33,27 +35,23 @@ static int __init bastide_register(unsigned int base, unsigned int aux, int irq)
        base += BAST_IDE_CS;
        aux  += BAST_IDE_CS;
 
-       for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-               hw.io_ports[i] = (unsigned long)base;
+       for (i = 0; i <= 7; i++) {
+               hw.io_ports_array[i] = (unsigned long)base;
                base += 0x20;
        }
 
-       hw.io_ports[IDE_CONTROL_OFFSET] = aux + (6 * 0x20);
+       hw.io_ports.ctl_addr = aux + (6 * 0x20);
        hw.irq = irq;
 
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif == NULL)
                goto out;
 
        i = hwif->index;
 
-       if (hwif->present)
-               ide_unregister(i);
-       else
-               ide_init_port_data(hwif, i);
-
+       ide_init_port_data(hwif, i);
        ide_init_port_hw(hwif, &hw);
-       hwif->quirkproc = NULL;
+       hwif->port_ops = NULL;
 
        idx[0] = i;
 
@@ -64,6 +62,8 @@ out:
 
 static int __init bastide_init(void)
 {
+       unsigned long base = BAST_VA_IDEPRI + BAST_IDE_CS;
+
        /* we can treat the VR1000 and the BAST the same */
 
        if (!(machine_is_bast() || machine_is_vr1000()))
@@ -71,6 +71,11 @@ static int __init bastide_init(void)
 
        printk("BAST: IDE driver, (c) 2003-2004 Simtec Electronics\n");
 
+       if (!request_mem_region(base, 0x400000, DRV_NAME)) {
+               printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
+               return -EBUSY;
+       }
+
        bastide_register(BAST_VA_IDEPRI, BAST_VA_IDEPRIAUX, IRQ_IDE0);
        bastide_register(BAST_VA_IDESEC, BAST_VA_IDESECAUX, IRQ_IDE1);
 
index e816b0ffcfe647a1899161225708014271316517..124445c20921a5fe043803c34e80957f5e9ca26d 100644 (file)
@@ -191,6 +191,10 @@ static void icside_maskproc(ide_drive_t *drive, int mask)
        local_irq_restore(flags);
 }
 
+static const struct ide_port_ops icside_v6_no_dma_port_ops = {
+       .maskproc               = icside_maskproc,
+};
+
 #ifdef CONFIG_BLK_DEV_IDEDMA_ICS
 /*
  * SG-DMA support.
@@ -266,6 +270,11 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
                ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
 }
 
+static const struct ide_port_ops icside_v6_port_ops = {
+       .set_dma_mode           = icside_set_dma_mode,
+       .maskproc               = icside_maskproc,
+};
+
 static void icside_dma_host_set(ide_drive_t *drive, int on)
 {
 }
@@ -375,32 +384,40 @@ static void icside_dma_lost_irq(ide_drive_t *drive)
        printk(KERN_ERR "%s: IRQ lost\n", drive->name);
 }
 
-static void icside_dma_init(ide_hwif_t *hwif)
+static int icside_dma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
 {
        hwif->dmatable_cpu      = NULL;
        hwif->dmatable_dma      = 0;
-       hwif->set_dma_mode      = icside_set_dma_mode;
-
-       hwif->dma_host_set      = icside_dma_host_set;
-       hwif->dma_setup         = icside_dma_setup;
-       hwif->dma_exec_cmd      = icside_dma_exec_cmd;
-       hwif->dma_start         = icside_dma_start;
-       hwif->ide_dma_end       = icside_dma_end;
-       hwif->ide_dma_test_irq  = icside_dma_test_irq;
-       hwif->dma_timeout       = icside_dma_timeout;
-       hwif->dma_lost_irq      = icside_dma_lost_irq;
+
+       return 0;
 }
+
+static const struct ide_dma_ops icside_v6_dma_ops = {
+       .dma_host_set           = icside_dma_host_set,
+       .dma_setup              = icside_dma_setup,
+       .dma_exec_cmd           = icside_dma_exec_cmd,
+       .dma_start              = icside_dma_start,
+       .dma_end                = icside_dma_end,
+       .dma_test_irq           = icside_dma_test_irq,
+       .dma_timeout            = icside_dma_timeout,
+       .dma_lost_irq           = icside_dma_lost_irq,
+};
 #else
-#define icside_dma_init(hwif)  (0)
+#define icside_v6_dma_ops NULL
 #endif
 
+static int icside_dma_off_init(ide_hwif_t *hwif, const struct ide_port_info *d)
+{
+       return -EOPNOTSUPP;
+}
+
 static ide_hwif_t *
 icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *ec)
 {
        unsigned long port = (unsigned long)base + info->dataoffset;
        ide_hwif_t *hwif;
 
-       hwif = ide_find_port(port);
+       hwif = ide_find_port();
        if (hwif) {
                int i;
 
@@ -408,15 +425,14 @@ icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *e
                 * Ensure we're using MMIO
                 */
                default_hwif_mmiops(hwif);
-               hwif->mmio = 1;
 
-               for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-                       hwif->io_ports[i] = port;
+               for (i = 0; i <= 7; i++) {
+                       hwif->io_ports_array[i] = port;
                        port += 1 << info->stepping;
                }
-               hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)base + info->ctrloffset;
+               hwif->io_ports.ctl_addr =
+                       (unsigned long)base + info->ctrloffset;
                hwif->irq     = ec->irq;
-               hwif->noprobe = 0;
                hwif->chipset = ide_acorn;
                hwif->gendev.parent = &ec->dev;
                hwif->dev = &ec->dev;
@@ -462,9 +478,10 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
 }
 
 static const struct ide_port_info icside_v6_port_info __initdata = {
-       .host_flags             = IDE_HFLAG_SERIALIZE |
-                                 IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
-                                 IDE_HFLAG_NO_AUTOTUNE,
+       .init_dma               = icside_dma_off_init,
+       .port_ops               = &icside_v6_no_dma_port_ops,
+       .dma_ops                = &icside_v6_dma_ops,
+       .host_flags             = IDE_HFLAG_SERIALIZE,
        .mwdma_mask             = ATA_MWDMA2,
        .swdma_mask             = ATA_SWDMA2,
 };
@@ -526,21 +543,19 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
        state->hwif[0]    = hwif;
        state->hwif[1]    = mate;
 
-       hwif->maskproc    = icside_maskproc;
        hwif->hwif_data   = state;
        hwif->config_data = (unsigned long)ioc_base;
        hwif->select_data = sel;
 
-       mate->maskproc    = icside_maskproc;
        mate->hwif_data   = state;
        mate->config_data = (unsigned long)ioc_base;
        mate->select_data = sel | 1;
 
        if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) {
-               icside_dma_init(hwif);
-               icside_dma_init(mate);
-       } else
-               d.mwdma_mask = d.swdma_mask = 0;
+               d.init_dma = icside_dma_init;
+               d.port_ops = &icside_v6_port_ops;
+               d.dma_ops = NULL;
+       }
 
        idx[0] = hwif->index;
        idx[1] = mate->index;
index be9ff7334c529b81cff974961d3bf4c40357e8c6..4263ffd4ab20ba10839466132442fac0a1eb3ad9 100644 (file)
@@ -14,6 +14,8 @@
 #include <asm/mach-types.h>
 #include <asm/irq.h>
 
+#define DRV_NAME "ide_arm"
+
 #ifdef CONFIG_ARCH_CLPS7500
 # include <asm/arch/hardware.h>
 #
@@ -28,13 +30,27 @@ static int __init ide_arm_init(void)
 {
        ide_hwif_t *hwif;
        hw_regs_t hw;
+       unsigned long base = IDE_ARM_IO, ctl = IDE_ARM_IO + 0x206;
        u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
 
+       if (!request_region(base, 8, DRV_NAME)) {
+               printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
+                               DRV_NAME, base, base + 7);
+               return -EBUSY;
+       }
+
+       if (!request_region(ctl, 1, DRV_NAME)) {
+               printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
+                               DRV_NAME, ctl);
+               release_region(base, 8);
+               return -EBUSY;
+       }
+
        memset(&hw, 0, sizeof(hw));
-       ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206);
+       ide_std_init_ports(&hw, base, ctl);
        hw.irq = IDE_ARM_IRQ;
 
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif) {
                ide_init_port_hw(hwif, &hw);
                idx[0] = hwif->index;
index 474162cdf66599ab8b581e37def8f89a0668ff40..aaf32541622d8a08ac0a5551209c6c26922c5e3d 100644 (file)
@@ -96,11 +96,11 @@ static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
        u16 val16;
 
        /* DMA Data Setup */
-       t0 = (palm_bk3710_udmatimings[mode].cycletime + ide_palm_clk - 1)
-                       / ide_palm_clk - 1;
-       tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1;
-       trp = (palm_bk3710_udmatimings[mode].rptime + ide_palm_clk - 1)
-                       / ide_palm_clk - 1;
+       t0 = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].cycletime,
+                         ide_palm_clk) - 1;
+       tenv = DIV_ROUND_UP(20, ide_palm_clk) - 1;
+       trp = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].rptime,
+                          ide_palm_clk) - 1;
 
        /* udmatim Register */
        val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
@@ -141,8 +141,8 @@ static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev,
        cycletime = max_t(int, t->cycle, min_cycle);
 
        /* DMA Data Setup */
-       t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
-       td = (t->active + ide_palm_clk - 1) / ide_palm_clk;
+       t0 = DIV_ROUND_UP(cycletime, ide_palm_clk);
+       td = DIV_ROUND_UP(t->active, ide_palm_clk);
        tkw = t0 - td - 1;
        td -= 1;
 
@@ -168,9 +168,9 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
        struct ide_timing *t;
 
        /* PIO Data Setup */
-       t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
-       t2 = (ide_timing_find_mode(XFER_PIO_0 + mode)->active +
-             ide_palm_clk - 1) / ide_palm_clk;
+       t0 = DIV_ROUND_UP(cycletime, ide_palm_clk);
+       t2 = DIV_ROUND_UP(ide_timing_find_mode(XFER_PIO_0 + mode)->active,
+                         ide_palm_clk);
 
        t2i = t0 - t2 - 1;
        t2 -= 1;
@@ -192,8 +192,8 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
 
        /* TASKFILE Setup */
        t = ide_timing_find_mode(XFER_PIO_0 + mode);
-       t0 = (t->cyc8b + ide_palm_clk - 1) / ide_palm_clk;
-       t2 = (t->act8b + ide_palm_clk - 1) / ide_palm_clk;
+       t0 = DIV_ROUND_UP(t->cyc8b, ide_palm_clk);
+       t2 = DIV_ROUND_UP(t->act8b, ide_palm_clk);
 
        t2i = t0 - t2 - 1;
        t2 -= 1;
@@ -317,17 +317,31 @@ static u8 __devinit palm_bk3710_cable_detect(ide_hwif_t *hwif)
        return ATA_CBL_PATA80;
 }
 
-static void __devinit palm_bk3710_init_hwif(ide_hwif_t *hwif)
+static int __devinit palm_bk3710_init_dma(ide_hwif_t *hwif,
+                                         const struct ide_port_info *d)
 {
-       hwif->set_pio_mode = palm_bk3710_set_pio_mode;
-       hwif->set_dma_mode = palm_bk3710_set_dma_mode;
+       unsigned long base =
+               hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET;
 
-       hwif->cable_detect = palm_bk3710_cable_detect;
+       printk(KERN_INFO "    %s: MMIO-DMA\n", hwif->name);
+
+       if (ide_allocate_dma_engine(hwif))
+               return -1;
+
+       ide_setup_dma(hwif, base);
+
+       return 0;
 }
 
+static const struct ide_port_ops palm_bk3710_ports_ops = {
+       .set_pio_mode           = palm_bk3710_set_pio_mode,
+       .set_dma_mode           = palm_bk3710_set_dma_mode,
+       .cable_detect           = palm_bk3710_cable_detect,
+};
+
 static const struct ide_port_info __devinitdata palm_bk3710_port_info = {
-       .init_hwif              = palm_bk3710_init_hwif,
-       .host_flags             = IDE_HFLAG_NO_DMA, /* hack (no PCI) */
+       .init_dma               = palm_bk3710_init_dma,
+       .port_ops               = &palm_bk3710_ports_ops,
        .pio_mask               = ATA_PIO4,
        .udma_mask              = ATA_UDMA4,    /* (input clk 99MHz) */
        .mwdma_mask             = ATA_MWDMA2,
@@ -372,30 +386,24 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev)
 
        pribase = mem->start + IDE_PALM_ATA_PRI_REG_OFFSET;
        for (i = 0; i < IDE_NR_PORTS - 2; i++)
-               hw.io_ports[i] = pribase + i;
-       hw.io_ports[IDE_CONTROL_OFFSET] = mem->start +
+               hw.io_ports_array[i] = pribase + i;
+       hw.io_ports.ctl_addr = mem->start +
                        IDE_PALM_ATA_PRI_CTL_OFFSET;
        hw.irq = irq->start;
        hw.chipset = ide_palm3710;
 
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif == NULL)
                goto out;
 
        i = hwif->index;
 
-       if (hwif->present)
-               ide_unregister(i);
-       else
-               ide_init_port_data(hwif, i);
-
+       ide_init_port_data(hwif, i);
        ide_init_port_hw(hwif, &hw);
 
        hwif->mmio = 1;
        default_hwif_mmiops(hwif);
 
-       ide_setup_dma(hwif, mem->start);
-
        idx[0] = i;
 
        ide_device_add(idx, &palm_bk3710_port_info);
@@ -409,9 +417,13 @@ out:
        return -ENODEV;
 }
 
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:palm_bk3710");
+
 static struct platform_driver platform_bk_driver = {
        .driver = {
                .name = "palm_bk3710",
+               .owner = THIS_MODULE,
        },
        .probe = palm_bk3710_probe,
        .remove = NULL,
index b30adcf321c3dcfdcafe27c79678c0845e9f5cf8..babc1a5e128d6fadc623294942efe621e08522a1 100644 (file)
@@ -17,11 +17,11 @@ static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base,
        unsigned long port = (unsigned long)base;
        int i;
 
-       for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-               hw->io_ports[i] = port;
+       for (i = 0; i <= 7; i++) {
+               hw->io_ports_array[i] = port;
                port += sz;
        }
-       hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
+       hw->io_ports.ctl_addr = (unsigned long)ctrl;
        hw->irq = irq;
 }
 
@@ -44,7 +44,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
                goto release;
        }
 
-       hwif = ide_find_port((unsigned long)base);
+       hwif = ide_find_port();
        if (hwif) {
                memset(&hw, 0, sizeof(hw));
                rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq);
@@ -53,7 +53,6 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
 
                ide_init_port_hw(hwif, &hw);
 
-               hwif->mmio = 1;
                default_hwif_mmiops(hwif);
 
                idx[0] = hwif->index;
@@ -76,7 +75,7 @@ static void __devexit rapide_remove(struct expansion_card *ec)
 
        ecard_set_drvdata(ec, NULL);
 
-       ide_unregister(hwif->index);
+       ide_unregister(hwif);
 
        ecard_release_resources(ec);
 }
index 31266d278095e025ca905b5b7b8a22f85f6f6ffc..9df26855bc055aeac78b55f015d10d85a8ca1a04 100644 (file)
@@ -88,8 +88,8 @@ enum /* Transfer types */
 int
 cris_ide_ack_intr(ide_hwif_t* hwif)
 {
-       reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2,
-                                int, hwif->io_ports[0]);
+       reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, int,
+                                              hwif->io_ports.data_addr);
        REG_WR_INT(ata, regi_ata, rw_ack_intr, 1 << ctrl2.sel);
        return 1;
 }
@@ -231,7 +231,7 @@ cris_ide_start_dma(ide_drive_t *drive, cris_dma_descr_type *d, int dir,int type,
        ide_hwif_t *hwif = drive->hwif;
 
        reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, int,
-                                              hwif->io_ports[IDE_DATA_OFFSET]);
+                                              hwif->io_ports.data_addr);
        reg_ata_rw_trf_cnt trf_cnt = {0};
 
        mycontext.saved_data = (dma_descr_data*)virt_to_phys(d);
@@ -271,7 +271,7 @@ static int cris_dma_test_irq(ide_drive_t *drive)
        int intr = REG_RD_INT(ata, regi_ata, r_intr);
 
        reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, int,
-                                              hwif->io_ports[IDE_DATA_OFFSET]);
+                                              hwif->io_ports.data_addr);
 
        return intr & (1 << ctrl2.sel) ? 1 : 0;
 }
@@ -531,7 +531,7 @@ static void cris_ide_start_dma(ide_drive_t *drive, cris_dma_descr_type *d, int d
        *R_ATA_CTRL_DATA =
                cmd |
                IO_FIELD(R_ATA_CTRL_DATA, data,
-                        drive->hwif->io_ports[IDE_DATA_OFFSET]) |
+                        drive->hwif->io_ports.data_addr) |
                IO_STATE(R_ATA_CTRL_DATA, src_dst,  dma)  |
                IO_STATE(R_ATA_CTRL_DATA, multi,    on)   |
                IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
@@ -550,7 +550,7 @@ static int cris_dma_test_irq(ide_drive_t *drive)
 {
        int intr = *R_IRQ_MASK0_RD;
        int bus = IO_EXTRACT(R_ATA_CTRL_DATA, sel,
-                            drive->hwif->io_ports[IDE_DATA_OFFSET]);
+                            drive->hwif->io_ports.data_addr);
 
        return intr & (1 << (bus + IO_BITNR(R_IRQ_MASK0_RD, ata_irq0))) ? 1 : 0;
 }
@@ -644,7 +644,7 @@ cris_ide_inw(unsigned long reg) {
                 * call will also timeout on busy, but as long as the
                 * write is still performed, everything will be fine.
                 */
-               if (cris_ide_get_reg(reg) == IDE_STATUS_OFFSET)
+               if (cris_ide_get_reg(reg) == 7)
                        return BUSY_STAT;
                else
                        /* For other rare cases we assume 0 is good enough.  */
@@ -673,11 +673,6 @@ cris_ide_inb(unsigned long reg)
        return (unsigned char)cris_ide_inw(reg);
 }
 
-static int cris_dma_end (ide_drive_t *drive);
-static int cris_dma_setup (ide_drive_t *drive);
-static void cris_dma_exec_cmd (ide_drive_t *drive, u8 command);
-static int cris_dma_test_irq(ide_drive_t *drive);
-static void cris_dma_start(ide_drive_t *drive);
 static void cris_ide_input_data (ide_drive_t *drive, void *, unsigned int);
 static void cris_ide_output_data (ide_drive_t *drive, void *, unsigned int);
 static void cris_atapi_input_bytes(ide_drive_t *drive, void *, unsigned int);
@@ -770,20 +765,29 @@ static void __init cris_setup_ports(hw_regs_t *hw, unsigned long base)
        memset(hw, 0, sizeof(*hw));
 
        for (i = 0; i <= 7; i++)
-               hw->io_ports[i] = base + cris_ide_reg_addr(i, 0, 1);
+               hw->io_ports_array[i] = base + cris_ide_reg_addr(i, 0, 1);
 
        /*
         * the IDE control register is at ATA address 6,
         * with CS1 active instead of CS0
         */
-       hw->io_ports[IDE_CONTROL_OFFSET] = base + cris_ide_reg_addr(6, 1, 0);
+       hw->io_ports.ctl_addr = base + cris_ide_reg_addr(6, 1, 0);
 
        hw->irq = ide_default_irq(0);
        hw->ack_intr = cris_ide_ack_intr;
 }
 
+static const struct ide_port_ops cris_port_ops = {
+       .set_pio_mode           = cris_set_pio_mode,
+       .set_dma_mode           = cris_set_dma_mode,
+};
+
+static const struct ide_dma_ops cris_dma_ops;
+
 static const struct ide_port_info cris_port_info __initdata = {
        .chipset                = ide_etrax100,
+       .port_ops               = &cris_port_ops,
+       .dma_ops                = &cris_dma_ops,
        .host_flags             = IDE_HFLAG_NO_ATAPI_DMA |
                                  IDE_HFLAG_NO_DMA, /* no SFF-style DMA */
        .pio_mask               = ATA_PIO4,
@@ -804,24 +808,16 @@ static int __init init_e100_ide(void)
 
                cris_setup_ports(&hw, cris_ide_base_address(h));
 
-               hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+               hwif = ide_find_port();
                if (hwif == NULL)
                        continue;
                ide_init_port_data(hwif, hwif->index);
                ide_init_port_hw(hwif, &hw);
-               hwif->mmio = 1;
-               hwif->set_pio_mode = &cris_set_pio_mode;
-               hwif->set_dma_mode = &cris_set_dma_mode;
+
                hwif->ata_input_data = &cris_ide_input_data;
                hwif->ata_output_data = &cris_ide_output_data;
                hwif->atapi_input_bytes = &cris_atapi_input_bytes;
                hwif->atapi_output_bytes = &cris_atapi_output_bytes;
-               hwif->dma_host_set = &cris_dma_host_set;
-               hwif->ide_dma_end = &cris_dma_end;
-               hwif->dma_setup = &cris_dma_setup;
-               hwif->dma_exec_cmd = &cris_dma_exec_cmd;
-               hwif->ide_dma_test_irq = &cris_dma_test_irq;
-               hwif->dma_start = &cris_dma_start;
                hwif->OUTB = &cris_ide_outb;
                hwif->OUTW = &cris_ide_outw;
                hwif->OUTBSYNC = &cris_ide_outbsync;
@@ -1076,6 +1072,15 @@ static void cris_dma_start(ide_drive_t *drive)
        }
 }
 
+static const struct ide_dma_ops cris_dma_ops = {
+       .dma_host_set           = cris_dma_host_set,
+       .dma_setup              = cris_dma_setup,
+       .dma_exec_cmd           = cris_dma_exec_cmd,
+       .dma_start              = cris_dma_start,
+       .dma_end                = cris_dma_end,
+       .dma_test_irq           = cris_dma_test_irq,
+};
+
 module_init(init_e100_ide);
 
 MODULE_LICENSE("GPL");
index 4108ec4ffa7fb40da200a8da5abcd6aefc72f867..fd23f12e17aa9642e34bfa8f05efd2395487bcfa 100644 (file)
@@ -63,9 +63,9 @@ static inline void hw_setup(hw_regs_t *hw)
        int i;
 
        memset(hw, 0, sizeof(hw_regs_t));
-       for (i = 0; i <= IDE_STATUS_OFFSET; i++)
-               hw->io_ports[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i;
-       hw->io_ports[IDE_CONTROL_OFFSET] = CONFIG_H8300_IDE_ALT;
+       for (i = 0; i <= 7; i++)
+               hw->io_ports_array[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i;
+       hw->io_ports.ctl_addr = CONFIG_H8300_IDE_ALT;
        hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ;
        hw->chipset = ide_generic;
 }
@@ -74,7 +74,6 @@ static inline void hwif_setup(ide_hwif_t *hwif)
 {
        default_hwif_iops(hwif);
 
-       hwif->mmio  = 1;
        hwif->OUTW  = mm_outw;
        hwif->OUTSW = mm_outsw;
        hwif->INW   = mm_inw;
@@ -99,8 +98,7 @@ static int __init h8300_ide_init(void)
 
        hw_setup(&hw);
 
-       /* register if */
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif == NULL) {
                printk(KERN_ERR "ide-h8300: IDE I/F register failed\n");
                return -ENOENT;
index 0f6fb6b72dd91bcbb15de6f237e279df2d60c353..9d3601fa56803c01c9870f5fd0ab12b196ff5637 100644 (file)
@@ -55,14 +55,22 @@ struct ide_acpi_hwif_link {
 /* note: adds function name and KERN_DEBUG */
 #ifdef DEBUGGING
 #define DEBPRINT(fmt, args...) \
-               printk(KERN_DEBUG "%s: " fmt, __FUNCTION__, ## args)
+               printk(KERN_DEBUG "%s: " fmt, __func__, ## args)
 #else
 #define DEBPRINT(fmt, args...) do {} while (0)
 #endif /* DEBUGGING */
 
-extern int ide_noacpi;
-extern int ide_noacpitfs;
-extern int ide_noacpionboot;
+int ide_noacpi;
+module_param_named(noacpi, ide_noacpi, bool, 0);
+MODULE_PARM_DESC(noacpi, "disable IDE ACPI support");
+
+int ide_acpigtf;
+module_param_named(acpigtf, ide_acpigtf, bool, 0);
+MODULE_PARM_DESC(acpigtf, "enable IDE ACPI _GTF support");
+
+int ide_acpionboot;
+module_param_named(acpionboot, ide_acpionboot, bool, 0);
+MODULE_PARM_DESC(acpionboot, "call IDE ACPI methods on boot");
 
 static bool ide_noacpi_psx;
 static int no_acpi_psx(const struct dmi_system_id *id)
@@ -309,7 +317,7 @@ static int do_drive_get_GTF(ide_drive_t *drive,
        if (ACPI_FAILURE(status)) {
                printk(KERN_DEBUG
                       "%s: Run _GTF error: status = 0x%x\n",
-                      __FUNCTION__, status);
+                      __func__, status);
                goto out;
        }
 
@@ -335,7 +343,7 @@ static int do_drive_get_GTF(ide_drive_t *drive,
            out_obj->buffer.length % REGS_PER_GTF) {
                printk(KERN_ERR
                       "%s: unexpected GTF length (%d) or addr (0x%p)\n",
-                      __FUNCTION__, out_obj->buffer.length,
+                      __func__, out_obj->buffer.length,
                       out_obj->buffer.pointer);
                err = -ENOENT;
                kfree(output.pointer);
@@ -376,7 +384,7 @@ static int taskfile_load_raw(ide_drive_t *drive,
        memcpy(&args.tf_array[7], &gtf->tfa, 7);
        args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
 
-       if (ide_noacpitfs) {
+       if (!ide_acpigtf) {
                DEBPRINT("_GTF execution disabled\n");
                return err;
        }
@@ -384,7 +392,7 @@ static int taskfile_load_raw(ide_drive_t *drive,
        err = ide_no_data_taskfile(drive, &args);
        if (err)
                printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n",
-                      __FUNCTION__, err);
+                      __func__, err);
 
        return err;
 }
@@ -422,7 +430,7 @@ static int do_drive_set_taskfiles(ide_drive_t *drive,
 
        if (gtf_length % REGS_PER_GTF) {
                printk(KERN_ERR "%s: unexpected GTF length (%d)\n",
-                      __FUNCTION__, gtf_length);
+                      __func__, gtf_length);
                goto out;
        }
 
@@ -547,7 +555,7 @@ void ide_acpi_get_timing(ide_hwif_t *hwif)
                printk(KERN_ERR
                        "%s: unexpected _GTM length (0x%x)[should be 0x%zx] or "
                        "addr (0x%p)\n",
-                       __FUNCTION__, out_obj->buffer.length,
+                       __func__, out_obj->buffer.length,
                        sizeof(struct GTM_buffer), out_obj->buffer.pointer);
                return;
        }
@@ -721,7 +729,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
                                 drive->name, err);
        }
 
-       if (ide_noacpionboot) {
+       if (!ide_acpionboot) {
                DEBPRINT("ACPI methods disabled on boot\n");
                return;
        }
index fe5aefbf83392fae89553050dd484dcf108fd428..b34fd2bde96ffe8e743caf2fad30de0ee1fa03fc 100644 (file)
@@ -13,8 +13,8 @@
  *
  * Suggestions are welcome. Patches that work are more welcome though. ;-)
  * For those wishing to work on this driver, please be sure you download
- * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI 
- * (SFF-8020i rev 2.6) standards. These documents can be obtained by 
+ * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI
+ * (SFF-8020i rev 2.6) standards. These documents can be obtained by
  * anonymous ftp from:
  * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
  * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf
 #include <linux/mutex.h>
 #include <linux/bcd.h>
 
-#include <scsi/scsi.h> /* For SCSI -> ATAPI command conversion */
+/* For SCSI -> ATAPI command conversion */
+#include <scsi/scsi.h>
 
-#include <asm/irq.h>
-#include <asm/io.h>
+#include <linux/irq.h>
+#include <linux/io.h>
 #include <asm/byteorder.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unaligned.h>
 
 #include "ide-cd.h"
 
 static DEFINE_MUTEX(idecd_ref_mutex);
 
-#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref) 
+#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref)
 
 #define ide_cd_g(disk) \
        container_of((disk)->private_data, struct cdrom_info, driver)
@@ -77,19 +78,17 @@ static void ide_cd_put(struct cdrom_info *cd)
        mutex_unlock(&idecd_ref_mutex);
 }
 
-/****************************************************************************
+/*
  * Generic packet command support and error handling routines.
  */
 
-/* Mark that we've seen a media change, and invalidate our internal
-   buffers. */
-static void cdrom_saw_media_change (ide_drive_t *drive)
+/* Mark that we've seen a media change and invalidate our internal buffers. */
+static void cdrom_saw_media_change(ide_drive_t *drive)
 {
        struct cdrom_info *cd = drive->driver_data;
 
        cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
        cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
-       cd->nsectors_buffered = 0;
 }
 
 static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
@@ -101,44 +100,43 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
                return 0;
 
        switch (sense->sense_key) {
-               case NO_SENSE: case RECOVERED_ERROR:
-                       break;
-               case NOT_READY:
-                       /*
-                        * don't care about tray state messages for
-                        * e.g. capacity commands or in-progress or
-                        * becoming ready
-                        */
-                       if (sense->asc == 0x3a || sense->asc == 0x04)
-                               break;
-                       log = 1;
-                       break;
-               case ILLEGAL_REQUEST:
-                       /*
-                        * don't log START_STOP unit with LoEj set, since
-                        * we cannot reliably check if drive can auto-close
-                        */
-                       if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
-                               break;
-                       log = 1;
-                       break;
-               case UNIT_ATTENTION:
-                       /*
-                        * Make good and sure we've seen this potential media
-                        * change. Some drives (i.e. Creative) fail to present
-                        * the correct sense key in the error register.
-                        */
-                       cdrom_saw_media_change(drive);
+       case NO_SENSE:
+       case RECOVERED_ERROR:
+               break;
+       case NOT_READY:
+               /*
+                * don't care about tray state messages for e.g. capacity
+                * commands or in-progress or becoming ready
+                */
+               if (sense->asc == 0x3a || sense->asc == 0x04)
                        break;
-               default:
-                       log = 1;
+               log = 1;
+               break;
+       case ILLEGAL_REQUEST:
+               /*
+                * don't log START_STOP unit with LoEj set, since we cannot
+                * reliably check if drive can auto-close
+                */
+               if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
                        break;
+               log = 1;
+               break;
+       case UNIT_ATTENTION:
+               /*
+                * Make good and sure we've seen this potential media change.
+                * Some drives (i.e. Creative) fail to present the correct sense
+                * key in the error register.
+                */
+               cdrom_saw_media_change(drive);
+               break;
+       default:
+               log = 1;
+               break;
        }
        return log;
 }
 
-static
-void cdrom_analyze_sense_data(ide_drive_t *drive,
+static void cdrom_analyze_sense_data(ide_drive_t *drive,
                              struct request *failed_command,
                              struct request_sense *sense)
 {
@@ -151,16 +149,17 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
                return;
 
        /*
-        * If a read toc is executed for a CD-R or CD-RW medium where
-        * the first toc has not been recorded yet, it will fail with
-        * 05/24/00 (which is a confusing error)
+        * If a read toc is executed for a CD-R or CD-RW medium where the first
+        * toc has not been recorded yet, it will fail with 05/24/00 (which is a
+        * confusing error)
         */
        if (failed_command && failed_command->cmd[0] == GPCMD_READ_TOC_PMA_ATIP)
                if (sense->sense_key == 0x05 && sense->asc == 0x24)
                        return;
 
-       if (sense->error_code == 0x70) {        /* Current Error */
-               switch(sense->sense_key) {
+       /* current error */
+       if (sense->error_code == 0x70) {
+               switch (sense->sense_key) {
                case MEDIUM_ERROR:
                case VOLUME_OVERFLOW:
                case ILLEGAL_REQUEST:
@@ -178,25 +177,23 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
                        if (bio_sectors < 4)
                                bio_sectors = 4;
                        if (drive->queue->hardsect_size == 2048)
-                               sector <<= 2;   /* Device sector size is 2K */
-                       sector &= ~(bio_sectors -1);
+                               /* device sector size is 2K */
+                               sector <<= 2;
+                       sector &= ~(bio_sectors - 1);
                        valid = (sector - failed_command->sector) << 9;
 
                        if (valid < 0)
                                valid = 0;
                        if (sector < get_capacity(info->disk) &&
-                               drive->probed_capacity - sector < 4 * 75) {
+                           drive->probed_capacity - sector < 4 * 75)
                                set_capacity(info->disk, sector);
-                       }
-               }
-       }
+               }
+       }
 
        ide_cd_log_error(drive->name, failed_command, sense);
 }
 
-/*
- * Initialize a ide-cd packet command request
- */
+/* Initialize a ide-cd packet command request */
 void ide_cd_init_rq(ide_drive_t *drive, struct request *rq)
 {
        struct cdrom_info *cd = drive->driver_data;
@@ -220,7 +217,8 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
 
        rq->data = sense;
        rq->cmd[0] = GPCMD_REQUEST_SENSE;
-       rq->cmd[4] = rq->data_len = 18;
+       rq->cmd[4] = 18;
+       rq->data_len = 18;
 
        rq->cmd_type = REQ_TYPE_SENSE;
 
@@ -230,7 +228,7 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
        (void) ide_do_drive_cmd(drive, rq, ide_preempt);
 }
 
-static void cdrom_end_request (ide_drive_t *drive, int uptodate)
+static void cdrom_end_request(ide_drive_t *drive, int uptodate)
 {
        struct request *rq = HWGROUP(drive)->rq;
        int nsectors = rq->hard_cur_sectors;
@@ -252,7 +250,7 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
                        }
                        cdrom_analyze_sense_data(drive, failed, sense);
                        /*
-                        * now end failed request
+                        * now end the failed request
                         */
                        if (blk_fs_request(failed)) {
                                if (ide_end_dequeued_request(drive, failed, 0,
@@ -280,21 +278,24 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
        ide_end_request(drive, uptodate, nsectors);
 }
 
-static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 stat)
+static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 st)
 {
-       if (stat & 0x80)
+       if (st & 0x80)
                return;
-       ide_dump_status(drive, msg, stat);
+       ide_dump_status(drive, msg, st);
 }
 
-/* Returns 0 if the request should be continued.
-   Returns 1 if the request was ended. */
+/*
+ * Returns:
+ * 0: if the request should be continued.
+ * 1: if the request was ended.
+ */
 static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
 {
        struct request *rq = HWGROUP(drive)->rq;
        int stat, err, sense_key;
-       
-       /* Check for errors. */
+
+       /* check for errors */
        stat = ide_read_status(drive);
 
        if (stat_ret)
@@ -303,20 +304,22 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
        if (OK_STAT(stat, good_stat, BAD_R_STAT))
                return 0;
 
-       /* Get the IDE error register. */
+       /* get the IDE error register */
        err = ide_read_error(drive);
        sense_key = err >> 4;
 
        if (rq == NULL) {
-               printk("%s: missing rq in cdrom_decode_status\n", drive->name);
+               printk(KERN_ERR "%s: missing rq in %s\n",
+                               drive->name, __func__);
                return 1;
        }
 
        if (blk_sense_request(rq)) {
-               /* We got an error trying to get sense info
-                  from the drive (probably while trying
-                  to recover from a former error).  Just give up. */
-
+               /*
+                * We got an error trying to get sense info from the drive
+                * (probably while trying to recover from a former error).
+                * Just give up.
+                */
                rq->cmd_flags |= REQ_FAILED;
                cdrom_end_request(drive, 0);
                ide_error(drive, "request sense failure", stat);
@@ -332,28 +335,27 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                if (blk_pc_request(rq) && !rq->errors)
                        rq->errors = SAM_STAT_CHECK_CONDITION;
 
-               /* Check for tray open. */
+               /* check for tray open */
                if (sense_key == NOT_READY) {
-                       cdrom_saw_media_change (drive);
+                       cdrom_saw_media_change(drive);
                } else if (sense_key == UNIT_ATTENTION) {
-                       /* Check for media change. */
-                       cdrom_saw_media_change (drive);
-                       /*printk("%s: media changed\n",drive->name);*/
+                       /* check for media change */
+                       cdrom_saw_media_change(drive);
                        return 0;
-               } else if ((sense_key == ILLEGAL_REQUEST) &&
-                          (rq->cmd[0] == GPCMD_START_STOP_UNIT)) {
-                       /*
-                        * Don't print error message for this condition--
-                        * SFF8090i indicates that 5/24/00 is the correct
-                        * response to a request to close the tray if the
-                        * drive doesn't have that capability.
-                        * cdrom_log_sense() knows this!
-                        */
+               } else if (sense_key == ILLEGAL_REQUEST &&
+                          rq->cmd[0] == GPCMD_START_STOP_UNIT) {
+                       /*
+                        * Don't print error message for this condition--
+                        * SFF8090i indicates that 5/24/00 is the correct
+                        * response to a request to close the tray if the
+                        * drive doesn't have that capability.
+                        * cdrom_log_sense() knows this!
+                        */
                } else if (!(rq->cmd_flags & REQ_QUIET)) {
-                       /* Otherwise, print an error. */
+                       /* otherwise, print an error */
                        ide_dump_status(drive, "packet command error", stat);
                }
-               
+
                rq->cmd_flags |= REQ_FAILED;
 
                /*
@@ -366,27 +368,30 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
        } else if (blk_fs_request(rq)) {
                int do_end_request = 0;
 
-               /* Handle errors from READ and WRITE requests. */
+               /* handle errors from READ and WRITE requests */
 
                if (blk_noretry_request(rq))
                        do_end_request = 1;
 
                if (sense_key == NOT_READY) {
-                       /* Tray open. */
+                       /* tray open */
                        if (rq_data_dir(rq) == READ) {
-                               cdrom_saw_media_change (drive);
+                               cdrom_saw_media_change(drive);
 
-                               /* Fail the request. */
-                               printk ("%s: tray open\n", drive->name);
+                               /* fail the request */
+                               printk(KERN_ERR "%s: tray open\n", drive->name);
                                do_end_request = 1;
                        } else {
                                struct cdrom_info *info = drive->driver_data;
 
-                               /* allow the drive 5 seconds to recover, some
+                               /*
+                                * Allow the drive 5 seconds to recover, some
                                 * devices will return this error while flushing
-                                * data from cache */
+                                * data from cache.
+                                */
                                if (!rq->errors)
-                                       info->write_timeout = jiffies + ATAPI_WAIT_WRITE_BUSY;
+                                       info->write_timeout = jiffies +
+                                                       ATAPI_WAIT_WRITE_BUSY;
                                rq->errors = 1;
                                if (time_after(jiffies, info->write_timeout))
                                        do_end_request = 1;
@@ -394,59 +399,68 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                                        unsigned long flags;
 
                                        /*
-                                        * take a breather relying on the
-                                        * unplug timer to kick us again
+                                        * take a breather relying on the unplug
+                                        * timer to kick us again
                                         */
                                        spin_lock_irqsave(&ide_lock, flags);
                                        blk_plug_device(drive->queue);
-                                       spin_unlock_irqrestore(&ide_lock,flags);
+                                       spin_unlock_irqrestore(&ide_lock,
+                                                               flags);
                                        return 1;
                                }
                        }
                } else if (sense_key == UNIT_ATTENTION) {
-                       /* Media change. */
-                       cdrom_saw_media_change (drive);
+                       /* media change */
+                       cdrom_saw_media_change(drive);
 
-                       /* Arrange to retry the request.
-                          But be sure to give up if we've retried
-                          too many times. */
+                       /*
+                        * Arrange to retry the request but be sure to give up
+                        * if we've retried too many times.
+                        */
                        if (++rq->errors > ERROR_MAX)
                                do_end_request = 1;
                } else if (sense_key == ILLEGAL_REQUEST ||
                           sense_key == DATA_PROTECT) {
-                       /* No point in retrying after an illegal
-                          request or data protect error.*/
-                       ide_dump_status_no_sense (drive, "command error", stat);
+                       /*
+                        * No point in retrying after an illegal request or data
+                        * protect error.
+                        */
+                       ide_dump_status_no_sense(drive, "command error", stat);
                        do_end_request = 1;
                } else if (sense_key == MEDIUM_ERROR) {
-                       /* No point in re-trying a zillion times on a bad 
-                        * sector...  If we got here the error is not correctable */
-                       ide_dump_status_no_sense (drive, "media error (bad sector)", stat);
+                       /*
+                        * No point in re-trying a zillion times on a bad
+                        * sector. If we got here the error is not correctable.
+                        */
+                       ide_dump_status_no_sense(drive,
+                                                "media error (bad sector)",
+                                                stat);
                        do_end_request = 1;
                } else if (sense_key == BLANK_CHECK) {
-                       /* Disk appears blank ?? */
-                       ide_dump_status_no_sense (drive, "media error (blank)", stat);
+                       /* disk appears blank ?? */
+                       ide_dump_status_no_sense(drive, "media error (blank)",
+                                                stat);
                        do_end_request = 1;
                } else if ((err & ~ABRT_ERR) != 0) {
-                       /* Go to the default handler
-                          for other errors. */
+                       /* go to the default handler for other errors */
                        ide_error(drive, "cdrom_decode_status", stat);
                        return 1;
                } else if ((++rq->errors > ERROR_MAX)) {
-                       /* We've racked up too many retries.  Abort. */
+                       /* we've racked up too many retries, abort */
                        do_end_request = 1;
                }
 
-               /* End a request through request sense analysis when we have
-                  sense data. We need this in order to perform end of media
-                  processing */
-
+               /*
+                * End a request through request sense analysis when we have
+                * sense data. We need this in order to perform end of media
+                * processing.
+                */
                if (do_end_request)
                        goto end_request;
 
                /*
-                * If we got a CHECK_CONDITION status,
-                * queue a request sense command.
+                * If we got a CHECK_CONDITION status, queue
+                * a request sense command.
                 */
                if (stat & ERR_STAT)
                        cdrom_queue_request_sense(drive, NULL, NULL);
@@ -455,7 +469,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                cdrom_end_request(drive, 0);
        }
 
-       /* Retry, or handle the next request. */
+       /* retry, or handle the next request */
        return 1;
 
 end_request:
@@ -480,35 +494,37 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
        unsigned long wait = 0;
 
        /*
-        * Some commands are *slow* and normally take a long time to
-        * complete. Usually we can use the ATAPI "disconnect" to bypass
-        * this, but not all commands/drives support that. Let
-        * ide_timer_expiry keep polling us for these.
+        * Some commands are *slow* and normally take a long time to complete.
+        * Usually we can use the ATAPI "disconnect" to bypass this, but not all
+        * commands/drives support that. Let ide_timer_expiry keep polling us
+        * for these.
         */
        switch (rq->cmd[0]) {
-               case GPCMD_BLANK:
-               case GPCMD_FORMAT_UNIT:
-               case GPCMD_RESERVE_RZONE_TRACK:
-               case GPCMD_CLOSE_TRACK:
-               case GPCMD_FLUSH_CACHE:
-                       wait = ATAPI_WAIT_PC;
-                       break;
-               default:
-                       if (!(rq->cmd_flags & REQ_QUIET))
-                               printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]);
-                       wait = 0;
-                       break;
+       case GPCMD_BLANK:
+       case GPCMD_FORMAT_UNIT:
+       case GPCMD_RESERVE_RZONE_TRACK:
+       case GPCMD_CLOSE_TRACK:
+       case GPCMD_FLUSH_CACHE:
+               wait = ATAPI_WAIT_PC;
+               break;
+       default:
+               if (!(rq->cmd_flags & REQ_QUIET))
+                       printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n",
+                                        rq->cmd[0]);
+               wait = 0;
+               break;
        }
        return wait;
 }
 
-/* Set up the device registers for transferring a packet command on DEV,
-   expecting to later transfer XFERLEN bytes.  HANDLER is the routine
-   which actually transfers the command to the drive.  If this is a
-   drq_interrupt device, this routine will arrange for HANDLER to be
-   called when the interrupt from the drive arrives.  Otherwise, HANDLER
-   will be called immediately after the drive is prepared for the transfer. */
-
+/*
+ * Set up the device registers for transferring a packet command on DEV,
+ * expecting to later transfer XFERLEN bytes.  HANDLER is the routine
+ * which actually transfers the command to the drive.  If this is a
+ * drq_interrupt device, this routine will arrange for HANDLER to be
+ * called when the interrupt from the drive arrives.  Otherwise, HANDLER
+ * will be called immediately after the drive is prepared for the transfer.
+ */
 static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
                                                  int xferlen,
                                                  ide_handler_t *handler)
@@ -517,15 +533,15 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
        struct cdrom_info *info = drive->driver_data;
        ide_hwif_t *hwif = drive->hwif;
 
-       /* Wait for the controller to be idle. */
+       /* wait for the controller to be idle */
        if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY))
                return startstop;
 
        /* FIXME: for Virtual DMA we must check harder */
        if (info->dma)
-               info->dma = !hwif->dma_setup(drive);
+               info->dma = !hwif->dma_ops->dma_setup(drive);
 
-       /* Set up the controller registers. */
+       /* set up the controller registers */
        ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL |
                           IDE_TFLAG_NO_SELECT_MASK, xferlen, info->dma);
 
@@ -535,7 +551,8 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
                        drive->waiting_for_dma = 0;
 
                /* packet command */
-               ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry);
+               ide_execute_command(drive, WIN_PACKETCMD, handler,
+                                   ATAPI_WAIT_PC, cdrom_timer_expiry);
                return ide_started;
        } else {
                unsigned long flags;
@@ -543,7 +560,7 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
                /* packet command */
                spin_lock_irqsave(&ide_lock, flags);
                hwif->OUTBSYNC(drive, WIN_PACKETCMD,
-                              hwif->io_ports[IDE_COMMAND_OFFSET]);
+                              hwif->io_ports.command_addr);
                ndelay(400);
                spin_unlock_irqrestore(&ide_lock, flags);
 
@@ -551,13 +568,14 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
        }
 }
 
-/* Send a packet command to DRIVE described by CMD_BUF and CMD_LEN.
-   The device registers must have already been prepared
-   by cdrom_start_packet_command.
-   HANDLER is the interrupt handler to call when the command completes
-   or there's data ready. */
+/*
+ * Send a packet command to DRIVE described by CMD_BUF and CMD_LEN. The device
+ * registers must have already been prepared by cdrom_start_packet_command.
+ * HANDLER is the interrupt handler to call when the command completes or
+ * there's data ready.
+ */
 #define ATAPI_MIN_CDB_BYTES 12
-static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
+static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
                                          struct request *rq,
                                          ide_handler_t *handler)
 {
@@ -567,24 +585,26 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
        ide_startstop_t startstop;
 
        if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
-               /* Here we should have been called after receiving an interrupt
-                  from the device.  DRQ should how be set. */
+               /*
+                * Here we should have been called after receiving an interrupt
+                * from the device.  DRQ should how be set.
+                */
 
-               /* Check for errors. */
+               /* check for errors */
                if (cdrom_decode_status(drive, DRQ_STAT, NULL))
                        return ide_stopped;
 
-               /* Ok, next interrupt will be DMA interrupt. */
+               /* ok, next interrupt will be DMA interrupt */
                if (info->dma)
                        drive->waiting_for_dma = 1;
        } else {
-               /* Otherwise, we must wait for DRQ to get set. */
+               /* otherwise, we must wait for DRQ to get set */
                if (ide_wait_stat(&startstop, drive, DRQ_STAT,
                                BUSY_STAT, WAIT_READY))
                        return startstop;
        }
 
-       /* Arm the interrupt handler. */
+       /* arm the interrupt handler */
        ide_set_handler(drive, handler, rq->timeout, cdrom_timer_expiry);
 
        /* ATAPI commands get padded out to 12 bytes minimum */
@@ -592,20 +612,19 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
        if (cmd_len < ATAPI_MIN_CDB_BYTES)
                cmd_len = ATAPI_MIN_CDB_BYTES;
 
-       /* Send the command to the device. */
+       /* send the command to the device */
        HWIF(drive)->atapi_output_bytes(drive, rq->cmd, cmd_len);
 
-       /* Start the DMA if need be */
+       /* start the DMA if need be */
        if (info->dma)
-               hwif->dma_start(drive);
+               hwif->dma_ops->dma_start(drive);
 
        return ide_started;
 }
 
-/****************************************************************************
+/*
  * Block read functions.
  */
-
 static void ide_cd_pad_transfer(ide_drive_t *drive, xfer_func_t *xf, int len)
 {
        while (len > 0) {
@@ -625,47 +644,6 @@ static void ide_cd_drain_data(ide_drive_t *drive, int nsects)
        }
 }
 
-/*
- * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector
- * buffer.  Once the first sector is added, any subsequent sectors are
- * assumed to be continuous (until the buffer is cleared).  For the first
- * sector added, SECTOR is its sector number.  (SECTOR is then ignored until
- * the buffer is cleared.)
- */
-static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
-                                  int sectors_to_transfer)
-{
-       struct cdrom_info *info = drive->driver_data;
-
-       /* Number of sectors to read into the buffer. */
-       int sectors_to_buffer = min_t(int, sectors_to_transfer,
-                                    (SECTOR_BUFFER_SIZE >> SECTOR_BITS) -
-                                      info->nsectors_buffered);
-
-       char *dest;
-
-       /* If we couldn't get a buffer, don't try to buffer anything... */
-       if (info->buffer == NULL)
-               sectors_to_buffer = 0;
-
-       /* If this is the first sector in the buffer, remember its number. */
-       if (info->nsectors_buffered == 0)
-               info->sector_buffered = sector;
-
-       /* Read the data into the buffer. */
-       dest = info->buffer + info->nsectors_buffered * SECTOR_SIZE;
-       while (sectors_to_buffer > 0) {
-               HWIF(drive)->atapi_input_bytes(drive, dest, SECTOR_SIZE);
-               --sectors_to_buffer;
-               --sectors_to_transfer;
-               ++info->nsectors_buffered;
-               dest += SECTOR_SIZE;
-       }
-
-       /* Throw away any remaining data. */
-       ide_cd_drain_data(drive, sectors_to_transfer);
-}
-
 /*
  * Check the contents of the interrupt reason register from the cdrom
  * and attempt to recover if there are problems.  Returns  0 if everything's
@@ -684,22 +662,23 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
                ide_hwif_t *hwif = drive->hwif;
                xfer_func_t *xf;
 
-               /* Whoops... */
+               /* whoops... */
                printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
-                               drive->name, __FUNCTION__);
+                               drive->name, __func__);
 
                xf = rw ? hwif->atapi_output_bytes : hwif->atapi_input_bytes;
                ide_cd_pad_transfer(drive, xf, len);
        } else  if (rw == 0 && ireason == 1) {
-               /* Some drives (ASUS) seem to tell us that status
-                * info is available. just get it and ignore.
+               /*
+                * Some drives (ASUS) seem to tell us that status info is
+                * available.  Just get it and ignore.
                 */
                (void)ide_read_status(drive);
                return 0;
        } else {
-               /* Drive wants a command packet, or invalid ireason... */
+               /* drive wants a command packet, or invalid ireason... */
                printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n",
-                               drive->name, __FUNCTION__, ireason);
+                               drive->name, __func__, ireason);
        }
 
        if (rq->cmd_type == REQ_TYPE_ATA_PC)
@@ -721,7 +700,7 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
                return 0;
 
        printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
-                       drive->name, __FUNCTION__, len);
+                       drive->name, __func__, len);
 
        if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES)
                printk(KERN_ERR "  This drive is not supported by "
@@ -734,72 +713,13 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
        return 1;
 }
 
-/*
- * Try to satisfy some of the current read request from our cached data.
- * Returns nonzero if the request has been completed, zero otherwise.
- */
-static int cdrom_read_from_buffer (ide_drive_t *drive)
-{
-       struct cdrom_info *info = drive->driver_data;
-       struct request *rq = HWGROUP(drive)->rq;
-       unsigned short sectors_per_frame;
-
-       sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
-
-       /* Can't do anything if there's no buffer. */
-       if (info->buffer == NULL) return 0;
-
-       /* Loop while this request needs data and the next block is present
-          in our cache. */
-       while (rq->nr_sectors > 0 &&
-              rq->sector >= info->sector_buffered &&
-              rq->sector < info->sector_buffered + info->nsectors_buffered) {
-               if (rq->current_nr_sectors == 0)
-                       cdrom_end_request(drive, 1);
-
-               memcpy (rq->buffer,
-                       info->buffer +
-                       (rq->sector - info->sector_buffered) * SECTOR_SIZE,
-                       SECTOR_SIZE);
-               rq->buffer += SECTOR_SIZE;
-               --rq->current_nr_sectors;
-               --rq->nr_sectors;
-               ++rq->sector;
-       }
-
-       /* If we've satisfied the current request,
-          terminate it successfully. */
-       if (rq->nr_sectors == 0) {
-               cdrom_end_request(drive, 1);
-               return -1;
-       }
-
-       /* Move on to the next buffer if needed. */
-       if (rq->current_nr_sectors == 0)
-               cdrom_end_request(drive, 1);
-
-       /* If this condition does not hold, then the kluge i use to
-          represent the number of sectors to skip at the start of a transfer
-          will fail.  I think that this will never happen, but let's be
-          paranoid and check. */
-       if (rq->current_nr_sectors < bio_cur_sectors(rq->bio) &&
-           (rq->sector & (sectors_per_frame - 1))) {
-               printk(KERN_ERR "%s: cdrom_read_from_buffer: buffer botch (%ld)\n",
-                       drive->name, (long)rq->sector);
-               cdrom_end_request(drive, 0);
-               return -1;
-       }
-
-       return 0;
-}
-
 static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
 
 /*
- * Routine to send a read/write packet command to the drive.
- * This is usually called directly from cdrom_start_{read,write}().
- * However, for drq_interrupt devices, it is called from an interrupt
- * when the drive is ready to accept the command.
+ * Routine to send a read/write packet command to the drive. This is usually
+ * called directly from cdrom_start_{read,write}(). However, for drq_interrupt
+ * devices, it is called from an interrupt when the drive is ready to accept
+ * the command.
  */
 static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
 {
@@ -821,11 +741,11 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
                 * is larger than the buffer size.
                 */
                if (nskip > 0) {
-                       /* Sanity check... */
+                       /* sanity check... */
                        if (rq->current_nr_sectors !=
                            bio_cur_sectors(rq->bio)) {
                                printk(KERN_ERR "%s: %s: buffer botch (%u)\n",
-                                               drive->name, __FUNCTION__,
+                                               drive->name, __func__,
                                                rq->current_nr_sectors);
                                cdrom_end_request(drive, 0);
                                return ide_stopped;
@@ -838,10 +758,10 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
                /* the immediate bit */
                rq->cmd[1] = 1 << 3;
 #endif
-       /* Set up the command */
+       /* set up the command */
        rq->timeout = ATAPI_WAIT_PC;
 
-       /* Send the command to the drive and return. */
+       /* send the command to the drive and return */
        return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
 }
 
@@ -849,7 +769,7 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
 #define IDECD_SEEK_TIMER       (5 * WAIT_MIN_SLEEP)    /* 100 ms */
 #define IDECD_SEEK_TIMEOUT     (2 * WAIT_CMD)          /* 20 sec */
 
-static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
+static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
 {
        struct cdrom_info *info = drive->driver_data;
        int stat;
@@ -861,19 +781,13 @@ static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
        info->cd_flags |= IDE_CD_FLAG_SEEKING;
 
        if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
-               if (--retry == 0) {
-                       /*
-                        * this condition is far too common, to bother
-                        * users about it
-                        */
-                       /* printk("%s: disabled DSC seek overlap\n", drive->name);*/ 
+               if (--retry == 0)
                        drive->dsc_overlap = 0;
-               }
        }
        return ide_stopped;
 }
 
-static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
+static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
 {
        struct request *rq = HWGROUP(drive)->rq;
        sector_t frame = rq->sector;
@@ -888,36 +802,40 @@ static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
        return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr);
 }
 
-static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block)
+static ide_startstop_t cdrom_start_seek(ide_drive_t *drive, unsigned int block)
 {
        struct cdrom_info *info = drive->driver_data;
 
        info->dma = 0;
        info->start_seek = jiffies;
-       return cdrom_start_packet_command(drive, 0, cdrom_start_seek_continuation);
+       return cdrom_start_packet_command(drive, 0,
+                                         cdrom_start_seek_continuation);
 }
 
-/* Fix up a possibly partially-processed request so that we can
-   start it over entirely, or even put it back on the request queue. */
-static void restore_request (struct request *rq)
+/*
+ * Fix up a possibly partially-processed request so that we can start it over
+ * entirely, or even put it back on the request queue.
+ */
+static void restore_request(struct request *rq)
 {
        if (rq->buffer != bio_data(rq->bio)) {
-               sector_t n = (rq->buffer - (char *) bio_data(rq->bio)) / SECTOR_SIZE;
+               sector_t n =
+                       (rq->buffer - (char *)bio_data(rq->bio)) / SECTOR_SIZE;
 
                rq->buffer = bio_data(rq->bio);
                rq->nr_sectors += n;
                rq->sector -= n;
        }
-       rq->hard_cur_sectors = rq->current_nr_sectors = bio_cur_sectors(rq->bio);
+       rq->current_nr_sectors = bio_cur_sectors(rq->bio);
+       rq->hard_cur_sectors = rq->current_nr_sectors;
        rq->hard_nr_sectors = rq->nr_sectors;
        rq->hard_sector = rq->sector;
        rq->q->prep_rq_fn(rq->q, rq);
 }
 
-/****************************************************************************
- * Execute all other packet commands.
+/*
+ * All other packet commands.
  */
-
 static void ide_cd_request_sense_fixup(struct request *rq)
 {
        /*
@@ -941,7 +859,7 @@ int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
        if (rq->sense == NULL)
                rq->sense = &sense;
 
-       /* Start of retry loop. */
+       /* start of retry loop */
        do {
                int error;
                unsigned long time = jiffies;
@@ -950,41 +868,45 @@ int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
                error = ide_do_drive_cmd(drive, rq, ide_wait);
                time = jiffies - time;
 
-               /* FIXME: we should probably abort/retry or something 
-                * in case of failure */
+               /*
+                * FIXME: we should probably abort/retry or something in case of
+                * failure.
+                */
                if (rq->cmd_flags & REQ_FAILED) {
-                       /* The request failed.  Retry if it was due to a unit
-                          attention status
-                          (usually means media was changed). */
+                       /*
+                        * The request failed.  Retry if it was due to a unit
+                        * attention status (usually means media was changed).
+                        */
                        struct request_sense *reqbuf = rq->sense;
 
                        if (reqbuf->sense_key == UNIT_ATTENTION)
                                cdrom_saw_media_change(drive);
                        else if (reqbuf->sense_key == NOT_READY &&
                                 reqbuf->asc == 4 && reqbuf->ascq != 4) {
-                               /* The drive is in the process of loading
-                                  a disk.  Retry, but wait a little to give
-                                  the drive time to complete the load. */
+                               /*
+                                * The drive is in the process of loading
+                                * a disk.  Retry, but wait a little to give
+                                * the drive time to complete the load.
+                                */
                                ssleep(2);
                        } else {
-                               /* Otherwise, don't retry. */
+                               /* otherwise, don't retry */
                                retries = 0;
                        }
                        --retries;
                }
 
-               /* End of retry loop. */
+               /* end of retry loop */
        } while ((rq->cmd_flags & REQ_FAILED) && retries >= 0);
 
-       /* Return an error if the command failed. */
+       /* return an error if the command failed */
        return (rq->cmd_flags & REQ_FAILED) ? -EIO : 0;
 }
 
 /*
- * Called from blk_end_request_callback() after the data of the request
- * is completed and before the request is completed.
- * By returning value '1', blk_end_request_callback() returns immediately
- * without completing the request.
+ * Called from blk_end_request_callback() after the data of the request is
+ * completed and before the request itself is completed. By returning value '1',
+ * blk_end_request_callback() returns immediately without completing it.
  */
 static int cdrom_newpc_intr_dummy_cb(struct request *rq)
 {
@@ -1003,11 +925,11 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
        unsigned int timeout;
        u8 lowcyl, highcyl;
 
-       /* Check for errors. */
+       /* check for errors */
        dma = info->dma;
        if (dma) {
                info->dma = 0;
-               dma_error = HWIF(drive)->ide_dma_end(drive);
+               dma_error = hwif->dma_ops->dma_end(drive);
                if (dma_error) {
                        printk(KERN_ERR "%s: DMA %s error\n", drive->name,
                                        write ? "write" : "read");
@@ -1018,9 +940,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
        if (cdrom_decode_status(drive, 0, &stat))
                return ide_stopped;
 
-       /*
-        * using dma, transfer is complete now
-        */
+       /* using dma, transfer is complete now */
        if (dma) {
                if (dma_error)
                        return ide_error(drive, "dma error", stat);
@@ -1031,12 +951,10 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                goto end_request;
        }
 
-       /*
-        * ok we fall to pio :/
-        */
-       ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]) & 0x3;
-       lowcyl  = hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]);
-       highcyl = hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]);
+       /* ok we fall to pio :/ */
+       ireason = hwif->INB(hwif->io_ports.nsect_addr) & 0x3;
+       lowcyl  = hwif->INB(hwif->io_ports.lbam_addr);
+       highcyl = hwif->INB(hwif->io_ports.lbah_addr);
 
        len = lowcyl + (256 * highcyl);
 
@@ -1044,9 +962,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
        if (thislen > len)
                thislen = len;
 
-       /*
-        * If DRQ is clear, the command has completed.
-        */
+       /* If DRQ is clear, the command has completed. */
        if ((stat & DRQ_STAT) == 0) {
                if (blk_fs_request(rq)) {
                        /*
@@ -1057,7 +973,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                        if (rq->current_nr_sectors > 0) {
                                printk(KERN_ERR "%s: %s: data underrun "
                                                "(%d blocks)\n",
-                                               drive->name, __FUNCTION__,
+                                               drive->name, __func__,
                                                rq->current_nr_sectors);
                                if (!write)
                                        rq->cmd_flags |= REQ_FAILED;
@@ -1067,15 +983,13 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                        return ide_stopped;
                } else if (!blk_pc_request(rq)) {
                        ide_cd_request_sense_fixup(rq);
-                       /* Complain if we still have data left to transfer. */
+                       /* complain if we still have data left to transfer */
                        uptodate = rq->data_len ? 0 : 1;
                }
                goto end_request;
        }
 
-       /*
-        * check which way to transfer data
-        */
+       /* check which way to transfer data */
        if (ide_cd_check_ireason(drive, rq, len, ireason, write))
                return ide_stopped;
 
@@ -1111,16 +1025,12 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                xferfunc = HWIF(drive)->atapi_input_bytes;
        }
 
-       /*
-        * transfer data
-        */
+       /* transfer data */
        while (thislen > 0) {
                u8 *ptr = blk_fs_request(rq) ? NULL : rq->data;
                int blen = rq->data_len;
 
-               /*
-                * bio backed?
-                */
+               /* bio backed? */
                if (rq->bio) {
                        if (blk_fs_request(rq)) {
                                ptr = rq->buffer;
@@ -1134,11 +1044,10 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                if (!ptr) {
                        if (blk_fs_request(rq) && !write)
                                /*
-                                * If the buffers are full, cache the rest
-                                * of the data in our internal buffer.
+                                * If the buffers are full, pipe the rest into
+                                * oblivion.
                                 */
-                               cdrom_buffer_sectors(drive, rq->sector,
-                                                    thislen >> 9);
+                               ide_cd_drain_data(drive, thislen >> 9);
                        else {
                                printk(KERN_ERR "%s: confused, missing data\n",
                                                drive->name);
@@ -1184,9 +1093,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                        rq->sense_len += blen;
        }
 
-       /*
-        * pad, if necessary
-        */
+       /* pad, if necessary */
        if (!blk_fs_request(rq) && len > 0)
                ide_cd_pad_transfer(drive, xferfunc, len);
 
@@ -1230,9 +1137,7 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
                queue_hardsect_size(drive->queue) >> SECTOR_BITS;
 
        if (write) {
-               /*
-                * disk has become write protected
-                */
+               /* disk has become write protected */
                if (cd->disk->policy) {
                        cdrom_end_request(drive, 0);
                        return ide_stopped;
@@ -1243,15 +1148,9 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
                 * weirdness which might be present in the request packet.
                 */
                restore_request(rq);
-
-               /* Satisfy whatever we can of this request from our cache. */
-               if (cdrom_read_from_buffer(drive))
-                       return ide_stopped;
        }
 
-       /*
-        * use DMA, if possible / writes *must* be hardware frame aligned
-        */
+       /* use DMA, if possible / writes *must* be hardware frame aligned */
        if ((rq->nr_sectors & (sectors_per_frame - 1)) ||
            (rq->sector & (sectors_per_frame - 1))) {
                if (write) {
@@ -1262,13 +1161,10 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
        } else
                cd->dma = drive->using_dma;
 
-       /* Clear the local sector buffer. */
-       cd->nsectors_buffered = 0;
-
        if (write)
                cd->devinfo.media_written = 1;
 
-       /* Start sending the read/write request to the drive. */
+       /* start sending the read/write request to the drive */
        return cdrom_start_packet_command(drive, 32768, cdrom_start_rw_cont);
 }
 
@@ -1293,12 +1189,11 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
 
        info->dma = 0;
 
-       /*
-        * sg request
-        */
+       /* sg request */
        if (rq->bio) {
                int mask = drive->queue->dma_alignment;
-               unsigned long addr = (unsigned long) page_address(bio_page(rq->bio));
+               unsigned long addr =
+                       (unsigned long)page_address(bio_page(rq->bio));
 
                info->dma = drive->using_dma;
 
@@ -1312,15 +1207,16 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
                        info->dma = 0;
        }
 
-       /* Start sending the command to the drive. */
-       return cdrom_start_packet_command(drive, rq->data_len, cdrom_do_newpc_cont);
+       /* start sending the command to the drive */
+       return cdrom_start_packet_command(drive, rq->data_len,
+                                         cdrom_do_newpc_cont);
 }
 
-/****************************************************************************
+/*
  * cdrom driver request routine.
  */
-static ide_startstop_t
-ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
+static ide_startstop_t ide_do_rw_cdrom(ide_drive_t *drive, struct request *rq,
+                                       sector_t block)
 {
        ide_startstop_t action;
        struct cdrom_info *info = drive->driver_data;
@@ -1332,16 +1228,21 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
 
                        if ((stat & SEEK_STAT) != SEEK_STAT) {
                                if (elapsed < IDECD_SEEK_TIMEOUT) {
-                                       ide_stall_queue(drive, IDECD_SEEK_TIMER);
+                                       ide_stall_queue(drive,
+                                                       IDECD_SEEK_TIMER);
                                        return ide_stopped;
                                }
-                               printk (KERN_ERR "%s: DSC timeout\n", drive->name);
+                               printk(KERN_ERR "%s: DSC timeout\n",
+                                               drive->name);
                        }
                        info->cd_flags &= ~IDE_CD_FLAG_SEEKING;
                }
-               if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) {
+               if (rq_data_dir(rq) == READ &&
+                   IDE_LARGE_SEEK(info->last_block, block,
+                                  IDECD_SEEK_THRESHOLD) &&
+                   drive->dsc_overlap)
                        action = cdrom_start_seek(drive, block);
-               else
+               else
                        action = cdrom_start_rw(drive, rq);
                info->last_block = block;
                return action;
@@ -1349,9 +1250,7 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
                   rq->cmd_type == REQ_TYPE_ATA_PC) {
                return cdrom_do_block_pc(drive, rq);
        } else if (blk_special_request(rq)) {
-               /*
-                * right now this can only be a reset...
-                */
+               /* right now this can only be a reset... */
                cdrom_end_request(drive, 1);
                return ide_stopped;
        }
@@ -1363,18 +1262,16 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
 
 
 
-/****************************************************************************
+/*
  * Ioctl handling.
  *
- * Routines which queue packet commands take as a final argument a pointer
- * to a request_sense struct.  If execution of the command results
- * in an error with a CHECK CONDITION status, this structure will be filled
- * with the results of the subsequent request sense command.  The pointer
- * can also be NULL, in which case no sense information is returned.
+ * Routines which queue packet commands take as a final argument a pointer to a
+ * request_sense struct. If execution of the command results in an error with a
+ * CHECK CONDITION status, this structure will be filled with the results of the
+ * subsequent request sense command. The pointer can also be NULL, in which case
+ * no sense information is returned.
  */
-
-static
-void msf_from_bcd (struct atapi_msf *msf)
+static void msf_from_bcd(struct atapi_msf *msf)
 {
        msf->minute = BCD2BIN(msf->minute);
        msf->second = BCD2BIN(msf->second);
@@ -1394,8 +1291,8 @@ int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
        req.cmd_flags |= REQ_QUIET;
 
        /*
-        * Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to
-        * switch CDs instead of supporting the LOAD_UNLOAD opcode.
+        * Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to switch CDs
+        * instead of supporting the LOAD_UNLOAD opcode.
         */
        req.cmd[7] = cdi->sanyo_slot % 3;
 
@@ -1471,36 +1368,39 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
        unsigned long sectors_per_frame = SECTORS_PER_FRAME;
 
        if (toc == NULL) {
-               /* Try to allocate space. */
+               /* try to allocate space */
                toc = kmalloc(sizeof(struct atapi_toc), GFP_KERNEL);
                if (toc == NULL) {
-                       printk (KERN_ERR "%s: No cdrom TOC buffer!\n", drive->name);
+                       printk(KERN_ERR "%s: No cdrom TOC buffer!\n",
+                                       drive->name);
                        return -ENOMEM;
                }
                info->toc = toc;
        }
 
-       /* Check to see if the existing data is still valid.
-          If it is, just return. */
+       /*
+        * Check to see if the existing data is still valid. If it is,
+        * just return.
+        */
        (void) cdrom_check_status(drive, sense);
 
        if (info->cd_flags & IDE_CD_FLAG_TOC_VALID)
                return 0;
 
-       /* Try to get the total cdrom capacity and sector size. */
+       /* try to get the total cdrom capacity and sector size */
        stat = cdrom_read_capacity(drive, &toc->capacity, &sectors_per_frame,
                                   sense);
        if (stat)
                toc->capacity = 0x1fffff;
 
        set_capacity(info->disk, toc->capacity * sectors_per_frame);
-       /* Save a private copy of te TOC capacity for error handling */
+       /* save a private copy of the TOC capacity for error handling */
        drive->probed_capacity = toc->capacity * sectors_per_frame;
 
        blk_queue_hardsect_size(drive->queue,
                                sectors_per_frame << SECTOR_BITS);
 
-       /* First read just the header, so we know how long the TOC is. */
+       /* first read just the header, so we know how long the TOC is */
        stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
                                    sizeof(struct atapi_toc_header), sense);
        if (stat)
@@ -1517,7 +1417,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
        if (ntracks > MAX_TRACKS)
                ntracks = MAX_TRACKS;
 
-       /* Now read the whole schmeer. */
+       /* now read the whole schmeer */
        stat = cdrom_read_tocentry(drive, toc->hdr.first_track, 1, 0,
                                  (char *)&toc->hdr,
                                   sizeof(struct atapi_toc_header) +
@@ -1525,15 +1425,18 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
                                   sizeof(struct atapi_toc_entry), sense);
 
        if (stat && toc->hdr.first_track > 1) {
-               /* Cds with CDI tracks only don't have any TOC entries,
-                  despite of this the returned values are
-                  first_track == last_track = number of CDI tracks + 1,
-                  so that this case is indistinguishable from the same
-                  layout plus an additional audio track.
-                  If we get an error for the regular case, we assume
-                  a CDI without additional audio tracks. In this case
-                  the readable TOC is empty (CDI tracks are not included)
-                  and only holds the Leadout entry. Heiko Eißfeldt */
+               /*
+                * Cds with CDI tracks only don't have any TOC entries, despite
+                * of this the returned values are
+                * first_track == last_track = number of CDI tracks + 1,
+                * so that this case is indistinguishable from the same layout
+                * plus an additional audio track. If we get an error for the
+                * regular case, we assume a CDI without additional audio
+                * tracks. In this case the readable TOC is empty (CDI tracks
+                * are not included) and only holds the Leadout entry.
+                *
+                * Heiko Eißfeldt.
+                */
                ntracks = 0;
                stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0,
                                           (char *)&toc->hdr,
@@ -1569,14 +1472,13 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
                                toc->ent[i].track = BCD2BIN(toc->ent[i].track);
                        msf_from_bcd(&toc->ent[i].addr.msf);
                }
-               toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute,
-                                                  toc->ent[i].addr.msf.second,
-                                                  toc->ent[i].addr.msf.frame);
+               toc->ent[i].addr.lba = msf_to_lba(toc->ent[i].addr.msf.minute,
+                                                 toc->ent[i].addr.msf.second,
+                                                 toc->ent[i].addr.msf.frame);
        }
 
-       /* Read the multisession information. */
        if (toc->hdr.first_track != CDROM_LEADOUT) {
-               /* Read the multisession information. */
+               /* read the multisession information */
                stat = cdrom_read_tocentry(drive, 0, 0, 1, (char *)&ms_tmp,
                                           sizeof(ms_tmp), sense);
                if (stat)
@@ -1584,26 +1486,27 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
 
                toc->last_session_lba = be32_to_cpu(ms_tmp.ent.addr.lba);
        } else {
-               ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT;
+               ms_tmp.hdr.last_track = CDROM_LEADOUT;
+               ms_tmp.hdr.first_track = ms_tmp.hdr.last_track;
                toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */
        }
 
        if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
-               /* Re-read multisession information using MSF format */
+               /* re-read multisession information using MSF format */
                stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
                                           sizeof(ms_tmp), sense);
                if (stat)
                        return stat;
 
-               msf_from_bcd (&ms_tmp.ent.addr.msf);
+               msf_from_bcd(&ms_tmp.ent.addr.msf);
                toc->last_session_lba = msf_to_lba(ms_tmp.ent.addr.msf.minute,
-                                                  ms_tmp.ent.addr.msf.second,
+                                                  ms_tmp.ent.addr.msf.second,
                                                   ms_tmp.ent.addr.msf.frame);
        }
 
        toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
 
-       /* Now try to get the total cdrom capacity. */
+       /* now try to get the total cdrom capacity */
        stat = cdrom_get_last_written(cdi, &last_written);
        if (!stat && (last_written > toc->capacity)) {
                toc->capacity = last_written;
@@ -1628,7 +1531,8 @@ int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
                size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
 
        init_cdrom_command(&cgc, buf, size, CGC_DATA_UNKNOWN);
-       do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
+       do {
+               /* we seem to get stat=0x01,err=0x00 the first time (??) */
                stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
                if (!stat)
                        break;
@@ -1679,7 +1583,7 @@ static struct cdrom_device_ops ide_cdrom_dops = {
        .generic_packet         = ide_cdrom_packet,
 };
 
-static int ide_cdrom_register (ide_drive_t *drive, int nslots)
+static int ide_cdrom_register(ide_drive_t *drive, int nslots)
 {
        struct cdrom_info *info = drive->driver_data;
        struct cdrom_device_info *devinfo = &info->devinfo;
@@ -1697,8 +1601,7 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
        return register_cdrom(devinfo);
 }
 
-static
-int ide_cdrom_probe_capabilities (ide_drive_t *drive)
+static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
 {
        struct cdrom_info *cd = drive->driver_data;
        struct cdrom_device_info *cdi = &cd->devinfo;
@@ -1712,7 +1615,8 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
 
        if (drive->media == ide_optical) {
                cdi->mask &= ~(CDC_MO_DRIVE | CDC_RAM);
-               printk(KERN_ERR "%s: ATAPI magneto-optical drive\n", drive->name);
+               printk(KERN_ERR "%s: ATAPI magneto-optical drive\n",
+                               drive->name);
                return nslots;
        }
 
@@ -1723,11 +1627,10 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
        }
 
        /*
-        * we have to cheat a little here. the packet will eventually
-        * be queued with ide_cdrom_packet(), which extracts the
-        * drive from cdi->handle. Since this device hasn't been
-        * registered with the Uniform layer yet, it can't do this.
-        * Same goes for cdi->ops.
+        * We have to cheat a little here. the packet will eventually be queued
+        * with ide_cdrom_packet(), which extracts the drive from cdi->handle.
+        * Since this device hasn't been registered with the Uniform layer yet,
+        * it can't do this. Same goes for cdi->ops.
         */
        cdi->handle = drive;
        cdi->ops = &ide_cdrom_dops;
@@ -1796,18 +1699,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
        return nslots;
 }
 
-#ifdef CONFIG_IDE_PROC_FS
-static void ide_cdrom_add_settings(ide_drive_t *drive)
-{
-       ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL);
-}
-#else
-static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; }
-#endif
-
-/*
- * standard prep_rq_fn that builds 10 byte cmds
- */
+/* standard prep_rq_fn that builds 10 byte cmds */
 static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq)
 {
        int hard_sect = queue_hardsect_size(q);
@@ -1846,9 +1738,7 @@ static int ide_cdrom_prep_pc(struct request *rq)
 {
        u8 *c = rq->cmd;
 
-       /*
-        * Transform 6-byte read/write commands to the 10-byte version
-        */
+       /* transform 6-byte read/write commands to the 10-byte version */
        if (c[0] == READ_6 || c[0] == WRITE_6) {
                c[8] = c[4];
                c[5] = c[3];
@@ -1870,7 +1760,7 @@ static int ide_cdrom_prep_pc(struct request *rq)
                rq->errors = ILLEGAL_REQUEST;
                return BLKPREP_KILL;
        }
-       
+
        return BLKPREP_OK;
 }
 
@@ -1890,6 +1780,41 @@ struct cd_list_entry {
        unsigned int    cd_flags;
 };
 
+#ifdef CONFIG_IDE_PROC_FS
+static sector_t ide_cdrom_capacity(ide_drive_t *drive)
+{
+       unsigned long capacity, sectors_per_frame;
+
+       if (cdrom_read_capacity(drive, &capacity, &sectors_per_frame, NULL))
+               return 0;
+
+       return capacity * sectors_per_frame;
+}
+
+static int proc_idecd_read_capacity(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+       ide_drive_t *drive = data;
+       int len;
+
+       len = sprintf(page, "%llu\n", (long long)ide_cdrom_capacity(drive));
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+}
+
+static ide_proc_entry_t idecd_proc[] = {
+       { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL },
+       { NULL, 0, NULL, NULL }
+};
+
+static void ide_cdrom_add_settings(ide_drive_t *drive)
+{
+       ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
+                       &drive->dsc_overlap, NULL);
+}
+#else
+static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; }
+#endif
+
 static const struct cd_list_entry ide_cd_quirks_list[] = {
        /* Limit transfer size per interrupt. */
        { "SAMSUNG CD-ROM SCR-2430", NULL,   IDE_CD_FLAG_LIMIT_NFRAMES      },
@@ -1947,8 +1872,7 @@ static unsigned int ide_cd_flags(struct hd_driveid *id)
        return 0;
 }
 
-static
-int ide_cdrom_setup (ide_drive_t *drive)
+static int ide_cdrom_setup(ide_drive_t *drive)
 {
        struct cdrom_info *cd = drive->driver_data;
        struct cdrom_device_info *cdi = &cd->devinfo;
@@ -1977,21 +1901,19 @@ int ide_cdrom_setup (ide_drive_t *drive)
                 id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
                cd->cd_flags |= IDE_CD_FLAG_TOCTRACKS_AS_BCD;
        else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD)
-               cdi->sanyo_slot = 3;    /* 3 => use CD in slot 0 */
+               /* 3 => use CD in slot 0 */
+               cdi->sanyo_slot = 3;
 
-       nslots = ide_cdrom_probe_capabilities (drive);
+       nslots = ide_cdrom_probe_capabilities(drive);
 
-       /*
-        * set correct block size
-        */
+       /* set correct block size */
        blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE);
 
-       if (drive->autotune == IDE_TUNE_DEFAULT ||
-           drive->autotune == IDE_TUNE_AUTO)
-               drive->dsc_overlap = (drive->next != drive);
+       drive->dsc_overlap = (drive->next != drive);
 
        if (ide_cdrom_register(drive, nslots)) {
-               printk (KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
+               printk(KERN_ERR "%s: %s failed to register device with the"
+                               " cdrom driver.\n", drive->name, __func__);
                cd->devinfo.handle = NULL;
                return 1;
        }
@@ -1999,19 +1921,6 @@ int ide_cdrom_setup (ide_drive_t *drive)
        return 0;
 }
 
-#ifdef CONFIG_IDE_PROC_FS
-static
-sector_t ide_cdrom_capacity (ide_drive_t *drive)
-{
-       unsigned long capacity, sectors_per_frame;
-
-       if (cdrom_read_capacity(drive, &capacity, &sectors_per_frame, NULL))
-               return 0;
-
-       return capacity * sectors_per_frame;
-}
-#endif
-
 static void ide_cd_remove(ide_drive_t *drive)
 {
        struct cdrom_info *info = drive->driver_data;
@@ -2030,7 +1939,6 @@ static void ide_cd_release(struct kref *kref)
        ide_drive_t *drive = info->drive;
        struct gendisk *g = info->disk;
 
-       kfree(info->buffer);
        kfree(info->toc);
        if (devinfo->handle == drive)
                unregister_cdrom(devinfo);
@@ -2044,23 +1952,6 @@ static void ide_cd_release(struct kref *kref)
 
 static int ide_cd_probe(ide_drive_t *);
 
-#ifdef CONFIG_IDE_PROC_FS
-static int proc_idecd_read_capacity
-       (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
-       ide_drive_t *drive = data;
-       int len;
-
-       len = sprintf(page,"%llu\n", (long long)ide_cdrom_capacity(drive));
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
-}
-
-static ide_proc_entry_t idecd_proc[] = {
-       { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL },
-       { NULL, 0, NULL, NULL }
-};
-#endif
-
 static ide_driver_t ide_cdrom_driver = {
        .gen_driver = {
                .owner          = THIS_MODULE,
@@ -2081,20 +1972,17 @@ static ide_driver_t ide_cdrom_driver = {
 #endif
 };
 
-static int idecd_open(struct inode * inode, struct file * file)
+static int idecd_open(struct inode *inode, struct file *file)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
        struct cdrom_info *info;
        int rc = -ENOMEM;
 
-       if (!(info = ide_cd_get(disk)))
+       info = ide_cd_get(disk);
+       if (!info)
                return -ENXIO;
 
-       if (!info->buffer)
-               info->buffer = kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL|__GFP_REPEAT);
-
-       if (info->buffer)
-               rc = cdrom_open(&info->devinfo, inode, file);
+       rc = cdrom_open(&info->devinfo, inode, file);
 
        if (rc < 0)
                ide_cd_put(info);
@@ -2102,12 +1990,12 @@ static int idecd_open(struct inode * inode, struct file * file)
        return rc;
 }
 
-static int idecd_release(struct inode * inode, struct file * file)
+static int idecd_release(struct inode *inode, struct file *file)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
        struct cdrom_info *info = ide_cd_g(disk);
 
-       cdrom_release (&info->devinfo, file);
+       cdrom_release(&info->devinfo, file);
 
        ide_cd_put(info);
 
@@ -2139,7 +2027,7 @@ static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg)
        struct packet_command cgc;
        char buffer[16];
        int stat;
-       char spindown;
+       char spindown;
 
        init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
 
@@ -2148,12 +2036,12 @@ static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg)
                return stat;
 
        spindown = buffer[11] & 0x0f;
-       if (copy_to_user((void __user *)arg, &spindown, sizeof (char)))
+       if (copy_to_user((void __user *)arg, &spindown, sizeof(char)))
                return -EFAULT;
        return 0;
 }
 
-static int idecd_ioctl (struct inode *inode, struct file *file,
+static int idecd_ioctl(struct inode *inode, struct file *file,
                        unsigned int cmd, unsigned long arg)
 {
        struct block_device *bdev = inode->i_bdev;
@@ -2161,13 +2049,13 @@ static int idecd_ioctl (struct inode *inode, struct file *file,
        int err;
 
        switch (cmd) {
-       case CDROMSETSPINDOWN:
+       case CDROMSETSPINDOWN:
                return idecd_set_spindown(&info->devinfo, arg);
-       case CDROMGETSPINDOWN:
+       case CDROMGETSPINDOWN:
                return idecd_get_spindown(&info->devinfo, arg);
        default:
                break;
-       }
+       }
 
        err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg);
        if (err == -EINVAL)
@@ -2193,16 +2081,16 @@ static int idecd_revalidate_disk(struct gendisk *disk)
 }
 
 static struct block_device_operations idecd_ops = {
-       .owner          = THIS_MODULE,
-       .open           = idecd_open,
-       .release        = idecd_release,
-       .ioctl          = idecd_ioctl,
-       .media_changed  = idecd_media_changed,
-       .revalidate_disk= idecd_revalidate_disk
+       .owner                  = THIS_MODULE,
+       .open                   = idecd_open,
+       .release                = idecd_release,
+       .ioctl                  = idecd_ioctl,
+       .media_changed          = idecd_media_changed,
+       .revalidate_disk        = idecd_revalidate_disk
 };
 
-/* options */
-static char *ignore = NULL;
+/* module options */
+static char *ignore;
 
 module_param(ignore, charp, 0400);
 MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
@@ -2222,17 +2110,20 @@ static int ide_cd_probe(ide_drive_t *drive)
        /* skip drives that we were told to ignore */
        if (ignore != NULL) {
                if (strstr(ignore, drive->name)) {
-                       printk(KERN_INFO "ide-cd: ignoring drive %s\n", drive->name);
+                       printk(KERN_INFO "ide-cd: ignoring drive %s\n",
+                                        drive->name);
                        goto failed;
                }
        }
        if (drive->scsi) {
-               printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name);
+               printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi "
+                                "emulation.\n", drive->name);
                goto failed;
        }
        info = kzalloc(sizeof(struct cdrom_info), GFP_KERNEL);
        if (info == NULL) {
-               printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name);
+               printk(KERN_ERR "%s: Can't allocate a cdrom structure\n",
+                               drive->name);
                goto failed;
        }
 
index 22e3751a681e0ce627aa1fb21cb95a88de298f8a..a58801c4484d309177afe8b7d32aa77c7ac7f91f 100644 (file)
@@ -119,10 +119,6 @@ struct cdrom_info {
 
        struct atapi_toc *toc;
 
-       unsigned long   sector_buffered;
-       unsigned long   nsectors_buffered;
-       unsigned char   *buffer;
-
        /* The result of the last successful request sense command
           on this device. */
        struct request_sense sense_data;
index 39501d130256109ad50d06a6b904249e9163f08a..8e08d083fce95cba5f091b0a1892f938f8dfba11 100644 (file)
@@ -16,8 +16,6 @@
 
 #define IDEDISK_VERSION        "1.18"
 
-//#define DEBUG
-
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -88,7 +86,7 @@ static void ide_disk_put(struct ide_disk_obj *idkp)
  *
  * It is called only once for each drive.
  */
-static int lba_capacity_is_ok (struct hd_driveid *id)
+static int lba_capacity_is_ok(struct hd_driveid *id)
 {
        unsigned long lba_sects, chs_sects, head, tail;
 
@@ -176,7 +174,8 @@ static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
  * __ide_do_rw_disk() issues READ and WRITE commands to a disk,
  * using LBA if supported, or CHS otherwise, to address sectors.
  */
-static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block)
+static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
+                                       sector_t block)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        unsigned int dma        = drive->using_dma;
@@ -228,7 +227,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
                        tf->device = (block >> 8) & 0xf;
                }
        } else {
-               unsigned int sect,head,cyl,track;
+               unsigned int sect, head, cyl, track;
+
                track = (int)block / drive->sect;
                sect  = (int)block % drive->sect + 1;
                head  = track % drive->head;
@@ -271,7 +271,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
  * 1073741822 == 549756 MB or 48bit addressing fake drive
  */
 
-static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block)
+static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
+                                     sector_t block)
 {
        ide_hwif_t *hwif = HWIF(drive);
 
@@ -452,7 +453,7 @@ static void idedisk_check_hpa(ide_drive_t *drive)
  * in above order (i.e., if value of higher priority is available,
  * reset will be ignored).
  */
-static void init_idedisk_capacity (ide_drive_t  *drive)
+static void init_idedisk_capacity(ide_drive_t *drive)
 {
        struct hd_driveid *id = drive->id;
        /*
@@ -479,7 +480,7 @@ static void init_idedisk_capacity (ide_drive_t  *drive)
        }
 }
 
-static sector_t idedisk_capacity (ide_drive_t *drive)
+static sector_t idedisk_capacity(ide_drive_t *drive)
 {
        return drive->capacity64 - drive->sect0;
 }
@@ -524,10 +525,11 @@ static int proc_idedisk_read_cache
        int             len;
 
        if (drive->id_read)
-               len = sprintf(out,"%i\n", drive->id->buf_size / 2);
+               len = sprintf(out, "%i\n", drive->id->buf_size / 2);
        else
-               len = sprintf(out,"(none)\n");
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+               len = sprintf(out, "(none)\n");
+
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 static int proc_idedisk_read_capacity
@@ -536,54 +538,52 @@ static int proc_idedisk_read_capacity
        ide_drive_t*drive = (ide_drive_t *)data;
        int len;
 
-       len = sprintf(page,"%llu\n", (long long)idedisk_capacity(drive));
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       len = sprintf(page, "%llu\n", (long long)idedisk_capacity(drive));
+
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
-static int proc_idedisk_read_smart_thresholds
-       (char *page, char **start, off_t off, int count, int *eof, void *data)
+static int proc_idedisk_read_smart(char *page, char **start, off_t off,
+                                  int count, int *eof, void *data, u8 sub_cmd)
 {
        ide_drive_t     *drive = (ide_drive_t *)data;
        int             len = 0, i = 0;
 
-       if (get_smart_data(drive, page, SMART_READ_THRESHOLDS) == 0) {
+       if (get_smart_data(drive, page, sub_cmd) == 0) {
                unsigned short *val = (unsigned short *) page;
                char *out = ((char *)val) + (SECTOR_WORDS * 4);
                page = out;
                do {
-                       out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
+                       out += sprintf(out, "%04x%c", le16_to_cpu(*val),
+                                      (++i & 7) ? ' ' : '\n');
                        val += 1;
                } while (i < (SECTOR_WORDS * 2));
                len = out - page;
        }
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
-static int proc_idedisk_read_smart_values
+static int proc_idedisk_read_sv
        (char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-       ide_drive_t     *drive = (ide_drive_t *)data;
-       int             len = 0, i = 0;
+       return proc_idedisk_read_smart(page, start, off, count, eof, data,
+                                      SMART_READ_VALUES);
+}
 
-       if (get_smart_data(drive, page, SMART_READ_VALUES) == 0) {
-               unsigned short *val = (unsigned short *) page;
-               char *out = ((char *)val) + (SECTOR_WORDS * 4);
-               page = out;
-               do {
-                       out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
-                       val += 1;
-               } while (i < (SECTOR_WORDS * 2));
-               len = out - page;
-       }
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+static int proc_idedisk_read_st
+       (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+       return proc_idedisk_read_smart(page, start, off, count, eof, data,
+                                      SMART_READ_THRESHOLDS);
 }
 
 static ide_proc_entry_t idedisk_proc[] = {
-       { "cache",              S_IFREG|S_IRUGO,        proc_idedisk_read_cache,                NULL },
-       { "capacity",           S_IFREG|S_IRUGO,        proc_idedisk_read_capacity,             NULL },
-       { "geometry",           S_IFREG|S_IRUGO,        proc_ide_read_geometry,                 NULL },
-       { "smart_values",       S_IFREG|S_IRUSR,        proc_idedisk_read_smart_values,         NULL },
-       { "smart_thresholds",   S_IFREG|S_IRUSR,        proc_idedisk_read_smart_thresholds,     NULL },
+       { "cache",        S_IFREG|S_IRUGO, proc_idedisk_read_cache,    NULL },
+       { "capacity",     S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
+       { "geometry",     S_IFREG|S_IRUGO, proc_ide_read_geometry,     NULL },
+       { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv,       NULL },
+       { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st,   NULL },
        { NULL, 0, NULL, NULL }
 };
 #endif /* CONFIG_IDE_PROC_FS */
@@ -625,12 +625,13 @@ static int set_multcount(ide_drive_t *drive, int arg)
        if (drive->special.b.set_multmode)
                return -EBUSY;
 
-       ide_init_drive_cmd (&rq);
+       ide_init_drive_cmd(&rq);
        rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
 
        drive->mult_req = arg;
        drive->special.b.set_multmode = 1;
-       (void) ide_do_drive_cmd (drive, &rq, ide_wait);
+       (void)ide_do_drive_cmd(drive, &rq, ide_wait);
+
        return (drive->mult_count == arg) ? 0 : -EIO;
 }
 
@@ -706,7 +707,7 @@ static int write_cache(ide_drive_t *drive, int arg)
        return err;
 }
 
-static int do_idedisk_flushcache (ide_drive_t *drive)
+static int do_idedisk_flushcache(ide_drive_t *drive)
 {
        ide_task_t args;
 
@@ -719,7 +720,7 @@ static int do_idedisk_flushcache (ide_drive_t *drive)
        return ide_no_data_taskfile(drive, &args);
 }
 
-static int set_acoustic (ide_drive_t *drive, int arg)
+static int set_acoustic(ide_drive_t *drive, int arg)
 {
        ide_task_t args;
 
@@ -753,7 +754,7 @@ static int set_lba_addressing(ide_drive_t *drive, int arg)
                return 0;
 
        if (!idedisk_supports_lba48(drive->id))
-                return -EIO;
+               return -EIO;
        drive->addressing = arg;
        return 0;
 }
@@ -763,23 +764,35 @@ static void idedisk_add_settings(ide_drive_t *drive)
 {
        struct hd_driveid *id = drive->id;
 
-       ide_add_setting(drive,  "bios_cyl",     SETTING_RW,     TYPE_INT,       0,      65535,                  1,      1,      &drive->bios_cyl,       NULL);
-       ide_add_setting(drive,  "bios_head",    SETTING_RW,     TYPE_BYTE,      0,      255,                    1,      1,      &drive->bios_head,      NULL);
-       ide_add_setting(drive,  "bios_sect",    SETTING_RW,     TYPE_BYTE,      0,      63,                     1,      1,      &drive->bios_sect,      NULL);
-       ide_add_setting(drive,  "address",      SETTING_RW,     TYPE_BYTE,      0,      2,                      1,      1,      &drive->addressing,     set_lba_addressing);
-       ide_add_setting(drive,  "multcount",    SETTING_RW,     TYPE_BYTE,      0,      id->max_multsect,       1,      1,      &drive->mult_count,     set_multcount);
-       ide_add_setting(drive,  "nowerr",       SETTING_RW,     TYPE_BYTE,      0,      1,                      1,      1,      &drive->nowerr,         set_nowerr);
-       ide_add_setting(drive,  "lun",          SETTING_RW,     TYPE_INT,       0,      7,                      1,      1,      &drive->lun,            NULL);
-       ide_add_setting(drive,  "wcache",       SETTING_RW,     TYPE_BYTE,      0,      1,                      1,      1,      &drive->wcache,         write_cache);
-       ide_add_setting(drive,  "acoustic",     SETTING_RW,     TYPE_BYTE,      0,      254,                    1,      1,      &drive->acoustic,       set_acoustic);
-       ide_add_setting(drive,  "failures",     SETTING_RW,     TYPE_INT,       0,      65535,                  1,      1,      &drive->failures,       NULL);
-       ide_add_setting(drive,  "max_failures", SETTING_RW,     TYPE_INT,       0,      65535,                  1,      1,      &drive->max_failures,   NULL);
+       ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
+                       &drive->bios_cyl, NULL);
+       ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
+                       &drive->bios_head, NULL);
+       ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1,
+                       &drive->bios_sect, NULL);
+       ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1,
+                       &drive->addressing, set_lba_addressing);
+       ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0,
+                       id->max_multsect, 1, 1, &drive->mult_count,
+                       set_multcount);
+       ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
+                       &drive->nowerr, set_nowerr);
+       ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1,
+                       &drive->lun, NULL);
+       ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
+                       &drive->wcache, write_cache);
+       ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1,
+                       &drive->acoustic, set_acoustic);
+       ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
+                       &drive->failures, NULL);
+       ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535,
+                       1, 1, &drive->max_failures, NULL);
 }
 #else
 static inline void idedisk_add_settings(ide_drive_t *drive) { ; }
 #endif
 
-static void idedisk_setup (ide_drive_t *drive)
+static void idedisk_setup(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
        struct hd_driveid *id = drive->id;
@@ -792,11 +805,10 @@ static void idedisk_setup (ide_drive_t *drive)
 
        if (drive->removable) {
                /*
-                * Removable disks (eg. SYQUEST); ignore 'WD' drives 
+                * Removable disks (eg. SYQUEST); ignore 'WD' drives
                 */
-               if (id->model[0] != 'W' || id->model[1] != 'D') {
+               if (id->model[0] != 'W' || id->model[1] != 'D')
                        drive->doorlocking = 1;
-               }
        }
 
        (void)set_lba_addressing(drive, 1);
@@ -810,10 +822,11 @@ static void idedisk_setup (ide_drive_t *drive)
                blk_queue_max_sectors(drive->queue, max_s);
        }
 
-       printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, drive->queue->max_sectors / 2);
+       printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
+                        drive->queue->max_sectors / 2);
 
        /* calculate drive capacity, and select LBA if possible */
-       init_idedisk_capacity (drive);
+       init_idedisk_capacity(drive);
 
        /* limit drive capacity to 137GB if LBA48 cannot be used */
        if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
@@ -826,9 +839,9 @@ static void idedisk_setup (ide_drive_t *drive)
 
        if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
                if (drive->capacity64 > 1ULL << 28) {
-                       printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode will"
-                                        " be used for accessing sectors > %u\n",
-                                        drive->name, 1 << 28);
+                       printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
+                                        " will be used for accessing sectors "
+                                        "> %u\n", drive->name, 1 << 28);
                } else
                        drive->addressing = 0;
        }
@@ -837,7 +850,8 @@ static void idedisk_setup (ide_drive_t *drive)
         * if possible, give fdisk access to more of the drive,
         * by correcting bios_cyls:
         */
-       capacity = idedisk_capacity (drive);
+       capacity = idedisk_capacity(drive);
+
        if (!drive->forced_geom) {
 
                if (idedisk_supports_lba48(drive->id)) {
@@ -993,7 +1007,8 @@ static int idedisk_open(struct inode *inode, struct file *filp)
        struct ide_disk_obj *idkp;
        ide_drive_t *drive;
 
-       if (!(idkp = ide_disk_get(disk)))
+       idkp = ide_disk_get(disk);
+       if (idkp == NULL)
                return -ENXIO;
 
        drive = idkp->drive;
@@ -1115,13 +1130,13 @@ static int idedisk_revalidate_disk(struct gendisk *disk)
 }
 
 static struct block_device_operations idedisk_ops = {
-       .owner          = THIS_MODULE,
-       .open           = idedisk_open,
-       .release        = idedisk_release,
-       .ioctl          = idedisk_ioctl,
-       .getgeo         = idedisk_getgeo,
-       .media_changed  = idedisk_media_changed,
-       .revalidate_disk= idedisk_revalidate_disk
+       .owner                  = THIS_MODULE,
+       .open                   = idedisk_open,
+       .release                = idedisk_release,
+       .ioctl                  = idedisk_ioctl,
+       .getgeo                 = idedisk_getgeo,
+       .media_changed          = idedisk_media_changed,
+       .revalidate_disk        = idedisk_revalidate_disk
 };
 
 MODULE_DESCRIPTION("ATA DISK Driver");
@@ -1184,7 +1199,7 @@ failed:
        return -ENODEV;
 }
 
-static void __exit idedisk_exit (void)
+static void __exit idedisk_exit(void)
 {
        driver_unregister(&idedisk_driver.gen_driver);
 }
index d61e5788d310f06dc42c12d7f7cd507e8fa10a39..c352cf27b6e7a08f90f70ea81ebe380705a676e0 100644 (file)
@@ -102,7 +102,7 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive)
 {
        u8 stat = 0, dma_stat = 0;
 
-       dma_stat = HWIF(drive)->ide_dma_end(drive);
+       dma_stat = drive->hwif->dma_ops->dma_end(drive);
        stat = ide_read_status(drive);
 
        if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
@@ -394,7 +394,7 @@ void ide_dma_off_quietly(ide_drive_t *drive)
        drive->using_dma = 0;
        ide_toggle_bounce(drive, 0);
 
-       drive->hwif->dma_host_set(drive, 0);
+       drive->hwif->dma_ops->dma_host_set(drive, 0);
 }
 
 EXPORT_SYMBOL(ide_dma_off_quietly);
@@ -427,7 +427,7 @@ void ide_dma_on(ide_drive_t *drive)
        drive->using_dma = 1;
        ide_toggle_bounce(drive, 1);
 
-       drive->hwif->dma_host_set(drive, 1);
+       drive->hwif->dma_ops->dma_host_set(drive, 1);
 }
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_SFF
@@ -482,11 +482,12 @@ int ide_dma_setup(ide_drive_t *drive)
 
 EXPORT_SYMBOL_GPL(ide_dma_setup);
 
-static void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
+void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
 {
        /* issue cmd to drive */
        ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
 }
+EXPORT_SYMBOL_GPL(ide_dma_exec_cmd);
 
 void ide_dma_start(ide_drive_t *drive)
 {
@@ -532,7 +533,7 @@ int __ide_dma_end (ide_drive_t *drive)
 EXPORT_SYMBOL(__ide_dma_end);
 
 /* returns 1 if dma irq issued, 0 otherwise */
-static int __ide_dma_test_irq(ide_drive_t *drive)
+int ide_dma_test_irq(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        u8 dma_stat             = hwif->INB(hwif->dma_status);
@@ -542,9 +543,10 @@ static int __ide_dma_test_irq(ide_drive_t *drive)
                return 1;
        if (!drive->waiting_for_dma)
                printk(KERN_WARNING "%s: (%s) called while not waiting\n",
-                       drive->name, __FUNCTION__);
+                       drive->name, __func__);
        return 0;
 }
+EXPORT_SYMBOL_GPL(ide_dma_test_irq);
 #else
 static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; }
 #endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
@@ -574,6 +576,7 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
 {
        struct hd_driveid *id = drive->id;
        ide_hwif_t *hwif = drive->hwif;
+       const struct ide_port_ops *port_ops = hwif->port_ops;
        unsigned int mask = 0;
 
        switch(base) {
@@ -581,8 +584,8 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
                if ((id->field_valid & 4) == 0)
                        break;
 
-               if (hwif->udma_filter)
-                       mask = hwif->udma_filter(drive);
+               if (port_ops && port_ops->udma_filter)
+                       mask = port_ops->udma_filter(drive);
                else
                        mask = hwif->ultra_mask;
                mask &= id->dma_ultra;
@@ -598,8 +601,8 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
        case XFER_MW_DMA_0:
                if ((id->field_valid & 2) == 0)
                        break;
-               if (hwif->mdma_filter)
-                       mask = hwif->mdma_filter(drive);
+               if (port_ops && port_ops->mdma_filter)
+                       mask = port_ops->mdma_filter(drive);
                else
                        mask = hwif->mwdma_mask;
                mask &= id->dma_mword;
@@ -703,17 +706,8 @@ static int ide_tune_dma(ide_drive_t *drive)
 
        speed = ide_max_dma_mode(drive);
 
-       if (!speed) {
-                /* is this really correct/needed? */
-               if ((hwif->host_flags & IDE_HFLAG_CY82C693) &&
-                   ide_dma_good_drive(drive))
-                       return 1;
-               else
-                       return 0;
-       }
-
-       if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
-               return 1;
+       if (!speed)
+               return 0;
 
        if (ide_set_dma_mode(drive, speed))
                return 0;
@@ -810,15 +804,15 @@ void ide_dma_timeout (ide_drive_t *drive)
 
        printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
 
-       if (hwif->ide_dma_test_irq(drive))
+       if (hwif->dma_ops->dma_test_irq(drive))
                return;
 
-       hwif->ide_dma_end(drive);
+       hwif->dma_ops->dma_end(drive);
 }
 
 EXPORT_SYMBOL(ide_dma_timeout);
 
-static void ide_release_dma_engine(ide_hwif_t *hwif)
+void ide_release_dma_engine(ide_hwif_t *hwif)
 {
        if (hwif->dmatable_cpu) {
                struct pci_dev *pdev = to_pci_dev(hwif->dev);
@@ -829,28 +823,7 @@ static void ide_release_dma_engine(ide_hwif_t *hwif)
        }
 }
 
-static int ide_release_iomio_dma(ide_hwif_t *hwif)
-{
-       release_region(hwif->dma_base, 8);
-       if (hwif->extra_ports)
-               release_region(hwif->extra_base, hwif->extra_ports);
-       return 1;
-}
-
-/*
- * Needed for allowing full modular support of ide-driver
- */
-int ide_release_dma(ide_hwif_t *hwif)
-{
-       ide_release_dma_engine(hwif);
-
-       if (hwif->mmio)
-               return 1;
-       else
-               return ide_release_iomio_dma(hwif);
-}
-
-static int ide_allocate_dma_engine(ide_hwif_t *hwif)
+int ide_allocate_dma_engine(ide_hwif_t *hwif)
 {
        struct pci_dev *pdev = to_pci_dev(hwif->dev);
 
@@ -862,65 +835,25 @@ static int ide_allocate_dma_engine(ide_hwif_t *hwif)
                return 0;
 
        printk(KERN_ERR "%s: -- Error, unable to allocate DMA table.\n",
-              hwif->cds->name);
+                       hwif->name);
 
        return 1;
 }
-
-static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base)
-{
-       printk(KERN_INFO "    %s: MMIO-DMA ", hwif->name);
-
-       return 0;
-}
-
-static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base)
-{
-       printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx",
-              hwif->name, base, base + 7);
-
-       if (!request_region(base, 8, hwif->name)) {
-               printk(" -- Error, ports in use.\n");
-               return 1;
-       }
-
-       if (hwif->cds->extra) {
-               hwif->extra_base = base + (hwif->channel ? 8 : 16);
-
-               if (!hwif->mate || !hwif->mate->extra_ports) {
-                       if (!request_region(hwif->extra_base,
-                                           hwif->cds->extra, hwif->cds->name)) {
-                               printk(" -- Error, extra ports in use.\n");
-                               release_region(base, 8);
-                               return 1;
-                       }
-                       hwif->extra_ports = hwif->cds->extra;
-               }
-       }
-
-       return 0;
-}
-
-static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base)
-{
-       if (hwif->mmio)
-               return ide_mapped_mmio_dma(hwif, base);
-
-       return ide_iomio_dma(hwif, base);
-}
+EXPORT_SYMBOL_GPL(ide_allocate_dma_engine);
+
+static const struct ide_dma_ops sff_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = ide_dma_start,
+       .dma_end                = __ide_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_timeout            = ide_dma_timeout,
+       .dma_lost_irq           = ide_dma_lost_irq,
+};
 
 void ide_setup_dma(ide_hwif_t *hwif, unsigned long base)
 {
-       u8 dma_stat;
-
-       if (ide_dma_iobase(hwif, base))
-               return;
-
-       if (ide_allocate_dma_engine(hwif)) {
-               ide_release_dma(hwif);
-               return;
-       }
-
        hwif->dma_base = base;
 
        if (!hwif->dma_command)
@@ -934,27 +867,7 @@ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base)
        if (!hwif->dma_prdtable)
                hwif->dma_prdtable      = hwif->dma_base + 4;
 
-       if (!hwif->dma_host_set)
-               hwif->dma_host_set = &ide_dma_host_set;
-       if (!hwif->dma_setup)
-               hwif->dma_setup = &ide_dma_setup;
-       if (!hwif->dma_exec_cmd)
-               hwif->dma_exec_cmd = &ide_dma_exec_cmd;
-       if (!hwif->dma_start)
-               hwif->dma_start = &ide_dma_start;
-       if (!hwif->ide_dma_end)
-               hwif->ide_dma_end = &__ide_dma_end;
-       if (!hwif->ide_dma_test_irq)
-               hwif->ide_dma_test_irq = &__ide_dma_test_irq;
-       if (!hwif->dma_timeout)
-               hwif->dma_timeout = &ide_dma_timeout;
-       if (!hwif->dma_lost_irq)
-               hwif->dma_lost_irq = &ide_dma_lost_irq;
-
-       dma_stat = hwif->INB(hwif->dma_status);
-       printk(KERN_CONT ", BIOS settings: %s:%s, %s:%s\n",
-              hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "PIO",
-              hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "PIO");
+       hwif->dma_ops = &sff_dma_ops;
 }
 
 EXPORT_SYMBOL_GPL(ide_setup_dma);
index 5f133dfb541c5e7fe4c406ef8e0775eb8a70598a..489079b8ed03fdfce46615fd7f24b6d1ecfb07ae 100644 (file)
@@ -396,7 +396,7 @@ static void idefloppy_retry_pc(ide_drive_t *drive)
 }
 
 /* The usual interrupt handler called during a packet command. */
-static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive)
 {
        idefloppy_floppy_t *floppy = drive->driver_data;
        ide_hwif_t *hwif = drive->hwif;
@@ -411,7 +411,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
        debug_log("Reached %s interrupt handler\n", __func__);
 
        if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
-               dma_error = hwif->ide_dma_end(drive);
+               dma_error = hwif->dma_ops->dma_end(drive);
                if (dma_error) {
                        printk(KERN_ERR "%s: DMA %s error\n", drive->name,
                                        rq_data_dir(rq) ? "write" : "read");
@@ -465,10 +465,10 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
        }
 
        /* Get the number of bytes to transfer */
-       bcount = (hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]) << 8) |
-                 hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]);
+       bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) |
+                 hwif->INB(hwif->io_ports.lbam_addr);
        /* on this interrupt */
-       ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+       ireason = hwif->INB(hwif->io_ports.nsect_addr);
 
        if (ireason & CD) {
                printk(KERN_ERR "ide-floppy: CoD != 0 in %s\n", __func__);
@@ -539,7 +539,7 @@ static ide_startstop_t idefloppy_transfer_pc(ide_drive_t *drive)
                                "initiated yet DRQ isn't asserted\n");
                return startstop;
        }
-       ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+       ireason = hwif->INB(hwif->io_ports.nsect_addr);
        if ((ireason & CD) == 0 || (ireason & IO)) {
                printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while "
                                "issuing a packet command\n");
@@ -586,7 +586,7 @@ static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive)
                                "initiated yet DRQ isn't asserted\n");
                return startstop;
        }
-       ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+       ireason = hwif->INB(hwif->io_ports.nsect_addr);
        if ((ireason & CD) == 0 || (ireason & IO)) {
                printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) "
                                "while issuing a packet command\n");
@@ -663,7 +663,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
        dma = 0;
 
        if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma)
-               dma = !hwif->dma_setup(drive);
+               dma = !hwif->dma_ops->dma_setup(drive);
 
        ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
                           IDE_TFLAG_OUT_DEVICE, bcount, dma);
@@ -671,7 +671,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
        if (dma) {
                /* Begin DMA, if necessary */
                pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
-               hwif->dma_start(drive);
+               hwif->dma_ops->dma_start(drive);
        }
 
        /* Can we transfer the packet when we get the interrupt or wait? */
@@ -692,7 +692,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
                return ide_started;
        } else {
                /* Issue the packet command */
-               hwif->OUTB(WIN_PACKETCMD, hwif->io_ports[IDE_COMMAND_OFFSET]);
+               hwif->OUTB(WIN_PACKETCMD, hwif->io_ports.command_addr);
                return (*pkt_xfer_routine) (drive);
        }
 }
@@ -1596,13 +1596,13 @@ static int idefloppy_revalidate_disk(struct gendisk *disk)
 }
 
 static struct block_device_operations idefloppy_ops = {
-       .owner          = THIS_MODULE,
-       .open           = idefloppy_open,
-       .release        = idefloppy_release,
-       .ioctl          = idefloppy_ioctl,
-       .getgeo         = idefloppy_getgeo,
-       .media_changed  = idefloppy_media_changed,
-       .revalidate_disk= idefloppy_revalidate_disk
+       .owner                  = THIS_MODULE,
+       .open                   = idefloppy_open,
+       .release                = idefloppy_release,
+       .ioctl                  = idefloppy_ioctl,
+       .getgeo                 = idefloppy_getgeo,
+       .media_changed          = idefloppy_media_changed,
+       .revalidate_disk        = idefloppy_revalidate_disk
 };
 
 static int ide_floppy_probe(ide_drive_t *drive)
index 25fda0a3263fea4603d67121f4b0df29b2195a54..a6073e248f450df8e09408652024b58dcc348d95 100644 (file)
@@ -33,7 +33,7 @@ static ssize_t store_add(struct class *cls, const char *buf, size_t n)
        if (sscanf(buf, "%x:%x:%d", &base, &ctl, &irq) != 3)
                return -EINVAL;
 
-       hwif = ide_find_port(base);
+       hwif = ide_find_port();
        if (hwif == NULL)
                return -ENOENT;
 
@@ -90,19 +90,45 @@ static int __init ide_generic_init(void)
        int i;
 
        for (i = 0; i < MAX_HWIFS; i++) {
-               ide_hwif_t *hwif = &ide_hwifs[i];
+               ide_hwif_t *hwif;
                unsigned long io_addr = ide_default_io_base(i);
                hw_regs_t hw;
 
-               if (hwif->chipset == ide_unknown && io_addr) {
+               idx[i] = 0xff;
+
+               if (io_addr) {
+                       if (!request_region(io_addr, 8, DRV_NAME)) {
+                               printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX "
+                                               "not free.\n",
+                                               DRV_NAME, io_addr, io_addr + 7);
+                               continue;
+                       }
+
+                       if (!request_region(io_addr + 0x206, 1, DRV_NAME)) {
+                               printk(KERN_ERR "%s: I/O resource 0x%lX "
+                                               "not free.\n",
+                                               DRV_NAME, io_addr + 0x206);
+                               release_region(io_addr, 8);
+                               continue;
+                       }
+
+                       /*
+                        * Skip probing if the corresponding
+                        * slot is already occupied.
+                        */
+                       hwif = ide_find_port();
+                       if (hwif == NULL || hwif->index != i) {
+                               idx[i] = 0xff;
+                               continue;
+                       }
+
                        memset(&hw, 0, sizeof(hw));
                        ide_std_init_ports(&hw, io_addr, io_addr + 0x206);
                        hw.irq = ide_default_irq(io_addr);
                        ide_init_port_hw(hwif, &hw);
 
                        idx[i] = i;
-               } else
-                       idx[i] = 0xff;
+               }
        }
 
        ide_device_add_all(idx, NULL);
index 31e5afadb7e9d9762eadda85721ddbf45e740a51..3a2d8930d17ff68bd596a5828a2558bb232b2b52 100644 (file)
@@ -218,7 +218,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
                 * we could be smarter and check for current xfer_speed
                 * in struct drive etc...
                 */
-               if (drive->hwif->dma_host_set == NULL)
+               if (drive->hwif->dma_ops == NULL)
                        break;
                /*
                 * TODO: respect ->using_dma setting
@@ -298,48 +298,43 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
 void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
 {
        ide_hwif_t *hwif = drive->hwif;
+       struct ide_io_ports *io_ports = &hwif->io_ports;
        struct ide_taskfile *tf = &task->tf;
 
        if (task->tf_flags & IDE_TFLAG_IN_DATA) {
-               u16 data = hwif->INW(hwif->io_ports[IDE_DATA_OFFSET]);
+               u16 data = hwif->INW(io_ports->data_addr);
 
                tf->data = data & 0xff;
                tf->hob_data = (data >> 8) & 0xff;
        }
 
        /* be sure we're looking at the low order bits */
-       hwif->OUTB(drive->ctl & ~0x80, hwif->io_ports[IDE_CONTROL_OFFSET]);
+       hwif->OUTB(drive->ctl & ~0x80, io_ports->ctl_addr);
 
        if (task->tf_flags & IDE_TFLAG_IN_NSECT)
-               tf->nsect  = hwif->INB(hwif->io_ports[IDE_NSECTOR_OFFSET]);
+               tf->nsect  = hwif->INB(io_ports->nsect_addr);
        if (task->tf_flags & IDE_TFLAG_IN_LBAL)
-               tf->lbal   = hwif->INB(hwif->io_ports[IDE_SECTOR_OFFSET]);
+               tf->lbal   = hwif->INB(io_ports->lbal_addr);
        if (task->tf_flags & IDE_TFLAG_IN_LBAM)
-               tf->lbam   = hwif->INB(hwif->io_ports[IDE_LCYL_OFFSET]);
+               tf->lbam   = hwif->INB(io_ports->lbam_addr);
        if (task->tf_flags & IDE_TFLAG_IN_LBAH)
-               tf->lbah   = hwif->INB(hwif->io_ports[IDE_HCYL_OFFSET]);
+               tf->lbah   = hwif->INB(io_ports->lbah_addr);
        if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
-               tf->device = hwif->INB(hwif->io_ports[IDE_SELECT_OFFSET]);
+               tf->device = hwif->INB(io_ports->device_addr);
 
        if (task->tf_flags & IDE_TFLAG_LBA48) {
-               hwif->OUTB(drive->ctl | 0x80,
-                          hwif->io_ports[IDE_CONTROL_OFFSET]);
+               hwif->OUTB(drive->ctl | 0x80, io_ports->ctl_addr);
 
                if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
-                       tf->hob_feature =
-                               hwif->INB(hwif->io_ports[IDE_FEATURE_OFFSET]);
+                       tf->hob_feature = hwif->INB(io_ports->feature_addr);
                if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
-                       tf->hob_nsect   =
-                               hwif->INB(hwif->io_ports[IDE_NSECTOR_OFFSET]);
+                       tf->hob_nsect   = hwif->INB(io_ports->nsect_addr);
                if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
-                       tf->hob_lbal    =
-                               hwif->INB(hwif->io_ports[IDE_SECTOR_OFFSET]);
+                       tf->hob_lbal    = hwif->INB(io_ports->lbal_addr);
                if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
-                       tf->hob_lbam    =
-                               hwif->INB(hwif->io_ports[IDE_LCYL_OFFSET]);
+                       tf->hob_lbam    = hwif->INB(io_ports->lbam_addr);
                if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
-                       tf->hob_lbah    =
-                               hwif->INB(hwif->io_ports[IDE_HCYL_OFFSET]);
+                       tf->hob_lbah    = hwif->INB(io_ports->lbah_addr);
        }
 }
 
@@ -454,7 +449,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
                if (err == ABRT_ERR) {
                        if (drive->select.b.lba &&
                            /* some newer drives don't support WIN_SPECIFY */
-                           hwif->INB(hwif->io_ports[IDE_COMMAND_OFFSET]) ==
+                           hwif->INB(hwif->io_ports.command_addr) ==
                                WIN_SPECIFY)
                                return ide_stopped;
                } else if ((err & BAD_CRC) == BAD_CRC) {
@@ -507,8 +502,7 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u
 
        if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
                /* force an abort */
-               hwif->OUTB(WIN_IDLEIMMEDIATE,
-                          hwif->io_ports[IDE_COMMAND_OFFSET]);
+               hwif->OUTB(WIN_IDLEIMMEDIATE, hwif->io_ports.command_addr);
 
        if (rq->errors >= ERROR_MAX) {
                ide_kill_rq(drive, rq);
@@ -721,15 +715,12 @@ static ide_startstop_t do_special (ide_drive_t *drive)
 #endif
        if (s->b.set_tune) {
                ide_hwif_t *hwif = drive->hwif;
+               const struct ide_port_ops *port_ops = hwif->port_ops;
                u8 req_pio = drive->tune_req;
 
                s->b.set_tune = 0;
 
                if (set_pio_mode_abuse(drive->hwif, req_pio)) {
-
-                       if (hwif->set_pio_mode == NULL)
-                               return ide_stopped;
-
                        /*
                         * take ide_lock for drive->[no_]unmask/[no_]io_32bit
                         */
@@ -737,10 +728,10 @@ static ide_startstop_t do_special (ide_drive_t *drive)
                                unsigned long flags;
 
                                spin_lock_irqsave(&ide_lock, flags);
-                               hwif->set_pio_mode(drive, req_pio);
+                               port_ops->set_pio_mode(drive, req_pio);
                                spin_unlock_irqrestore(&ide_lock, flags);
                        } else
-                               hwif->set_pio_mode(drive, req_pio);
+                               port_ops->set_pio_mode(drive, req_pio);
                } else {
                        int keep_dma = drive->using_dma;
 
@@ -1241,12 +1232,12 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
 
        if (error < 0) {
                printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
-               (void)HWIF(drive)->ide_dma_end(drive);
+               (void)hwif->dma_ops->dma_end(drive);
                ret = ide_error(drive, "dma timeout error",
                                ide_read_status(drive));
        } else {
                printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
-               hwif->dma_timeout(drive);
+               hwif->dma_ops->dma_timeout(drive);
        }
 
        /*
@@ -1358,7 +1349,7 @@ void ide_timer_expiry (unsigned long data)
                                startstop = handler(drive);
                        } else if (drive_is_ready(drive)) {
                                if (drive->waiting_for_dma)
-                                       hwgroup->hwif->dma_lost_irq(drive);
+                                       hwif->dma_ops->dma_lost_irq(drive);
                                (void)ide_ack_intr(hwif);
                                printk(KERN_WARNING "%s: lost interrupt\n", drive->name);
                                startstop = handler(drive);
@@ -1424,7 +1415,7 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
         */
        do {
                if (hwif->irq == irq) {
-                       stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+                       stat = hwif->INB(hwif->io_ports.status_addr);
                        if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
                                /* Try to not flood the console with msgs */
                                static unsigned long last_msgtime, count;
@@ -1514,7 +1505,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
                         * Whack the status register, just in case
                         * we have a leftover pending IRQ.
                         */
-                       (void) hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+                       (void) hwif->INB(hwif->io_ports.status_addr);
 #endif /* CONFIG_BLK_DEV_IDEPCI */
                }
                spin_unlock_irqrestore(&ide_lock, flags);
index 45944219eea013f37060b6fd67a306afc2b33192..5425d3038ec2d2095b78f0b7d6e73dc09305cbb2 100644 (file)
@@ -159,17 +159,20 @@ EXPORT_SYMBOL(default_hwif_mmiops);
 void SELECT_DRIVE (ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
+       const struct ide_port_ops *port_ops = hwif->port_ops;
 
-       if (hwif->selectproc)
-               hwif->selectproc(drive);
+       if (port_ops && port_ops->selectproc)
+               port_ops->selectproc(drive);
 
-       hwif->OUTB(drive->select.all, hwif->io_ports[IDE_SELECT_OFFSET]);
+       hwif->OUTB(drive->select.all, hwif->io_ports.device_addr);
 }
 
 void SELECT_MASK (ide_drive_t *drive, int mask)
 {
-       if (HWIF(drive)->maskproc)
-               HWIF(drive)->maskproc(drive, mask);
+       const struct ide_port_ops *port_ops = drive->hwif->port_ops;
+
+       if (port_ops && port_ops->maskproc)
+               port_ops->maskproc(drive, mask);
 }
 
 /*
@@ -191,24 +194,22 @@ static void ata_vlb_sync(ide_drive_t *drive, unsigned long port)
  */
 static void ata_input_data(ide_drive_t *drive, void *buffer, u32 wcount)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       u8 io_32bit             = drive->io_32bit;
+       ide_hwif_t *hwif = drive->hwif;
+       struct ide_io_ports *io_ports = &hwif->io_ports;
+       u8 io_32bit = drive->io_32bit;
 
        if (io_32bit) {
                if (io_32bit & 2) {
                        unsigned long flags;
 
                        local_irq_save(flags);
-                       ata_vlb_sync(drive, hwif->io_ports[IDE_NSECTOR_OFFSET]);
-                       hwif->INSL(hwif->io_ports[IDE_DATA_OFFSET], buffer,
-                                  wcount);
+                       ata_vlb_sync(drive, io_ports->nsect_addr);
+                       hwif->INSL(io_ports->data_addr, buffer, wcount);
                        local_irq_restore(flags);
                } else
-                       hwif->INSL(hwif->io_ports[IDE_DATA_OFFSET], buffer,
-                                  wcount);
+                       hwif->INSL(io_ports->data_addr, buffer, wcount);
        } else
-               hwif->INSW(hwif->io_ports[IDE_DATA_OFFSET], buffer,
-                          wcount << 1);
+               hwif->INSW(io_ports->data_addr, buffer, wcount << 1);
 }
 
 /*
@@ -216,24 +217,22 @@ static void ata_input_data(ide_drive_t *drive, void *buffer, u32 wcount)
  */
 static void ata_output_data(ide_drive_t *drive, void *buffer, u32 wcount)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       u8 io_32bit             = drive->io_32bit;
+       ide_hwif_t *hwif = drive->hwif;
+       struct ide_io_ports *io_ports = &hwif->io_ports;
+       u8 io_32bit = drive->io_32bit;
 
        if (io_32bit) {
                if (io_32bit & 2) {
                        unsigned long flags;
 
                        local_irq_save(flags);
-                       ata_vlb_sync(drive, hwif->io_ports[IDE_NSECTOR_OFFSET]);
-                       hwif->OUTSL(hwif->io_ports[IDE_DATA_OFFSET], buffer,
-                                   wcount);
+                       ata_vlb_sync(drive, io_ports->nsect_addr);
+                       hwif->OUTSL(io_ports->data_addr, buffer, wcount);
                        local_irq_restore(flags);
                } else
-                       hwif->OUTSL(hwif->io_ports[IDE_DATA_OFFSET], buffer,
-                                   wcount);
+                       hwif->OUTSL(io_ports->data_addr, buffer, wcount);
        } else
-               hwif->OUTSW(hwif->io_ports[IDE_DATA_OFFSET], buffer,
-                           wcount << 1);
+               hwif->OUTSW(io_ports->data_addr, buffer, wcount << 1);
 }
 
 /*
@@ -252,14 +251,13 @@ static void atapi_input_bytes(ide_drive_t *drive, void *buffer, u32 bytecount)
 #if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
        if (MACH_IS_ATARI || MACH_IS_Q40) {
                /* Atari has a byte-swapped IDE interface */
-               insw_swapw(hwif->io_ports[IDE_DATA_OFFSET], buffer,
-                          bytecount / 2);
+               insw_swapw(hwif->io_ports.data_addr, buffer, bytecount / 2);
                return;
        }
 #endif /* CONFIG_ATARI || CONFIG_Q40 */
        hwif->ata_input_data(drive, buffer, bytecount / 4);
        if ((bytecount & 0x03) >= 2)
-               hwif->INSW(hwif->io_ports[IDE_DATA_OFFSET],
+               hwif->INSW(hwif->io_ports.data_addr,
                           (u8 *)buffer + (bytecount & ~0x03), 1);
 }
 
@@ -271,14 +269,13 @@ static void atapi_output_bytes(ide_drive_t *drive, void *buffer, u32 bytecount)
 #if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
        if (MACH_IS_ATARI || MACH_IS_Q40) {
                /* Atari has a byte-swapped IDE interface */
-               outsw_swapw(hwif->io_ports[IDE_DATA_OFFSET], buffer,
-                           bytecount / 2);
+               outsw_swapw(hwif->io_ports.data_addr, buffer, bytecount / 2);
                return;
        }
 #endif /* CONFIG_ATARI || CONFIG_Q40 */
        hwif->ata_output_data(drive, buffer, bytecount / 4);
        if ((bytecount & 0x03) >= 2)
-               hwif->OUTSW(hwif->io_ports[IDE_DATA_OFFSET],
+               hwif->OUTSW(hwif->io_ports.data_addr,
                            (u8 *)buffer + (bytecount & ~0x03), 1);
 }
 
@@ -429,7 +426,7 @@ int drive_is_ready (ide_drive_t *drive)
        u8 stat                 = 0;
 
        if (drive->waiting_for_dma)
-               return hwif->ide_dma_test_irq(drive);
+               return hwif->dma_ops->dma_test_irq(drive);
 
 #if 0
        /* need to guarantee 400ns since last command was issued */
@@ -442,7 +439,7 @@ int drive_is_ready (ide_drive_t *drive)
         * an interrupt with another pci card/device.  We make no assumptions
         * about possible isa-pnp and pci-pnp issues yet.
         */
-       if (hwif->io_ports[IDE_CONTROL_OFFSET])
+       if (hwif->io_ports.ctl_addr)
                stat = ide_read_altstatus(drive);
        else
                /* Note: this may clear a pending IRQ!! */
@@ -644,7 +641,7 @@ int ide_driveid_update(ide_drive_t *drive)
        SELECT_MASK(drive, 1);
        ide_set_irq(drive, 1);
        msleep(50);
-       hwif->OUTB(WIN_IDENTIFY, hwif->io_ports[IDE_COMMAND_OFFSET]);
+       hwif->OUTB(WIN_IDENTIFY, hwif->io_ports.command_addr);
        timeout = jiffies + WAIT_WORSTCASE;
        do {
                if (time_after(jiffies, timeout)) {
@@ -693,6 +690,7 @@ int ide_driveid_update(ide_drive_t *drive)
 int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
 {
        ide_hwif_t *hwif = drive->hwif;
+       struct ide_io_ports *io_ports = &hwif->io_ports;
        int error = 0;
        u8 stat;
 
@@ -700,8 +698,8 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
 //             msleep(50);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
-       if (hwif->dma_host_set) /* check if host supports DMA */
-               hwif->dma_host_set(drive, 0);
+       if (hwif->dma_ops)      /* check if host supports DMA */
+               hwif->dma_ops->dma_host_set(drive, 0);
 #endif
 
        /* Skip setting PIO flow-control modes on pre-EIDE drives */
@@ -731,10 +729,9 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
        SELECT_MASK(drive, 0);
        udelay(1);
        ide_set_irq(drive, 0);
-       hwif->OUTB(speed, hwif->io_ports[IDE_NSECTOR_OFFSET]);
-       hwif->OUTB(SETFEATURES_XFER, hwif->io_ports[IDE_FEATURE_OFFSET]);
-       hwif->OUTBSYNC(drive, WIN_SETFEATURES,
-                      hwif->io_ports[IDE_COMMAND_OFFSET]);
+       hwif->OUTB(speed, io_ports->nsect_addr);
+       hwif->OUTB(SETFEATURES_XFER, io_ports->feature_addr);
+       hwif->OUTBSYNC(drive, WIN_SETFEATURES, io_ports->command_addr);
        if (drive->quirk_list == 2)
                ide_set_irq(drive, 1);
 
@@ -759,8 +756,8 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
 #ifdef CONFIG_BLK_DEV_IDEDMA
        if ((speed >= XFER_SW_DMA_0 || (hwif->host_flags & IDE_HFLAG_VDMA)) &&
            drive->using_dma)
-               hwif->dma_host_set(drive, 1);
-       else if (hwif->dma_host_set)    /* check if host supports DMA */
+               hwif->dma_ops->dma_host_set(drive, 1);
+       else if (hwif->dma_ops) /* check if host supports DMA */
                ide_dma_off_quietly(drive);
 #endif
 
@@ -842,7 +839,7 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
 
        spin_lock_irqsave(&ide_lock, flags);
        __ide_set_handler(drive, handler, timeout, expiry);
-       hwif->OUTBSYNC(drive, cmd, hwif->io_ports[IDE_COMMAND_OFFSET]);
+       hwif->OUTBSYNC(drive, cmd, hwif->io_ports.command_addr);
        /*
         * Drive takes 400nS to respond, we must avoid the IRQ being
         * serviced before that.
@@ -905,10 +902,11 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
 {
        ide_hwgroup_t *hwgroup  = HWGROUP(drive);
        ide_hwif_t *hwif        = HWIF(drive);
+       const struct ide_port_ops *port_ops = hwif->port_ops;
        u8 tmp;
 
-       if (hwif->reset_poll != NULL) {
-               if (hwif->reset_poll(drive)) {
+       if (port_ops && port_ops->reset_poll) {
+               if (port_ops->reset_poll(drive)) {
                        printk(KERN_ERR "%s: host reset_poll failure for %s.\n",
                                hwif->name, drive->name);
                        return ide_stopped;
@@ -974,6 +972,8 @@ static void ide_disk_pre_reset(ide_drive_t *drive)
 
 static void pre_reset(ide_drive_t *drive)
 {
+       const struct ide_port_ops *port_ops = drive->hwif->port_ops;
+
        if (drive->media == ide_disk)
                ide_disk_pre_reset(drive);
        else
@@ -994,8 +994,8 @@ static void pre_reset(ide_drive_t *drive)
                return;
        }
 
-       if (HWIF(drive)->pre_reset != NULL)
-               HWIF(drive)->pre_reset(drive);
+       if (port_ops && port_ops->pre_reset)
+               port_ops->pre_reset(drive);
 
        if (drive->current_speed != 0xff)
                drive->desired_speed = drive->current_speed;
@@ -1023,12 +1023,16 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
        unsigned long flags;
        ide_hwif_t *hwif;
        ide_hwgroup_t *hwgroup;
+       struct ide_io_ports *io_ports;
+       const struct ide_port_ops *port_ops;
        u8 ctl;
 
        spin_lock_irqsave(&ide_lock, flags);
        hwif = HWIF(drive);
        hwgroup = HWGROUP(drive);
 
+       io_ports = &hwif->io_ports;
+
        /* We must not reset with running handlers */
        BUG_ON(hwgroup->handler != NULL);
 
@@ -1038,8 +1042,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
                pre_reset(drive);
                SELECT_DRIVE(drive);
                udelay (20);
-               hwif->OUTBSYNC(drive, WIN_SRST,
-                              hwif->io_ports[IDE_COMMAND_OFFSET]);
+               hwif->OUTBSYNC(drive, WIN_SRST, io_ports->command_addr);
                ndelay(400);
                hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
                hwgroup->polling = 1;
@@ -1055,7 +1058,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
        for (unit = 0; unit < MAX_DRIVES; ++unit)
                pre_reset(&hwif->drives[unit]);
 
-       if (hwif->io_ports[IDE_CONTROL_OFFSET] == 0) {
+       if (io_ports->ctl_addr == 0) {
                spin_unlock_irqrestore(&ide_lock, flags);
                return ide_stopped;
        }
@@ -1070,14 +1073,14 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
         * recover from reset very quickly, saving us the first 50ms wait time.
         */
        /* set SRST and nIEN */
-       hwif->OUTBSYNC(drive, drive->ctl|6, hwif->io_ports[IDE_CONTROL_OFFSET]);
+       hwif->OUTBSYNC(drive, drive->ctl|6, io_ports->ctl_addr);
        /* more than enough time */
        udelay(10);
        if (drive->quirk_list == 2)
                ctl = drive->ctl;       /* clear SRST and nIEN */
        else
                ctl = drive->ctl | 2;   /* clear SRST, leave nIEN */
-       hwif->OUTBSYNC(drive, ctl, hwif->io_ports[IDE_CONTROL_OFFSET]);
+       hwif->OUTBSYNC(drive, ctl, io_ports->ctl_addr);
        /* more than enough time */
        udelay(10);
        hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
@@ -1089,8 +1092,9 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
         * state when the disks are reset this way. At least, the Winbond
         * 553 documentation says that
         */
-       if (hwif->resetproc)
-               hwif->resetproc(drive);
+       port_ops = hwif->port_ops;
+       if (port_ops && port_ops->resetproc)
+               port_ops->resetproc(drive);
 
        spin_unlock_irqrestore(&ide_lock, flags);
        return ide_started;
@@ -1121,7 +1125,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
                 * about locking issues (2.5 work ?).
                 */
                mdelay(1);
-               stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+               stat = hwif->INB(hwif->io_ports.status_addr);
                if ((stat & BUSY_STAT) == 0)
                        return 0;
                /*
index 7031a8dcf6921330ac890af8c23b36294793b08d..6f04ea3e93a896ecf7c84954ab5145f63a9bd117 100644 (file)
@@ -85,7 +85,7 @@ static u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
                        mode = XFER_PIO_4;
        }
 
-//     printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed);
+/*     printk("%s: mode 0x%02x, speed 0x%02x\n", __func__, mode, speed); */
 
        return min(speed, mode);
 }
@@ -274,16 +274,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
                if (overridden)
                        printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n",
                                         drive->name);
-
-               /*
-                * Conservative "downgrade" for all pre-ATA2 drives
-                */
-               if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_DOWNGRADE) == 0 &&
-                   pio_mode && pio_mode < 4) {
-                       pio_mode--;
-                       printk(KERN_INFO "%s: applying conservative "
-                                        "PIO \"downgrade\"\n", drive->name);
-               }
        }
 
        if (pio_mode > max_mode)
@@ -298,9 +288,11 @@ EXPORT_SYMBOL_GPL(ide_get_best_pio_mode);
 void ide_set_pio(ide_drive_t *drive, u8 req_pio)
 {
        ide_hwif_t *hwif = drive->hwif;
+       const struct ide_port_ops *port_ops = hwif->port_ops;
        u8 host_pio, pio;
 
-       if (hwif->set_pio_mode == NULL)
+       if (port_ops == NULL || port_ops->set_pio_mode == NULL ||
+           (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
                return;
 
        BUG_ON(hwif->pio_mask == 0x00);
@@ -352,26 +344,30 @@ void ide_toggle_bounce(ide_drive_t *drive, int on)
 int ide_set_pio_mode(ide_drive_t *drive, const u8 mode)
 {
        ide_hwif_t *hwif = drive->hwif;
+       const struct ide_port_ops *port_ops = hwif->port_ops;
+
+       if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
+               return 0;
 
-       if (hwif->set_pio_mode == NULL)
+       if (port_ops == NULL || port_ops->set_pio_mode == NULL)
                return -1;
 
        /*
         * TODO: temporary hack for some legacy host drivers that didn't
         * set transfer mode on the device in ->set_pio_mode method...
         */
-       if (hwif->set_dma_mode == NULL) {
-               hwif->set_pio_mode(drive, mode - XFER_PIO_0);
+       if (port_ops->set_dma_mode == NULL) {
+               port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
                return 0;
        }
 
        if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
                if (ide_config_drive_speed(drive, mode))
                        return -1;
-               hwif->set_pio_mode(drive, mode - XFER_PIO_0);
+               port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
                return 0;
        } else {
-               hwif->set_pio_mode(drive, mode - XFER_PIO_0);
+               port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
                return ide_config_drive_speed(drive, mode);
        }
 }
@@ -379,17 +375,21 @@ int ide_set_pio_mode(ide_drive_t *drive, const u8 mode)
 int ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
 {
        ide_hwif_t *hwif = drive->hwif;
+       const struct ide_port_ops *port_ops = hwif->port_ops;
+
+       if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
+               return 0;
 
-       if (hwif->set_dma_mode == NULL)
+       if (port_ops == NULL || port_ops->set_dma_mode == NULL)
                return -1;
 
        if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
                if (ide_config_drive_speed(drive, mode))
                        return -1;
-               hwif->set_dma_mode(drive, mode);
+               port_ops->set_dma_mode(drive, mode);
                return 0;
        } else {
-               hwif->set_dma_mode(drive, mode);
+               port_ops->set_dma_mode(drive, mode);
                return ide_config_drive_speed(drive, mode);
        }
 }
@@ -409,8 +409,10 @@ EXPORT_SYMBOL_GPL(ide_set_dma_mode);
 int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
 {
        ide_hwif_t *hwif = drive->hwif;
+       const struct ide_port_ops *port_ops = hwif->port_ops;
 
-       if (hwif->set_dma_mode == NULL)
+       if (port_ops == NULL || port_ops->set_dma_mode == NULL ||
+           (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
                return -1;
 
        rate = ide_rate_filter(drive, rate);
index 34c2ad36ce54641586d85f6188d52cd4521b12af..6a8953f68e9f709945f2f108550dea12907d3670 100644 (file)
  *
  * You should have received a copy of the GNU General Public License
  * (for example /usr/src/linux/COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #include <linux/init.h>
 #include <linux/pnp.h>
 #include <linux/ide.h>
 
+#define DRV_NAME "ide-pnp"
+
 /* Add your devices here :)) */
 static struct pnp_device_id idepnp_devices[] = {
-       /* Generic ESDI/IDE/ATA compatible hard disk controller */
+       /* Generic ESDI/IDE/ATA compatible hard disk controller */
        {.id = "PNP0600", .driver_data = 0},
        {.id = ""}
 };
 
-static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id)
+static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
 {
        hw_regs_t hw;
        ide_hwif_t *hwif;
+       unsigned long base, ctl;
 
        if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && pnp_irq_valid(dev, 0)))
                return -1;
 
+       base = pnp_port_start(dev, 0);
+       ctl = pnp_port_start(dev, 1);
+
+       if (!request_region(base, 8, DRV_NAME)) {
+               printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
+                               DRV_NAME, base, base + 7);
+               return -EBUSY;
+       }
+
+       if (!request_region(ctl, 1, DRV_NAME)) {
+               printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
+                               DRV_NAME, ctl);
+               release_region(base, 8);
+               return -EBUSY;
+       }
+
        memset(&hw, 0, sizeof(hw));
-       ide_std_init_ports(&hw, pnp_port_start(dev, 0),
-                               pnp_port_start(dev, 1));
+       ide_std_init_ports(&hw, base, ctl);
        hw.irq = pnp_irq(dev, 0);
 
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif) {
                u8 index = hwif->index;
                u8 idx[4] = { index, 0xff, 0xff, 0xff };
@@ -47,24 +65,27 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
                ide_init_port_hw(hwif, &hw);
 
                printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index);
-               pnp_set_drvdata(dev,hwif);
+               pnp_set_drvdata(dev, hwif);
 
                ide_device_add(idx, NULL);
 
                return 0;
        }
 
+       release_region(ctl, 1);
+       release_region(base, 8);
+
        return -1;
 }
 
-static void idepnp_remove(struct pnp_dev * dev)
+static void idepnp_remove(struct pnp_dev *dev)
 {
        ide_hwif_t *hwif = pnp_get_drvdata(dev);
 
-       if (hwif)
-               ide_unregister(hwif->index);
-       else
-               printk(KERN_ERR "idepnp: Unable to remove device, please report.\n");
+       ide_unregister(hwif);
+
+       release_region(pnp_port_start(dev, 1), 1);
+       release_region(pnp_port_start(dev, 0), 8);
 }
 
 static struct pnp_driver idepnp_driver = {
index 6a196c27b0aa016ad044a78db16bebdedbfb51e0..862f02603f9b386f2fcf3102fb8be4ff2837c663 100644 (file)
@@ -264,6 +264,7 @@ err_misc:
 static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
 {
        ide_hwif_t *hwif = HWIF(drive);
+       struct ide_io_ports *io_ports = &hwif->io_ports;
        int use_altstatus = 0, rc;
        unsigned long timeout;
        u8 s = 0, a = 0;
@@ -271,7 +272,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
        /* take a deep breath */
        msleep(50);
 
-       if (hwif->io_ports[IDE_CONTROL_OFFSET]) {
+       if (io_ports->ctl_addr) {
                a = ide_read_altstatus(drive);
                s = ide_read_status(drive);
                if ((a ^ s) & ~INDEX_STAT)
@@ -289,10 +290,10 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
         */
        if ((cmd == WIN_PIDENTIFY))
                /* disable dma & overlap */
-               hwif->OUTB(0, hwif->io_ports[IDE_FEATURE_OFFSET]);
+               hwif->OUTB(0, io_ports->feature_addr);
 
        /* ask drive for ID */
-       hwif->OUTB(cmd, hwif->io_ports[IDE_COMMAND_OFFSET]);
+       hwif->OUTB(cmd, io_ports->command_addr);
 
        timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
        timeout += jiffies;
@@ -353,7 +354,7 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
         * interrupts during the identify-phase that
         * the irq handler isn't expecting.
         */
-       if (hwif->io_ports[IDE_CONTROL_OFFSET]) {
+       if (hwif->io_ports.ctl_addr) {
                if (!hwif->irq) {
                        autoprobe = 1;
                        cookie = probe_irq_on();
@@ -393,7 +394,7 @@ static int ide_busy_sleep(ide_hwif_t *hwif)
 
        do {
                msleep(50);
-               stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+               stat = hwif->INB(hwif->io_ports.status_addr);
                if ((stat & BUSY_STAT) == 0)
                        return 0;
        } while (time_before(jiffies, timeout));
@@ -425,6 +426,7 @@ static int ide_busy_sleep(ide_hwif_t *hwif)
 static int do_probe (ide_drive_t *drive, u8 cmd)
 {
        ide_hwif_t *hwif = HWIF(drive);
+       struct ide_io_ports *io_ports = &hwif->io_ports;
        int rc;
        u8 stat;
 
@@ -445,7 +447,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
        msleep(50);
        SELECT_DRIVE(drive);
        msleep(50);
-       if (hwif->INB(hwif->io_ports[IDE_SELECT_OFFSET]) != drive->select.all &&
+       if (hwif->INB(io_ports->device_addr) != drive->select.all &&
            !drive->present) {
                if (drive->select.b.unit != 0) {
                        /* exit with drive0 selected */
@@ -472,17 +474,13 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
                if (stat == (BUSY_STAT | READY_STAT))
                        return 4;
 
-               if ((rc == 1 && cmd == WIN_PIDENTIFY) &&
-                       ((drive->autotune == IDE_TUNE_DEFAULT) ||
-                       (drive->autotune == IDE_TUNE_AUTO))) {
+               if (rc == 1 && cmd == WIN_PIDENTIFY) {
                        printk(KERN_ERR "%s: no response (status = 0x%02x), "
                                        "resetting drive\n", drive->name, stat);
                        msleep(50);
-                       hwif->OUTB(drive->select.all,
-                                  hwif->io_ports[IDE_SELECT_OFFSET]);
+                       hwif->OUTB(drive->select.all, io_ports->device_addr);
                        msleep(50);
-                       hwif->OUTB(WIN_SRST,
-                                  hwif->io_ports[IDE_COMMAND_OFFSET]);
+                       hwif->OUTB(WIN_SRST, io_ports->command_addr);
                        (void)ide_busy_sleep(hwif);
                        rc = try_to_identify(drive, cmd);
                }
@@ -518,7 +516,7 @@ static void enable_nest (ide_drive_t *drive)
        printk("%s: enabling %s -- ", hwif->name, drive->id->model);
        SELECT_DRIVE(drive);
        msleep(50);
-       hwif->OUTB(EXABYTE_ENABLE_NEST, hwif->io_ports[IDE_COMMAND_OFFSET]);
+       hwif->OUTB(EXABYTE_ENABLE_NEST, hwif->io_ports.command_addr);
 
        if (ide_busy_sleep(hwif)) {
                printk(KERN_CONT "failed (timeout)\n");
@@ -644,7 +642,7 @@ static int ide_register_port(ide_hwif_t *hwif)
        ret = device_register(&hwif->gendev);
        if (ret < 0) {
                printk(KERN_WARNING "IDE: %s: device_register error: %d\n",
-                       __FUNCTION__, ret);
+                       __func__, ret);
                goto out;
        }
 
@@ -773,8 +771,7 @@ static int ide_probe_port(ide_hwif_t *hwif)
 
        BUG_ON(hwif->present);
 
-       if (hwif->noprobe ||
-           (hwif->drives[0].noprobe && hwif->drives[1].noprobe))
+       if (hwif->drives[0].noprobe && hwif->drives[1].noprobe)
                return -EACCES;
 
        /*
@@ -801,14 +798,9 @@ static int ide_probe_port(ide_hwif_t *hwif)
                if (drive->present)
                        rc = 0;
        }
-       if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) {
-               printk(KERN_WARNING "%s: reset\n", hwif->name);
-               hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
-               udelay(10);
-               hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
-               (void)ide_busy_sleep(hwif);
-       }
+
        local_irq_restore(flags);
+
        /*
         * Use cached IRQ number. It might be (and is...) changed by probe
         * code above
@@ -821,29 +813,25 @@ static int ide_probe_port(ide_hwif_t *hwif)
 
 static void ide_port_tune_devices(ide_hwif_t *hwif)
 {
+       const struct ide_port_ops *port_ops = hwif->port_ops;
        int unit;
 
        for (unit = 0; unit < MAX_DRIVES; unit++) {
                ide_drive_t *drive = &hwif->drives[unit];
 
-               if (drive->present && hwif->quirkproc)
-                       hwif->quirkproc(drive);
+               if (drive->present && port_ops && port_ops->quirkproc)
+                       port_ops->quirkproc(drive);
        }
 
        for (unit = 0; unit < MAX_DRIVES; ++unit) {
                ide_drive_t *drive = &hwif->drives[unit];
 
                if (drive->present) {
-                       if (drive->autotune == IDE_TUNE_AUTO)
-                               ide_set_max_pio(drive);
-
-                       if (drive->autotune != IDE_TUNE_DEFAULT &&
-                           drive->autotune != IDE_TUNE_AUTO)
-                               continue;
+                       ide_set_max_pio(drive);
 
                        drive->nice1 = 1;
 
-                       if (hwif->dma_host_set)
+                       if (hwif->dma_ops)
                                ide_set_dma(drive);
                }
        }
@@ -994,6 +982,7 @@ static void ide_port_setup_devices(ide_hwif_t *hwif)
  */
 static int init_irq (ide_hwif_t *hwif)
 {
+       struct ide_io_ports *io_ports = &hwif->io_ports;
        unsigned int index;
        ide_hwgroup_t *hwgroup;
        ide_hwif_t *match = NULL;
@@ -1077,9 +1066,9 @@ static int init_irq (ide_hwif_t *hwif)
                if (IDE_CHIPSET_IS_PCI(hwif->chipset))
                        sa = IRQF_SHARED;
 
-               if (hwif->io_ports[IDE_CONTROL_OFFSET])
+               if (io_ports->ctl_addr)
                        /* clear nIEN */
-                       hwif->OUTB(0x08, hwif->io_ports[IDE_CONTROL_OFFSET]);
+                       hwif->OUTB(0x08, io_ports->ctl_addr);
 
                if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup))
                        goto out_unlink;
@@ -1095,12 +1084,11 @@ static int init_irq (ide_hwif_t *hwif)
 
 #if !defined(__mc68000__)
        printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
-               hwif->io_ports[IDE_DATA_OFFSET],
-               hwif->io_ports[IDE_DATA_OFFSET]+7,
-               hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq);
+               io_ports->data_addr, io_ports->status_addr,
+               io_ports->ctl_addr, hwif->irq);
 #else
        printk("%s at 0x%08lx on irq %d", hwif->name,
-               hwif->io_ports[IDE_DATA_OFFSET], hwif->irq);
+               io_ports->data_addr, hwif->irq);
 #endif /* __mc68000__ */
        if (match)
                printk(" (%sed with %s)",
@@ -1242,8 +1230,8 @@ static int hwif_init(ide_hwif_t *hwif)
        int old_irq;
 
        if (!hwif->irq) {
-               if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET])))
-               {
+               hwif->irq = ide_default_irq(hwif->io_ports.data_addr);
+               if (!hwif->irq) {
                        printk("%s: DISABLED, NO IRQ\n", hwif->name);
                        return 0;
                }
@@ -1272,7 +1260,8 @@ static int hwif_init(ide_hwif_t *hwif)
         *      It failed to initialise. Find the default IRQ for 
         *      this port and try that.
         */
-       if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) {
+       hwif->irq = ide_default_irq(hwif->io_ports.data_addr);
+       if (!hwif->irq) {
                printk("%s: Disabled unable to get IRQ %d.\n",
                        hwif->name, old_irq);
                goto out;
@@ -1324,6 +1313,7 @@ static void hwif_register_devices(ide_hwif_t *hwif)
 
 static void ide_port_init_devices(ide_hwif_t *hwif)
 {
+       const struct ide_port_ops *port_ops = hwif->port_ops;
        int i;
 
        for (i = 0; i < MAX_DRIVES; i++) {
@@ -1335,12 +1325,10 @@ static void ide_port_init_devices(ide_hwif_t *hwif)
                        drive->unmask = 1;
                if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS)
                        drive->no_unmask = 1;
-               if ((hwif->host_flags & IDE_HFLAG_NO_AUTOTUNE) == 0)
-                       drive->autotune = 1;
        }
 
-       if (hwif->port_init_devs)
-               hwif->port_init_devs(hwif);
+       if (port_ops && port_ops->port_init_devs)
+               port_ops->port_init_devs(hwif);
 }
 
 static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
@@ -1355,9 +1343,6 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
        if (d->init_iops)
                d->init_iops(hwif);
 
-       if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0)
-               ide_hwif_setup_dma(hwif, d);
-
        if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) ||
            (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS))
                hwif->irq = port ? 15 : 14;
@@ -1365,16 +1350,36 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
        hwif->host_flags = d->host_flags;
        hwif->pio_mask = d->pio_mask;
 
-       if ((d->host_flags & IDE_HFLAG_SERIALIZE) && hwif->mate)
-               hwif->mate->serialized = hwif->serialized = 1;
+       /* ->set_pio_mode for DTC2278 is currently limited to port 0 */
+       if (hwif->chipset != ide_dtc2278 || hwif->channel == 0)
+               hwif->port_ops = d->port_ops;
+
+       if ((d->host_flags & IDE_HFLAG_SERIALIZE) ||
+           ((d->host_flags & IDE_HFLAG_SERIALIZE_DMA) && hwif->dma_base)) {
+               if (hwif->mate)
+                       hwif->mate->serialized = hwif->serialized = 1;
+       }
 
        hwif->swdma_mask = d->swdma_mask;
        hwif->mwdma_mask = d->mwdma_mask;
        hwif->ultra_mask = d->udma_mask;
 
-       /* reset DMA masks only for SFF-style DMA controllers */
-       if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0 && hwif->dma_base == 0)
-               hwif->swdma_mask = hwif->mwdma_mask = hwif->ultra_mask = 0;
+       if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) {
+               int rc;
+
+               if (d->init_dma)
+                       rc = d->init_dma(hwif, d);
+               else
+                       rc = ide_hwif_setup_dma(hwif, d);
+
+               if (rc < 0) {
+                       printk(KERN_INFO "%s: DMA disabled\n", hwif->name);
+                       hwif->swdma_mask = 0;
+                       hwif->mwdma_mask = 0;
+                       hwif->ultra_mask = 0;
+               } else if (d->dma_ops)
+                       hwif->dma_ops = d->dma_ops;
+       }
 
        if (d->host_flags & IDE_HFLAG_RQSIZE_256)
                hwif->rqsize = 256;
@@ -1386,9 +1391,11 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
 
 static void ide_port_cable_detect(ide_hwif_t *hwif)
 {
-       if (hwif->cable_detect && (hwif->ultra_mask & 0x78)) {
+       const struct ide_port_ops *port_ops = hwif->port_ops;
+
+       if (port_ops && port_ops->cable_detect && (hwif->ultra_mask & 0x78)) {
                if (hwif->cbl != ATA_CBL_PATA40_SHORT)
-                       hwif->cbl = hwif->cable_detect(hwif);
+                       hwif->cbl = port_ops->cable_detect(hwif);
        }
 }
 
@@ -1444,19 +1451,74 @@ static int ide_sysfs_register_port(ide_hwif_t *hwif)
        return rc;
 }
 
+/**
+ *     ide_find_port_slot      -       find free ide_hwifs[] slot
+ *     @d: IDE port info
+ *
+ *     Return the new hwif.  If we are out of free slots return NULL.
+ */
+
+ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d)
+{
+       ide_hwif_t *hwif;
+       int i;
+       u8 bootable = (d && (d->host_flags & IDE_HFLAG_NON_BOOTABLE)) ? 0 : 1;
+
+       /*
+        * Claim an unassigned slot.
+        *
+        * Give preference to claiming other slots before claiming ide0/ide1,
+        * just in case there's another interface yet-to-be-scanned
+        * which uses ports 0x1f0/0x170 (the ide0/ide1 defaults).
+        *
+        * Unless there is a bootable card that does not use the standard
+        * ports 0x1f0/0x170 (the ide0/ide1 defaults).
+        */
+       if (bootable) {
+               i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;
+
+               for (; i < MAX_HWIFS; i++) {
+                       hwif = &ide_hwifs[i];
+                       if (hwif->chipset == ide_unknown)
+                               return hwif;
+               }
+       } else {
+               for (i = 2; i < MAX_HWIFS; i++) {
+                       hwif = &ide_hwifs[i];
+                       if (hwif->chipset == ide_unknown)
+                               return hwif;
+               }
+               for (i = 0; i < 2 && i < MAX_HWIFS; i++) {
+                       hwif = &ide_hwifs[i];
+                       if (hwif->chipset == ide_unknown)
+                               return hwif;
+               }
+       }
+
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(ide_find_port_slot);
+
 int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
 {
        ide_hwif_t *hwif, *mate = NULL;
        int i, rc = 0;
 
        for (i = 0; i < MAX_HWIFS; i++) {
-               if (d == NULL || idx[i] == 0xff) {
+               if (idx[i] == 0xff) {
                        mate = NULL;
                        continue;
                }
 
                hwif = &ide_hwifs[idx[i]];
 
+               ide_port_apply_params(hwif);
+
+               if (d == NULL) {
+                       mate = NULL;
+                       continue;
+               }
+
                if (d->chipset != ide_etrax100 && (i & 1) && mate) {
                        hwif->mate = mate;
                        mate->mate = hwif;
@@ -1475,25 +1537,15 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
 
                hwif = &ide_hwifs[idx[i]];
 
-               if ((hwif->chipset != ide_4drives || !hwif->mate ||
-                    !hwif->mate->present) && ide_hwif_request_regions(hwif)) {
-                       printk(KERN_ERR "%s: ports already in use, "
-                                       "skipping probe\n", hwif->name);
-                       continue;
-               }
-
-               if (ide_probe_port(hwif) < 0) {
-                       ide_hwif_release_regions(hwif);
-                       continue;
-               }
-
-               hwif->present = 1;
+               if (ide_probe_port(hwif) == 0)
+                       hwif->present = 1;
 
                if (hwif->chipset != ide_4drives || !hwif->mate ||
                    !hwif->mate->present)
                        ide_register_port(hwif);
 
-               ide_port_tune_devices(hwif);
+               if (hwif->present)
+                       ide_port_tune_devices(hwif);
        }
 
        for (i = 0; i < MAX_HWIFS; i++) {
@@ -1502,9 +1554,6 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
 
                hwif = &ide_hwifs[idx[i]];
 
-               if (!hwif->present)
-                       continue;
-
                if (hwif_init(hwif) == 0) {
                        printk(KERN_INFO "%s: failed to initialize IDE "
                                         "interface\n", hwif->name);
@@ -1513,10 +1562,13 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
                        continue;
                }
 
-               ide_port_setup_devices(hwif);
+               if (hwif->present)
+                       ide_port_setup_devices(hwif);
 
                ide_acpi_init(hwif);
-               ide_acpi_port_init_devices(hwif);
+
+               if (hwif->present)
+                       ide_acpi_port_init_devices(hwif);
        }
 
        for (i = 0; i < MAX_HWIFS; i++) {
@@ -1525,11 +1577,11 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
 
                hwif = &ide_hwifs[idx[i]];
 
-               if (hwif->present) {
-                       if (hwif->chipset == ide_unknown)
-                               hwif->chipset = ide_generic;
+               if (hwif->chipset == ide_unknown)
+                       hwif->chipset = ide_generic;
+
+               if (hwif->present)
                        hwif_register_devices(hwif);
-               }
        }
 
        for (i = 0; i < MAX_HWIFS; i++) {
@@ -1538,11 +1590,11 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
 
                hwif = &ide_hwifs[idx[i]];
 
-               if (hwif->present) {
-                       ide_sysfs_register_port(hwif);
-                       ide_proc_register_port(hwif);
+               ide_sysfs_register_port(hwif);
+               ide_proc_register_port(hwif);
+
+               if (hwif->present)
                        ide_proc_port_register_devices(hwif);
-               }
        }
 
        return rc;
@@ -1563,6 +1615,7 @@ EXPORT_SYMBOL_GPL(ide_device_add);
 
 void ide_port_scan(ide_hwif_t *hwif)
 {
+       ide_port_apply_params(hwif);
        ide_port_cable_detect(hwif);
        ide_port_init_devices(hwif);
 
@@ -1578,3 +1631,67 @@ void ide_port_scan(ide_hwif_t *hwif)
        ide_proc_port_register_devices(hwif);
 }
 EXPORT_SYMBOL_GPL(ide_port_scan);
+
+static void ide_legacy_init_one(u8 *idx, hw_regs_t *hw, u8 port_no,
+                               const struct ide_port_info *d,
+                               unsigned long config)
+{
+       ide_hwif_t *hwif;
+       unsigned long base, ctl;
+       int irq;
+
+       if (port_no == 0) {
+               base = 0x1f0;
+               ctl  = 0x3f6;
+               irq  = 14;
+       } else {
+               base = 0x170;
+               ctl  = 0x376;
+               irq  = 15;
+       }
+
+       if (!request_region(base, 8, d->name)) {
+               printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
+                               d->name, base, base + 7);
+               return;
+       }
+
+       if (!request_region(ctl, 1, d->name)) {
+               printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
+                               d->name, ctl);
+               release_region(base, 8);
+               return;
+       }
+
+       ide_std_init_ports(hw, base, ctl);
+       hw->irq = irq;
+
+       hwif = ide_find_port_slot(d);
+       if (hwif) {
+               ide_init_port_hw(hwif, hw);
+               if (config)
+                       hwif->config_data = config;
+               idx[port_no] = hwif->index;
+       }
+}
+
+int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config)
+{
+       u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+       hw_regs_t hw[2];
+
+       memset(&hw, 0, sizeof(hw));
+
+       if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0)
+               ide_legacy_init_one(idx, &hw[0], 0, d, config);
+       ide_legacy_init_one(idx, &hw[1], 1, d, config);
+
+       if (idx[0] == 0xff && idx[1] == 0xff &&
+           (d->host_flags & IDE_HFLAG_SINGLE))
+               return -ENOENT;
+
+       ide_device_add(idx, d);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ide_legacy_device_add);
index edd7f186dc4d220afdb362151f4ebc31a3543754..7b2f3815a838700bfdce5d88ea62f0d6199037d7 100644 (file)
@@ -47,28 +47,28 @@ static int proc_ide_read_imodel
        const char      *name;
 
        switch (hwif->chipset) {
-               case ide_generic:       name = "generic";       break;
-               case ide_pci:           name = "pci";           break;
-               case ide_cmd640:        name = "cmd640";        break;
-               case ide_dtc2278:       name = "dtc2278";       break;
-               case ide_ali14xx:       name = "ali14xx";       break;
-               case ide_qd65xx:        name = "qd65xx";        break;
-               case ide_umc8672:       name = "umc8672";       break;
-               case ide_ht6560b:       name = "ht6560b";       break;
-               case ide_rz1000:        name = "rz1000";        break;
-               case ide_trm290:        name = "trm290";        break;
-               case ide_cmd646:        name = "cmd646";        break;
-               case ide_cy82c693:      name = "cy82c693";      break;
-               case ide_4drives:       name = "4drives";       break;
-               case ide_pmac:          name = "mac-io";        break;
-               case ide_au1xxx:        name = "au1xxx";        break;
-               case ide_palm3710:      name = "palm3710";      break;
-               case ide_etrax100:      name = "etrax100";      break;
-               case ide_acorn:         name = "acorn";         break;
-               default:                name = "(unknown)";     break;
+       case ide_generic:       name = "generic";       break;
+       case ide_pci:           name = "pci";           break;
+       case ide_cmd640:        name = "cmd640";        break;
+       case ide_dtc2278:       name = "dtc2278";       break;
+       case ide_ali14xx:       name = "ali14xx";       break;
+       case ide_qd65xx:        name = "qd65xx";        break;
+       case ide_umc8672:       name = "umc8672";       break;
+       case ide_ht6560b:       name = "ht6560b";       break;
+       case ide_rz1000:        name = "rz1000";        break;
+       case ide_trm290:        name = "trm290";        break;
+       case ide_cmd646:        name = "cmd646";        break;
+       case ide_cy82c693:      name = "cy82c693";      break;
+       case ide_4drives:       name = "4drives";       break;
+       case ide_pmac:          name = "mac-io";        break;
+       case ide_au1xxx:        name = "au1xxx";        break;
+       case ide_palm3710:      name = "palm3710";      break;
+       case ide_etrax100:      name = "etrax100";      break;
+       case ide_acorn:         name = "acorn";         break;
+       default:                name = "(unknown)";     break;
        }
        len = sprintf(page, "%s\n", name);
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 static int proc_ide_read_mate
@@ -81,7 +81,7 @@ static int proc_ide_read_mate
                len = sprintf(page, "%s\n", hwif->mate->name);
        else
                len = sprintf(page, "(none)\n");
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 static int proc_ide_read_channel
@@ -93,7 +93,7 @@ static int proc_ide_read_channel
        page[0] = hwif->channel ? '1' : '0';
        page[1] = '\n';
        len = 2;
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 static int proc_ide_read_identify
@@ -120,7 +120,7 @@ static int proc_ide_read_identify
                        len = out - page;
                }
        }
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 /**
@@ -197,7 +197,7 @@ EXPORT_SYMBOL(ide_add_setting);
  *     The caller must hold the setting semaphore.
  */
 
-static void __ide_remove_setting (ide_drive_t *drive, char *name)
+static void __ide_remove_setting(ide_drive_t *drive, char *name)
 {
        ide_settings_t **p, *setting;
 
@@ -205,7 +205,8 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name)
 
        while ((*p) && strcmp((*p)->name, name))
                p = &((*p)->next);
-       if ((setting = (*p)) == NULL)
+       setting = (*p);
+       if (setting == NULL)
                return;
 
        (*p) = setting->next;
@@ -223,7 +224,7 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name)
  *     caller must hold ide_setting_mtx.
  */
 
-static void auto_remove_settings (ide_drive_t *drive)
+static void auto_remove_settings(ide_drive_t *drive)
 {
        ide_settings_t *setting;
 repeat:
@@ -279,16 +280,16 @@ static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
 
        if ((setting->rw & SETTING_READ)) {
                spin_lock_irqsave(&ide_lock, flags);
-               switch(setting->data_type) {
-                       case TYPE_BYTE:
-                               val = *((u8 *) setting->data);
-                               break;
-                       case TYPE_SHORT:
-                               val = *((u16 *) setting->data);
-                               break;
-                       case TYPE_INT:
-                               val = *((u32 *) setting->data);
-                               break;
+               switch (setting->data_type) {
+               case TYPE_BYTE:
+                       val = *((u8 *) setting->data);
+                       break;
+               case TYPE_SHORT:
+                       val = *((u16 *) setting->data);
+                       break;
+               case TYPE_INT:
+                       val = *((u32 *) setting->data);
+                       break;
                }
                spin_unlock_irqrestore(&ide_lock, flags);
        }
@@ -326,15 +327,15 @@ static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int va
        if (ide_spin_wait_hwgroup(drive))
                return -EBUSY;
        switch (setting->data_type) {
-               case TYPE_BYTE:
-                       *((u8 *) setting->data) = val;
-                       break;
-               case TYPE_SHORT:
-                       *((u16 *) setting->data) = val;
-                       break;
-               case TYPE_INT:
-                       *((u32 *) setting->data) = val;
-                       break;
+       case TYPE_BYTE:
+               *((u8 *) setting->data) = val;
+               break;
+       case TYPE_SHORT:
+               *((u16 *) setting->data) = val;
+               break;
+       case TYPE_INT:
+               *((u32 *) setting->data) = val;
+               break;
        }
        spin_unlock_irq(&ide_lock);
        return 0;
@@ -390,7 +391,7 @@ void ide_add_generic_settings (ide_drive_t *drive)
 
 static void proc_ide_settings_warn(void)
 {
-       static int warned = 0;
+       static int warned;
 
        if (warned)
                return;
@@ -413,11 +414,12 @@ static int proc_ide_read_settings
        mutex_lock(&ide_setting_mtx);
        out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
        out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
-       while(setting) {
+       while (setting) {
                mul_factor = setting->mul_factor;
                div_factor = setting->div_factor;
                out += sprintf(out, "%-24s", setting->name);
-               if ((rc = ide_read_setting(drive, setting)) >= 0)
+               rc = ide_read_setting(drive, setting);
+               if (rc >= 0)
                        out += sprintf(out, "%-16d", rc * mul_factor / div_factor);
                else
                        out += sprintf(out, "%-16s", "write-only");
@@ -431,7 +433,7 @@ static int proc_ide_read_settings
        }
        len = out - page;
        mutex_unlock(&ide_setting_mtx);
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 #define MAX_LEN        30
@@ -512,8 +514,7 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
 
                        mutex_lock(&ide_setting_mtx);
                        setting = ide_find_setting_by_name(drive, name);
-                       if (!setting)
-                       {
+                       if (!setting) {
                                mutex_unlock(&ide_setting_mtx);
                                goto parse_error;
                        }
@@ -533,8 +534,8 @@ parse_error:
 int proc_ide_read_capacity
        (char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-       int len = sprintf(page,"%llu\n", (long long)0x7fffffff);
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       int len = sprintf(page, "%llu\n", (long long)0x7fffffff);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 EXPORT_SYMBOL_GPL(proc_ide_read_capacity);
@@ -546,13 +547,13 @@ int proc_ide_read_geometry
        char            *out = page;
        int             len;
 
-       out += sprintf(out,"physical     %d/%d/%d\n",
+       out += sprintf(out, "physical     %d/%d/%d\n",
                        drive->cyl, drive->head, drive->sect);
-       out += sprintf(out,"logical      %d/%d/%d\n",
+       out += sprintf(out, "logical      %d/%d/%d\n",
                        drive->bios_cyl, drive->bios_head, drive->bios_sect);
 
        len = out - page;
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 EXPORT_SYMBOL(proc_ide_read_geometry);
@@ -566,7 +567,7 @@ static int proc_ide_read_dmodel
 
        len = sprintf(page, "%.40s\n",
                (id && id->model[0]) ? (char *)id->model : "(none)");
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 static int proc_ide_read_driver
@@ -583,7 +584,7 @@ static int proc_ide_read_driver
                                dev->driver->name, ide_drv->version);
        } else
                len = sprintf(page, "ide-default version 0.9.newide\n");
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
@@ -598,14 +599,14 @@ static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
        err = device_attach(dev);
        if (err < 0)
                printk(KERN_WARNING "IDE: %s: device_attach error: %d\n",
-                       __FUNCTION__, err);
+                       __func__, err);
        drive->driver_req[0] = 0;
        if (dev->driver == NULL) {
                err = device_attach(dev);
                if (err < 0)
                        printk(KERN_WARNING
                                "IDE: %s: device_attach(2) error: %d\n",
-                               __FUNCTION__, err);
+                               __func__, err);
        }
        if (dev->driver && !strcmp(dev->driver->name, driver))
                ret = 0;
@@ -639,30 +640,26 @@ static int proc_ide_read_media
        int             len;
 
        switch (drive->media) {
-               case ide_disk:  media = "disk\n";
-                               break;
-               case ide_cdrom: media = "cdrom\n";
-                               break;
-               case ide_tape:  media = "tape\n";
-                               break;
-               case ide_floppy:media = "floppy\n";
-                               break;
-               case ide_optical:media = "optical\n";
-                               break;
-               default:        media = "UNKNOWN\n";
-                               break;
+       case ide_disk:          media = "disk\n";       break;
+       case ide_cdrom:         media = "cdrom\n";      break;
+       case ide_tape:          media = "tape\n";       break;
+       case ide_floppy:        media = "floppy\n";     break;
+       case ide_optical:       media = "optical\n";    break;
+       default:                media = "UNKNOWN\n";    break;
        }
-       strcpy(page,media);
+       strcpy(page, media);
        len = strlen(media);
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 static ide_proc_entry_t generic_drive_entries[] = {
-       { "driver",     S_IFREG|S_IRUGO,        proc_ide_read_driver,   proc_ide_write_driver },
-       { "identify",   S_IFREG|S_IRUSR,        proc_ide_read_identify, NULL },
-       { "media",      S_IFREG|S_IRUGO,        proc_ide_read_media,    NULL },
-       { "model",      S_IFREG|S_IRUGO,        proc_ide_read_dmodel,   NULL },
-       { "settings",   S_IFREG|S_IRUSR|S_IWUSR,proc_ide_read_settings, proc_ide_write_settings },
+       { "driver",     S_IFREG|S_IRUGO,         proc_ide_read_driver,
+                                                proc_ide_write_driver },
+       { "identify",   S_IFREG|S_IRUSR,         proc_ide_read_identify, NULL },
+       { "media",      S_IFREG|S_IRUGO,         proc_ide_read_media,    NULL },
+       { "model",      S_IFREG|S_IRUGO,         proc_ide_read_dmodel,   NULL },
+       { "settings",   S_IFREG|S_IRUSR|S_IWUSR, proc_ide_read_settings,
+                                                proc_ide_write_settings },
        { NULL, 0, NULL, NULL }
 };
 
@@ -734,7 +731,6 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
        spin_unlock_irqrestore(&ide_lock, flags);
        mutex_unlock(&ide_setting_mtx);
 }
-
 EXPORT_SYMBOL(ide_proc_unregister_driver);
 
 void ide_proc_port_register_devices(ide_hwif_t *hwif)
@@ -755,7 +751,7 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif)
                drive->proc = proc_mkdir(drive->name, parent);
                if (drive->proc)
                        ide_add_proc_entries(drive->proc, generic_drive_entries, drive);
-               sprintf(name,"ide%d/%s", (drive->name[2]-'a')/2, drive->name);
+               sprintf(name, "ide%d/%s", (drive->name[2]-'a')/2, drive->name);
                ent = proc_symlink(drive->name, proc_ide_root, name);
                if (!ent) return;
        }
@@ -790,15 +786,6 @@ void ide_proc_register_port(ide_hwif_t *hwif)
        }
 }
 
-#ifdef CONFIG_BLK_DEV_IDEPCI
-void ide_pci_create_host_proc(const char *name, get_info_t *get_info)
-{
-       create_proc_info_entry(name, 0, proc_ide_root, get_info);
-}
-
-EXPORT_SYMBOL_GPL(ide_pci_create_host_proc);
-#endif
-
 void ide_proc_unregister_port(ide_hwif_t *hwif)
 {
        if (hwif->proc) {
@@ -825,7 +812,7 @@ static int ide_drivers_show(struct seq_file *s, void *p)
        err = bus_for_each_drv(&ide_bus_type, NULL, s, proc_print_driver);
        if (err < 0)
                printk(KERN_WARNING "IDE: %s: bus_for_each_drv error: %d\n",
-                       __FUNCTION__, err);
+                       __func__, err);
        return 0;
 }
 
index 98888da1b600d3a4965e2dbc2d041332e5c5cbbc..0e79efff1debdd5c357c658b77b0ec1a60e735e2 100644 (file)
@@ -102,7 +102,7 @@ static int __init ide_scan_pcibus(void)
                if (__pci_register_driver(d, d->driver.owner,
                                          d->driver.mod_name))
                        printk(KERN_ERR "%s: failed to register %s driver\n",
-                                       __FUNCTION__, d->driver.mod_name);
+                                       __func__, d->driver.mod_name);
        }
 
        return 0;
index f43fd070f1b6d0c7221f8ab86a1ff89c913ac4cf..29870c415110ad0bc3cf2d4bf76791ebfe0d5763 100644 (file)
@@ -72,26 +72,6 @@ enum {
 #endif
 
 /**************************** Tunable parameters *****************************/
-
-
-/*
- * Pipelined mode parameters.
- *
- * We try to use the minimum number of stages which is enough to keep the tape
- * constantly streaming. To accomplish that, we implement a feedback loop around
- * the maximum number of stages:
- *
- * We start from MIN maximum stages (we will not even use MIN stages if we don't
- * need them), increment it by RATE*(MAX-MIN) whenever we sense that the
- * pipeline is empty, until we reach the optimum value or until we reach MAX.
- *
- * Setting the following parameter to 0 is illegal: the pipelined mode cannot be
- * disabled (idetape_calculate_speeds() divides by tape->max_stages.)
- */
-#define IDETAPE_MIN_PIPELINE_STAGES      1
-#define IDETAPE_MAX_PIPELINE_STAGES    400
-#define IDETAPE_INCREASE_STAGES_RATE    20
-
 /*
  * After each failed packet command we issue a request sense command and retry
  * the packet command IDETAPE_MAX_PC_RETRIES times.
@@ -224,28 +204,17 @@ enum {
        /* 0 When the tape position is unknown */
        IDETAPE_FLAG_ADDRESS_VALID      = (1 << 1),
        /* Device already opened */
-       IDETAPE_FLAG_BUSY                       = (1 << 2),
-       /* Error detected in a pipeline stage */
-       IDETAPE_FLAG_PIPELINE_ERR       = (1 << 3),
+       IDETAPE_FLAG_BUSY               = (1 << 2),
        /* Attempt to auto-detect the current user block size */
-       IDETAPE_FLAG_DETECT_BS          = (1 << 4),
+       IDETAPE_FLAG_DETECT_BS          = (1 << 3),
        /* Currently on a filemark */
-       IDETAPE_FLAG_FILEMARK           = (1 << 5),
+       IDETAPE_FLAG_FILEMARK           = (1 << 4),
        /* DRQ interrupt device */
-       IDETAPE_FLAG_DRQ_INTERRUPT      = (1 << 6),
-       /* pipeline active */
-       IDETAPE_FLAG_PIPELINE_ACTIVE    = (1 << 7),
+       IDETAPE_FLAG_DRQ_INTERRUPT      = (1 << 5),
        /* 0 = no tape is loaded, so we don't rewind after ejecting */
-       IDETAPE_FLAG_MEDIUM_PRESENT     = (1 << 8),
+       IDETAPE_FLAG_MEDIUM_PRESENT     = (1 << 6),
 };
 
-/* A pipeline stage. */
-typedef struct idetape_stage_s {
-       struct request rq;                      /* The corresponding request */
-       struct idetape_bh *bh;                  /* The data buffers */
-       struct idetape_stage_s *next;           /* Pointer to the next stage */
-} idetape_stage_t;
-
 /*
  * Most of our global data which we need to save even as we leave the driver due
  * to an interrupt or a timer event is stored in the struct defined below.
@@ -289,9 +258,7 @@ typedef struct ide_tape_obj {
         * While polling for DSC we use postponed_rq to postpone the current
         * request so that ide.c will be able to service pending requests on the
         * other device. Note that at most we will have only one DSC (usually
-        * data transfer) request in the device request queue. Additional
-        * requests can be queued in our internal pipeline, but they will be
-        * visible to ide.c only one at a time.
+        * data transfer) request in the device request queue.
         */
        struct request *postponed_rq;
        /* The time in which we started polling for DSC */
@@ -331,43 +298,20 @@ typedef struct ide_tape_obj {
         * At most, there is only one ide-tape originated data transfer request
         * in the device request queue. This allows ide.c to easily service
         * requests from the other device when we postpone our active request.
-        * In the pipelined operation mode, we use our internal pipeline
-        * structure to hold more data requests. The data buffer size is chosen
-        * based on the tape's recommendation.
         */
-       /* ptr to the request which is waiting in the device request queue */
-       struct request *active_data_rq;
+
        /* Data buffer size chosen based on the tape's recommendation */
-       int stage_size;
-       idetape_stage_t *merge_stage;
-       int merge_stage_size;
+       int buffer_size;
+       /* merge buffer */
+       struct idetape_bh *merge_bh;
+       /* size of the merge buffer */
+       int merge_bh_size;
+       /* pointer to current buffer head within the merge buffer */
        struct idetape_bh *bh;
        char *b_data;
        int b_count;
 
-       /*
-        * Pipeline parameters.
-        *
-        * To accomplish non-pipelined mode, we simply set the following
-        * variables to zero (or NULL, where appropriate).
-        */
-       /* Number of currently used stages */
-       int nr_stages;
-       /* Number of pending stages */
-       int nr_pending_stages;
-       /* We will not allocate more than this number of stages */
-       int max_stages, min_pipeline, max_pipeline;
-       /* The first stage which will be removed from the pipeline */
-       idetape_stage_t *first_stage;
-       /* The currently active stage */
-       idetape_stage_t *active_stage;
-       /* Will be serviced after the currently active request */
-       idetape_stage_t *next_stage;
-       /* New requests will be added to the pipeline here */
-       idetape_stage_t *last_stage;
-       /* Optional free stage which we can use */
-       idetape_stage_t *cache_stage;
-       int pages_per_stage;
+       int pages_per_buffer;
        /* Wasted space in each stage */
        int excess_bh_size;
 
@@ -388,45 +332,6 @@ typedef struct ide_tape_obj {
        /* the tape is write protected (hardware or opened as read-only) */
        char write_prot;
 
-       /*
-        * Limit the number of times a request can be postponed, to avoid an
-        * infinite postpone deadlock.
-        */
-       int postpone_cnt;
-
-       /*
-        * Measures number of frames:
-        *
-        * 1. written/read to/from the driver pipeline (pipeline_head).
-        * 2. written/read to/from the tape buffers (idetape_bh).
-        * 3. written/read by the tape to/from the media (tape_head).
-        */
-       int pipeline_head;
-       int buffer_head;
-       int tape_head;
-       int last_tape_head;
-
-       /* Speed control at the tape buffers input/output */
-       unsigned long insert_time;
-       int insert_size;
-       int insert_speed;
-       int max_insert_speed;
-       int measure_insert_time;
-
-       /* Speed regulation negative feedback loop */
-       int speed_control;
-       int pipeline_head_speed;
-       int controlled_pipeline_head_speed;
-       int uncontrolled_pipeline_head_speed;
-       int controlled_last_pipeline_head;
-       unsigned long uncontrolled_pipeline_head_time;
-       unsigned long controlled_pipeline_head_time;
-       int controlled_previous_pipeline_head;
-       int uncontrolled_previous_pipeline_head;
-       unsigned long controlled_previous_head_time;
-       unsigned long uncontrolled_previous_head_time;
-       int restart_speed_control_req;
-
        u32 debug_mask;
 } idetape_tape_t;
 
@@ -674,128 +579,36 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
        }
 }
 
-static void idetape_activate_next_stage(ide_drive_t *drive)
+/* Free data buffers completely. */
+static void ide_tape_kfree_buffer(idetape_tape_t *tape)
 {
-       idetape_tape_t *tape = drive->driver_data;
-       idetape_stage_t *stage = tape->next_stage;
-       struct request *rq = &stage->rq;
+       struct idetape_bh *prev_bh, *bh = tape->merge_bh;
 
-       debug_log(DBG_PROCS, "Enter %s\n", __func__);
+       while (bh) {
+               u32 size = bh->b_size;
 
-       if (stage == NULL) {
-               printk(KERN_ERR "ide-tape: bug: Trying to activate a non"
-                               " existing stage\n");
-               return;
-       }
+               while (size) {
+                       unsigned int order = fls(size >> PAGE_SHIFT)-1;
 
-       rq->rq_disk = tape->disk;
-       rq->buffer = NULL;
-       rq->special = (void *)stage->bh;
-       tape->active_data_rq = rq;
-       tape->active_stage = stage;
-       tape->next_stage = stage->next;
-}
-
-/* Free a stage along with its related buffers completely. */
-static void __idetape_kfree_stage(idetape_stage_t *stage)
-{
-       struct idetape_bh *prev_bh, *bh = stage->bh;
-       int size;
-
-       while (bh != NULL) {
-               if (bh->b_data != NULL) {
-                       size = (int) bh->b_size;
-                       while (size > 0) {
-                               free_page((unsigned long) bh->b_data);
-                               size -= PAGE_SIZE;
-                               bh->b_data += PAGE_SIZE;
-                       }
+                       if (bh->b_data)
+                               free_pages((unsigned long)bh->b_data, order);
+
+                       size &= (order-1);
+                       bh->b_data += (1 << order) * PAGE_SIZE;
                }
                prev_bh = bh;
                bh = bh->b_reqnext;
                kfree(prev_bh);
        }
-       kfree(stage);
-}
-
-static void idetape_kfree_stage(idetape_tape_t *tape, idetape_stage_t *stage)
-{
-       __idetape_kfree_stage(stage);
+       kfree(tape->merge_bh);
 }
 
-/*
- * Remove tape->first_stage from the pipeline. The caller should avoid race
- * conditions.
- */
-static void idetape_remove_stage_head(ide_drive_t *drive)
-{
-       idetape_tape_t *tape = drive->driver_data;
-       idetape_stage_t *stage;
-
-       debug_log(DBG_PROCS, "Enter %s\n", __func__);
-
-       if (tape->first_stage == NULL) {
-               printk(KERN_ERR "ide-tape: bug: tape->first_stage is NULL\n");
-               return;
-       }
-       if (tape->active_stage == tape->first_stage) {
-               printk(KERN_ERR "ide-tape: bug: Trying to free our active "
-                               "pipeline stage\n");
-               return;
-       }
-       stage = tape->first_stage;
-       tape->first_stage = stage->next;
-       idetape_kfree_stage(tape, stage);
-       tape->nr_stages--;
-       if (tape->first_stage == NULL) {
-               tape->last_stage = NULL;
-               if (tape->next_stage != NULL)
-                       printk(KERN_ERR "ide-tape: bug: tape->next_stage !="
-                                       " NULL\n");
-               if (tape->nr_stages)
-                       printk(KERN_ERR "ide-tape: bug: nr_stages should be 0 "
-                                       "now\n");
-       }
-}
-
-/*
- * This will free all the pipeline stages starting from new_last_stage->next
- * to the end of the list, and point tape->last_stage to new_last_stage.
- */
-static void idetape_abort_pipeline(ide_drive_t *drive,
-                                  idetape_stage_t *new_last_stage)
-{
-       idetape_tape_t *tape = drive->driver_data;
-       idetape_stage_t *stage = new_last_stage->next;
-       idetape_stage_t *nstage;
-
-       debug_log(DBG_PROCS, "%s: Enter %s\n", tape->name, __func__);
-
-       while (stage) {
-               nstage = stage->next;
-               idetape_kfree_stage(tape, stage);
-               --tape->nr_stages;
-               --tape->nr_pending_stages;
-               stage = nstage;
-       }
-       if (new_last_stage)
-               new_last_stage->next = NULL;
-       tape->last_stage = new_last_stage;
-       tape->next_stage = NULL;
-}
-
-/*
- * Finish servicing a request and insert a pending pipeline request into the
- * main device queue.
- */
 static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
 {
        struct request *rq = HWGROUP(drive)->rq;
        idetape_tape_t *tape = drive->driver_data;
        unsigned long flags;
        int error;
-       int remove_stage = 0;
-       idetape_stage_t *active_stage;
 
        debug_log(DBG_PROCS, "Enter %s\n", __func__);
 
@@ -815,58 +628,8 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
 
        spin_lock_irqsave(&tape->lock, flags);
 
-       /* The request was a pipelined data transfer request */
-       if (tape->active_data_rq == rq) {
-               active_stage = tape->active_stage;
-               tape->active_stage = NULL;
-               tape->active_data_rq = NULL;
-               tape->nr_pending_stages--;
-               if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
-                       remove_stage = 1;
-                       if (error) {
-                               set_bit(IDETAPE_FLAG_PIPELINE_ERR,
-                                       &tape->flags);
-                               if (error == IDETAPE_ERROR_EOD)
-                                       idetape_abort_pipeline(drive,
-                                                               active_stage);
-                       }
-               } else if (rq->cmd[0] & REQ_IDETAPE_READ) {
-                       if (error == IDETAPE_ERROR_EOD) {
-                               set_bit(IDETAPE_FLAG_PIPELINE_ERR,
-                                       &tape->flags);
-                               idetape_abort_pipeline(drive, active_stage);
-                       }
-               }
-               if (tape->next_stage != NULL) {
-                       idetape_activate_next_stage(drive);
-
-                       /* Insert the next request into the request queue. */
-                       (void)ide_do_drive_cmd(drive, tape->active_data_rq,
-                                               ide_end);
-               } else if (!error) {
-                       /*
-                        * This is a part of the feedback loop which tries to
-                        * find the optimum number of stages. We are starting
-                        * from a minimum maximum number of stages, and if we
-                        * sense that the pipeline is empty, we try to increase
-                        * it, until we reach the user compile time memory
-                        * limit.
-                        */
-                       int i = (tape->max_pipeline - tape->min_pipeline) / 10;
-
-                       tape->max_stages += max(i, 1);
-                       tape->max_stages = max(tape->max_stages,
-                                               tape->min_pipeline);
-                       tape->max_stages = min(tape->max_stages,
-                                               tape->max_pipeline);
-               }
-       }
        ide_end_drive_cmd(drive, 0, 0);
 
-       if (remove_stage)
-               idetape_remove_stage_head(drive);
-       if (tape->active_data_rq == NULL)
-               clear_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, &tape->flags);
        spin_unlock_irqrestore(&tape->lock, flags);
        return 0;
 }
@@ -993,7 +756,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
        stat = ide_read_status(drive);
 
        if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
-               if (hwif->ide_dma_end(drive) || (stat & ERR_STAT)) {
+               if (hwif->dma_ops->dma_end(drive) || (stat & ERR_STAT)) {
                        /*
                         * A DMA error is sometimes expected. For example,
                         * if the tape is crossing a filemark during a
@@ -1083,10 +846,10 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
                return ide_do_reset(drive);
        }
        /* Get the number of bytes to transfer on this interrupt. */
-       bcount = (hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]) << 8) |
-                 hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]);
+       bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) |
+                 hwif->INB(hwif->io_ports.lbam_addr);
 
-       ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+       ireason = hwif->INB(hwif->io_ports.nsect_addr);
 
        if (ireason & CD) {
                printk(KERN_ERR "ide-tape: CoD != 0 in %s\n", __func__);
@@ -1190,12 +953,12 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
                                "yet DRQ isn't asserted\n");
                return startstop;
        }
-       ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+       ireason = hwif->INB(hwif->io_ports.nsect_addr);
        while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
                printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing "
                                "a packet command, retrying\n");
                udelay(100);
-               ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+               ireason = hwif->INB(hwif->io_ports.nsect_addr);
                if (retries == 0) {
                        printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while "
                                        "issuing a packet command, ignoring\n");
@@ -1213,7 +976,7 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
 #ifdef CONFIG_BLK_DEV_IDEDMA
        /* Begin DMA, if necessary */
        if (pc->flags & PC_FLAG_DMA_IN_PROGRESS)
-               hwif->dma_start(drive);
+               hwif->dma_ops->dma_start(drive);
 #endif
        /* Send the actual packet */
        HWIF(drive)->atapi_output_bytes(drive, pc->c, 12);
@@ -1279,7 +1042,7 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
                ide_dma_off(drive);
        }
        if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma)
-               dma_ok = !hwif->dma_setup(drive);
+               dma_ok = !hwif->dma_ops->dma_setup(drive);
 
        ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
                           IDE_TFLAG_OUT_DEVICE, bcount, dma_ok);
@@ -1292,7 +1055,7 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
                                    IDETAPE_WAIT_CMD, NULL);
                return ide_started;
        } else {
-               hwif->OUTB(WIN_PACKETCMD, hwif->io_ports[IDE_COMMAND_OFFSET]);
+               hwif->OUTB(WIN_PACKETCMD, hwif->io_ports.command_addr);
                return idetape_transfer_pc(drive);
        }
 }
@@ -1335,69 +1098,6 @@ static void idetape_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
        pc->idetape_callback = &idetape_pc_callback;
 }
 
-static void idetape_calculate_speeds(ide_drive_t *drive)
-{
-       idetape_tape_t *tape = drive->driver_data;
-
-       if (time_after(jiffies,
-                       tape->controlled_pipeline_head_time + 120 * HZ)) {
-               tape->controlled_previous_pipeline_head =
-                       tape->controlled_last_pipeline_head;
-               tape->controlled_previous_head_time =
-                       tape->controlled_pipeline_head_time;
-               tape->controlled_last_pipeline_head = tape->pipeline_head;
-               tape->controlled_pipeline_head_time = jiffies;
-       }
-       if (time_after(jiffies, tape->controlled_pipeline_head_time + 60 * HZ))
-               tape->controlled_pipeline_head_speed = (tape->pipeline_head -
-                               tape->controlled_last_pipeline_head) * 32 * HZ /
-                               (jiffies - tape->controlled_pipeline_head_time);
-       else if (time_after(jiffies, tape->controlled_previous_head_time))
-               tape->controlled_pipeline_head_speed = (tape->pipeline_head -
-                               tape->controlled_previous_pipeline_head) * 32 *
-                       HZ / (jiffies - tape->controlled_previous_head_time);
-
-       if (tape->nr_pending_stages < tape->max_stages/*- 1 */) {
-               /* -1 for read mode error recovery */
-               if (time_after(jiffies, tape->uncontrolled_previous_head_time +
-                                       10 * HZ)) {
-                       tape->uncontrolled_pipeline_head_time = jiffies;
-                       tape->uncontrolled_pipeline_head_speed =
-                               (tape->pipeline_head -
-                                tape->uncontrolled_previous_pipeline_head) *
-                               32 * HZ / (jiffies -
-                                       tape->uncontrolled_previous_head_time);
-               }
-       } else {
-               tape->uncontrolled_previous_head_time = jiffies;
-               tape->uncontrolled_previous_pipeline_head = tape->pipeline_head;
-               if (time_after(jiffies, tape->uncontrolled_pipeline_head_time +
-                                       30 * HZ))
-                       tape->uncontrolled_pipeline_head_time = jiffies;
-
-       }
-       tape->pipeline_head_speed = max(tape->uncontrolled_pipeline_head_speed,
-                                       tape->controlled_pipeline_head_speed);
-
-       if (tape->speed_control == 1) {
-               if (tape->nr_pending_stages >= tape->max_stages / 2)
-                       tape->max_insert_speed = tape->pipeline_head_speed +
-                               (1100 - tape->pipeline_head_speed) * 2 *
-                               (tape->nr_pending_stages - tape->max_stages / 2)
-                               / tape->max_stages;
-               else
-                       tape->max_insert_speed = 500 +
-                               (tape->pipeline_head_speed - 500) * 2 *
-                               tape->nr_pending_stages / tape->max_stages;
-
-               if (tape->nr_pending_stages >= tape->max_stages * 99 / 100)
-                       tape->max_insert_speed = 5000;
-       } else
-               tape->max_insert_speed = tape->speed_control;
-
-       tape->max_insert_speed = max(tape->max_insert_speed, 500);
-}
-
 static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
 {
        idetape_tape_t *tape = drive->driver_data;
@@ -1432,17 +1132,7 @@ static ide_startstop_t idetape_rw_callback(ide_drive_t *drive)
        int blocks = tape->pc->xferred / tape->blk_size;
 
        tape->avg_size += blocks * tape->blk_size;
-       tape->insert_size += blocks * tape->blk_size;
-       if (tape->insert_size > 1024 * 1024)
-               tape->measure_insert_time = 1;
-       if (tape->measure_insert_time) {
-               tape->measure_insert_time = 0;
-               tape->insert_time = jiffies;
-               tape->insert_size = 0;
-       }
-       if (time_after(jiffies, tape->insert_time))
-               tape->insert_speed = tape->insert_size / 1024 * HZ /
-                                       (jiffies - tape->insert_time);
+
        if (time_after_eq(jiffies, tape->avg_time + HZ)) {
                tape->avg_speed = tape->avg_size * HZ /
                                (jiffies - tape->avg_time) / 1024;
@@ -1475,7 +1165,7 @@ static void idetape_create_read_cmd(idetape_tape_t *tape,
        pc->buf = NULL;
        pc->buf_size = length * tape->blk_size;
        pc->req_xfer = pc->buf_size;
-       if (pc->req_xfer == tape->stage_size)
+       if (pc->req_xfer == tape->buffer_size)
                pc->flags |= PC_FLAG_DMA_RECOMMENDED;
 }
 
@@ -1495,7 +1185,7 @@ static void idetape_create_write_cmd(idetape_tape_t *tape,
        pc->buf = NULL;
        pc->buf_size = length * tape->blk_size;
        pc->req_xfer = pc->buf_size;
-       if (pc->req_xfer == tape->stage_size)
+       if (pc->req_xfer == tape->buffer_size)
                pc->flags |= PC_FLAG_DMA_RECOMMENDED;
 }
 
@@ -1547,10 +1237,6 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
                drive->post_reset = 0;
        }
 
-       if (time_after(jiffies, tape->insert_time))
-               tape->insert_speed = tape->insert_size / 1024 * HZ /
-                                       (jiffies - tape->insert_time);
-       idetape_calculate_speeds(drive);
        if (!test_and_clear_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags) &&
            (stat & SEEK_STAT) == 0) {
                if (postponed_rq == NULL) {
@@ -1574,16 +1260,12 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
                return ide_stopped;
        }
        if (rq->cmd[0] & REQ_IDETAPE_READ) {
-               tape->buffer_head++;
-               tape->postpone_cnt = 0;
                pc = idetape_next_pc_storage(drive);
                idetape_create_read_cmd(tape, pc, rq->current_nr_sectors,
                                        (struct idetape_bh *)rq->special);
                goto out;
        }
        if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
-               tape->buffer_head++;
-               tape->postpone_cnt = 0;
                pc = idetape_next_pc_storage(drive);
                idetape_create_write_cmd(tape, pc, rq->current_nr_sectors,
                                         (struct idetape_bh *)rq->special);
@@ -1604,111 +1286,91 @@ out:
        return idetape_issue_pc(drive, pc);
 }
 
-/* Pipeline related functions */
-static inline int idetape_pipeline_active(idetape_tape_t *tape)
-{
-       int rc1, rc2;
-
-       rc1 = test_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, &tape->flags);
-       rc2 = (tape->active_data_rq != NULL);
-       return rc1;
-}
-
 /*
- * The function below uses __get_free_page to allocate a pipeline stage, along
- * with all the necessary small buffers which together make a buffer of size
- * tape->stage_size (or a bit more). We attempt to combine sequential pages as
+ * The function below uses __get_free_pages to allocate a data buffer of size
+ * tape->buffer_size (or a bit more). We attempt to combine sequential pages as
  * much as possible.
  *
- * It returns a pointer to the new allocated stage, or NULL if we can't (or
- * don't want to) allocate a stage.
- *
- * Pipeline stages are optional and are used to increase performance. If we
- * can't allocate them, we'll manage without them.
+ * It returns a pointer to the newly allocated buffer, or NULL in case of
+ * failure.
  */
-static idetape_stage_t *__idetape_kmalloc_stage(idetape_tape_t *tape, int full,
-                                               int clear)
+static struct idetape_bh *ide_tape_kmalloc_buffer(idetape_tape_t *tape,
+                                                 int full, int clear)
 {
-       idetape_stage_t *stage;
-       struct idetape_bh *prev_bh, *bh;
-       int pages = tape->pages_per_stage;
+       struct idetape_bh *prev_bh, *bh, *merge_bh;
+       int pages = tape->pages_per_buffer;
+       unsigned int order, b_allocd;
        char *b_data = NULL;
 
-       stage = kmalloc(sizeof(idetape_stage_t), GFP_KERNEL);
-       if (!stage)
-               return NULL;
-       stage->next = NULL;
-
-       stage->bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
-       bh = stage->bh;
+       merge_bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
+       bh = merge_bh;
        if (bh == NULL)
                goto abort;
-       bh->b_reqnext = NULL;
-       bh->b_data = (char *) __get_free_page(GFP_KERNEL);
+
+       order = fls(pages) - 1;
+       bh->b_data = (char *) __get_free_pages(GFP_KERNEL, order);
        if (!bh->b_data)
                goto abort;
+       b_allocd = (1 << order) * PAGE_SIZE;
+       pages &= (order-1);
+
        if (clear)
-               memset(bh->b_data, 0, PAGE_SIZE);
-       bh->b_size = PAGE_SIZE;
+               memset(bh->b_data, 0, b_allocd);
+       bh->b_reqnext = NULL;
+       bh->b_size = b_allocd;
        atomic_set(&bh->b_count, full ? bh->b_size : 0);
 
-       while (--pages) {
-               b_data = (char *) __get_free_page(GFP_KERNEL);
+       while (pages) {
+               order = fls(pages) - 1;
+               b_data = (char *) __get_free_pages(GFP_KERNEL, order);
                if (!b_data)
                        goto abort;
+               b_allocd = (1 << order) * PAGE_SIZE;
+
                if (clear)
-                       memset(b_data, 0, PAGE_SIZE);
-               if (bh->b_data == b_data + PAGE_SIZE) {
-                       bh->b_size += PAGE_SIZE;
-                       bh->b_data -= PAGE_SIZE;
+                       memset(b_data, 0, b_allocd);
+
+               /* newly allocated page frames below buffer header or ...*/
+               if (bh->b_data == b_data + b_allocd) {
+                       bh->b_size += b_allocd;
+                       bh->b_data -= b_allocd;
                        if (full)
-                               atomic_add(PAGE_SIZE, &bh->b_count);
+                               atomic_add(b_allocd, &bh->b_count);
                        continue;
                }
+               /* they are above the header */
                if (b_data == bh->b_data + bh->b_size) {
-                       bh->b_size += PAGE_SIZE;
+                       bh->b_size += b_allocd;
                        if (full)
-                               atomic_add(PAGE_SIZE, &bh->b_count);
+                               atomic_add(b_allocd, &bh->b_count);
                        continue;
                }
                prev_bh = bh;
                bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
                if (!bh) {
-                       free_page((unsigned long) b_data);
+                       free_pages((unsigned long) b_data, order);
                        goto abort;
                }
                bh->b_reqnext = NULL;
                bh->b_data = b_data;
-               bh->b_size = PAGE_SIZE;
+               bh->b_size = b_allocd;
                atomic_set(&bh->b_count, full ? bh->b_size : 0);
                prev_bh->b_reqnext = bh;
+
+               pages &= (order-1);
        }
+
        bh->b_size -= tape->excess_bh_size;
        if (full)
                atomic_sub(tape->excess_bh_size, &bh->b_count);
-       return stage;
+       return merge_bh;
 abort:
-       __idetape_kfree_stage(stage);
+       ide_tape_kfree_buffer(tape);
        return NULL;
 }
 
-static idetape_stage_t *idetape_kmalloc_stage(idetape_tape_t *tape)
-{
-       idetape_stage_t *cache_stage = tape->cache_stage;
-
-       debug_log(DBG_PROCS, "Enter %s\n", __func__);
-
-       if (tape->nr_stages >= tape->max_stages)
-               return NULL;
-       if (cache_stage != NULL) {
-               tape->cache_stage = NULL;
-               return cache_stage;
-       }
-       return __idetape_kmalloc_stage(tape, 0, 0);
-}
-
 static int idetape_copy_stage_from_user(idetape_tape_t *tape,
-               idetape_stage_t *stage, const char __user *buf, int n)
+                                       const char __user *buf, int n)
 {
        struct idetape_bh *bh = tape->bh;
        int count;
@@ -1740,7 +1402,7 @@ static int idetape_copy_stage_from_user(idetape_tape_t *tape,
 }
 
 static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf,
-               idetape_stage_t *stage, int n)
+                                     int n)
 {
        struct idetape_bh *bh = tape->bh;
        int count;
@@ -1771,11 +1433,11 @@ static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf,
        return ret;
 }
 
-static void idetape_init_merge_stage(idetape_tape_t *tape)
+static void idetape_init_merge_buffer(idetape_tape_t *tape)
 {
-       struct idetape_bh *bh = tape->merge_stage->bh;
+       struct idetape_bh *bh = tape->merge_bh;
+       tape->bh = tape->merge_bh;
 
-       tape->bh = bh;
        if (tape->chrdev_dir == IDETAPE_DIR_WRITE)
                atomic_set(&bh->b_count, 0);
        else {
@@ -1784,61 +1446,6 @@ static void idetape_init_merge_stage(idetape_tape_t *tape)
        }
 }
 
-static void idetape_switch_buffers(idetape_tape_t *tape, idetape_stage_t *stage)
-{
-       struct idetape_bh *tmp;
-
-       tmp = stage->bh;
-       stage->bh = tape->merge_stage->bh;
-       tape->merge_stage->bh = tmp;
-       idetape_init_merge_stage(tape);
-}
-
-/* Add a new stage at the end of the pipeline. */
-static void idetape_add_stage_tail(ide_drive_t *drive, idetape_stage_t *stage)
-{
-       idetape_tape_t *tape = drive->driver_data;
-       unsigned long flags;
-
-       debug_log(DBG_PROCS, "Enter %s\n", __func__);
-
-       spin_lock_irqsave(&tape->lock, flags);
-       stage->next = NULL;
-       if (tape->last_stage != NULL)
-               tape->last_stage->next = stage;
-       else
-               tape->first_stage = stage;
-               tape->next_stage  = stage;
-       tape->last_stage = stage;
-       if (tape->next_stage == NULL)
-               tape->next_stage = tape->last_stage;
-       tape->nr_stages++;
-       tape->nr_pending_stages++;
-       spin_unlock_irqrestore(&tape->lock, flags);
-}
-
-/* Install a completion in a pending request and sleep until it is serviced. The
- * caller should ensure that the request will not be serviced before we install
- * the completion (usually by disabling interrupts).
- */
-static void idetape_wait_for_request(ide_drive_t *drive, struct request *rq)
-{
-       DECLARE_COMPLETION_ONSTACK(wait);
-       idetape_tape_t *tape = drive->driver_data;
-
-       if (rq == NULL || !blk_special_request(rq)) {
-               printk(KERN_ERR "ide-tape: bug: Trying to sleep on non-valid"
-                                " request\n");
-               return;
-       }
-       rq->end_io_data = &wait;
-       rq->end_io = blk_end_sync_rq;
-       spin_unlock_irq(&tape->lock);
-       wait_for_completion(&wait);
-       /* The stage and its struct request have been deallocated */
-       spin_lock_irq(&tape->lock);
-}
-
 static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive)
 {
        idetape_tape_t *tape = drive->driver_data;
@@ -1907,7 +1514,7 @@ static void idetape_create_test_unit_ready_cmd(struct ide_atapi_pc *pc)
  * to the request list without waiting for it to be serviced! In that case, we
  * usually use idetape_queue_pc_head().
  */
-static int __idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
+static int idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
 {
        struct ide_tape_obj *tape = drive->driver_data;
        struct request rq;
@@ -1939,7 +1546,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
        timeout += jiffies;
        while (time_before(jiffies, timeout)) {
                idetape_create_test_unit_ready_cmd(&pc);
-               if (!__idetape_queue_pc_tail(drive, &pc))
+               if (!idetape_queue_pc_tail(drive, &pc))
                        return 0;
                if ((tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2)
                    || (tape->asc == 0x3A)) {
@@ -1948,7 +1555,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
                                return -ENOMEDIUM;
                        idetape_create_load_unload_cmd(drive, &pc,
                                                        IDETAPE_LU_LOAD_MASK);
-                       __idetape_queue_pc_tail(drive, &pc);
+                       idetape_queue_pc_tail(drive, &pc);
                        load_attempted = 1;
                /* not about to be ready */
                } else if (!(tape->sense_key == 2 && tape->asc == 4 &&
@@ -1959,11 +1566,6 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
        return -EIO;
 }
 
-static int idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
-{
-       return __idetape_queue_pc_tail(drive, pc);
-}
-
 static int idetape_flush_tape_buffers(ide_drive_t *drive)
 {
        struct ide_atapi_pc pc;
@@ -2029,50 +1631,21 @@ static int idetape_create_prevent_cmd(ide_drive_t *drive,
        return 1;
 }
 
-static int __idetape_discard_read_pipeline(ide_drive_t *drive)
+static void __ide_tape_discard_merge_buffer(ide_drive_t *drive)
 {
        idetape_tape_t *tape = drive->driver_data;
-       unsigned long flags;
-       int cnt;
 
        if (tape->chrdev_dir != IDETAPE_DIR_READ)
-               return 0;
+               return;
 
-       /* Remove merge stage. */
-       cnt = tape->merge_stage_size / tape->blk_size;
-       if (test_and_clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
-               ++cnt;          /* Filemarks count as 1 sector */
-       tape->merge_stage_size = 0;
-       if (tape->merge_stage != NULL) {
-               __idetape_kfree_stage(tape->merge_stage);
-               tape->merge_stage = NULL;
+       clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags);
+       tape->merge_bh_size = 0;
+       if (tape->merge_bh != NULL) {
+               ide_tape_kfree_buffer(tape);
+               tape->merge_bh = NULL;
        }
 
-       /* Clear pipeline flags. */
-       clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags);
        tape->chrdev_dir = IDETAPE_DIR_NONE;
-
-       /* Remove pipeline stages. */
-       if (tape->first_stage == NULL)
-               return 0;
-
-       spin_lock_irqsave(&tape->lock, flags);
-       tape->next_stage = NULL;
-       if (idetape_pipeline_active(tape))
-               idetape_wait_for_request(drive, tape->active_data_rq);
-       spin_unlock_irqrestore(&tape->lock, flags);
-
-       while (tape->first_stage != NULL) {
-               struct request *rq_ptr = &tape->first_stage->rq;
-
-               cnt += rq_ptr->nr_sectors - rq_ptr->current_nr_sectors;
-               if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK)
-                       ++cnt;
-               idetape_remove_stage_head(drive);
-       }
-       tape->nr_pending_stages = 0;
-       tape->max_stages = tape->min_pipeline;
-       return cnt;
 }
 
 /*
@@ -2089,7 +1662,7 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
        struct ide_atapi_pc pc;
 
        if (tape->chrdev_dir == IDETAPE_DIR_READ)
-               __idetape_discard_read_pipeline(drive);
+               __ide_tape_discard_merge_buffer(drive);
        idetape_wait_ready(drive, 60 * 5 * HZ);
        idetape_create_locate_cmd(drive, &pc, block, partition, skip);
        retval = idetape_queue_pc_tail(drive, &pc);
@@ -2100,20 +1673,19 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
        return (idetape_queue_pc_tail(drive, &pc));
 }
 
-static void idetape_discard_read_pipeline(ide_drive_t *drive,
+static void ide_tape_discard_merge_buffer(ide_drive_t *drive,
                                          int restore_position)
 {
        idetape_tape_t *tape = drive->driver_data;
-       int cnt;
        int seek, position;
 
-       cnt = __idetape_discard_read_pipeline(drive);
+       __ide_tape_discard_merge_buffer(drive);
        if (restore_position) {
                position = idetape_read_position(drive);
-               seek = position > cnt ? position - cnt : 0;
+               seek = position > 0 ? position : 0;
                if (idetape_position_tape(drive, seek, 0, 0)) {
                        printk(KERN_INFO "ide-tape: %s: position_tape failed in"
-                                        " discard_pipeline()\n", tape->name);
+                                        " %s\n", tape->name, __func__);
                        return;
                }
        }
@@ -2131,12 +1703,6 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
 
        debug_log(DBG_SENSE, "%s: cmd=%d\n", __func__, cmd);
 
-       if (idetape_pipeline_active(tape)) {
-               printk(KERN_ERR "ide-tape: bug: the pipeline is active in %s\n",
-                               __func__);
-               return (0);
-       }
-
        idetape_init_rq(&rq, cmd);
        rq.rq_disk = tape->disk;
        rq.special = (void *)bh;
@@ -2148,27 +1714,13 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
        if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0)
                return 0;
 
-       if (tape->merge_stage)
-               idetape_init_merge_stage(tape);
+       if (tape->merge_bh)
+               idetape_init_merge_buffer(tape);
        if (rq.errors == IDETAPE_ERROR_GENERAL)
                return -EIO;
        return (tape->blk_size * (blocks-rq.current_nr_sectors));
 }
 
-/* start servicing the pipeline stages, starting from tape->next_stage. */
-static void idetape_plug_pipeline(ide_drive_t *drive)
-{
-       idetape_tape_t *tape = drive->driver_data;
-
-       if (tape->next_stage == NULL)
-               return;
-       if (!idetape_pipeline_active(tape)) {
-               set_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, &tape->flags);
-               idetape_activate_next_stage(drive);
-               (void) ide_do_drive_cmd(drive, tape->active_data_rq, ide_end);
-       }
-}
-
 static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc)
 {
        idetape_init_pc(pc);
@@ -2206,135 +1758,39 @@ static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd)
        pc->idetape_callback = &idetape_pc_callback;
 }
 
-static void idetape_wait_first_stage(ide_drive_t *drive)
-{
-       idetape_tape_t *tape = drive->driver_data;
-       unsigned long flags;
-
-       if (tape->first_stage == NULL)
-               return;
-       spin_lock_irqsave(&tape->lock, flags);
-       if (tape->active_stage == tape->first_stage)
-               idetape_wait_for_request(drive, tape->active_data_rq);
-       spin_unlock_irqrestore(&tape->lock, flags);
-}
-
-/*
- * Try to add a character device originated write request to our pipeline. In
- * case we don't succeed, we revert to non-pipelined operation mode for this
- * request. In order to accomplish that, we
- *
- * 1. Try to allocate a new pipeline stage.
- * 2. If we can't, wait for more and more requests to be serviced and try again
- * each time.
- * 3. If we still can't allocate a stage, fallback to non-pipelined operation
- * mode for this request.
- */
+/* Queue up a character device originated write request. */
 static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks)
 {
        idetape_tape_t *tape = drive->driver_data;
-       idetape_stage_t *new_stage;
-       unsigned long flags;
-       struct request *rq;
 
        debug_log(DBG_CHRDEV, "Enter %s\n", __func__);
 
-       /* Attempt to allocate a new stage. Beware possible race conditions. */
-       while ((new_stage = idetape_kmalloc_stage(tape)) == NULL) {
-               spin_lock_irqsave(&tape->lock, flags);
-               if (idetape_pipeline_active(tape)) {
-                       idetape_wait_for_request(drive, tape->active_data_rq);
-                       spin_unlock_irqrestore(&tape->lock, flags);
-               } else {
-                       spin_unlock_irqrestore(&tape->lock, flags);
-                       idetape_plug_pipeline(drive);
-                       if (idetape_pipeline_active(tape))
-                               continue;
-                       /*
-                        * The machine is short on memory. Fallback to non-
-                        * pipelined operation mode for this request.
-                        */
-                       return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE,
-                                               blocks, tape->merge_stage->bh);
-               }
-       }
-       rq = &new_stage->rq;
-       idetape_init_rq(rq, REQ_IDETAPE_WRITE);
-       /* Doesn't actually matter - We always assume sequential access */
-       rq->sector = tape->first_frame;
-       rq->current_nr_sectors = blocks;
-       rq->nr_sectors = blocks;
-
-       idetape_switch_buffers(tape, new_stage);
-       idetape_add_stage_tail(drive, new_stage);
-       tape->pipeline_head++;
-       idetape_calculate_speeds(drive);
-
-       /*
-        * Estimate whether the tape has stopped writing by checking if our
-        * write pipeline is currently empty. If we are not writing anymore,
-        * wait for the pipeline to be almost completely full (90%) before
-        * starting to service requests, so that we will be able to keep up with
-        * the higher speeds of the tape.
-        */
-       if (!idetape_pipeline_active(tape)) {
-               if (tape->nr_stages >= tape->max_stages * 9 / 10 ||
-                       tape->nr_stages >= tape->max_stages -
-                       tape->uncontrolled_pipeline_head_speed * 3 * 1024 /
-                       tape->blk_size) {
-                       tape->measure_insert_time = 1;
-                       tape->insert_time = jiffies;
-                       tape->insert_size = 0;
-                       tape->insert_speed = 0;
-                       idetape_plug_pipeline(drive);
-               }
-       }
-       if (test_and_clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags))
-               /* Return a deferred error */
-               return -EIO;
-       return blocks;
-}
-
-/*
- * Wait until all pending pipeline requests are serviced. Typically called on
- * device close.
- */
-static void idetape_wait_for_pipeline(ide_drive_t *drive)
-{
-       idetape_tape_t *tape = drive->driver_data;
-       unsigned long flags;
-
-       while (tape->next_stage || idetape_pipeline_active(tape)) {
-               idetape_plug_pipeline(drive);
-               spin_lock_irqsave(&tape->lock, flags);
-               if (idetape_pipeline_active(tape))
-                       idetape_wait_for_request(drive, tape->active_data_rq);
-               spin_unlock_irqrestore(&tape->lock, flags);
-       }
+       return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE,
+                                    blocks, tape->merge_bh);
 }
 
-static void idetape_empty_write_pipeline(ide_drive_t *drive)
+static void ide_tape_flush_merge_buffer(ide_drive_t *drive)
 {
        idetape_tape_t *tape = drive->driver_data;
        int blocks, min;
        struct idetape_bh *bh;
 
        if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
-               printk(KERN_ERR "ide-tape: bug: Trying to empty write pipeline,"
+               printk(KERN_ERR "ide-tape: bug: Trying to empty merge buffer"
                                " but we are not writing.\n");
                return;
        }
-       if (tape->merge_stage_size > tape->stage_size) {
+       if (tape->merge_bh_size > tape->buffer_size) {
                printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n");
-               tape->merge_stage_size = tape->stage_size;
+               tape->merge_bh_size = tape->buffer_size;
        }
-       if (tape->merge_stage_size) {
-               blocks = tape->merge_stage_size / tape->blk_size;
-               if (tape->merge_stage_size % tape->blk_size) {
+       if (tape->merge_bh_size) {
+               blocks = tape->merge_bh_size / tape->blk_size;
+               if (tape->merge_bh_size % tape->blk_size) {
                        unsigned int i;
 
                        blocks++;
-                       i = tape->blk_size - tape->merge_stage_size %
+                       i = tape->blk_size - tape->merge_bh_size %
                                tape->blk_size;
                        bh = tape->bh->b_reqnext;
                        while (bh) {
@@ -2358,74 +1814,33 @@ static void idetape_empty_write_pipeline(ide_drive_t *drive)
                        }
                }
                (void) idetape_add_chrdev_write_request(drive, blocks);
-               tape->merge_stage_size = 0;
+               tape->merge_bh_size = 0;
        }
-       idetape_wait_for_pipeline(drive);
-       if (tape->merge_stage != NULL) {
-               __idetape_kfree_stage(tape->merge_stage);
-               tape->merge_stage = NULL;
+       if (tape->merge_bh != NULL) {
+               ide_tape_kfree_buffer(tape);
+               tape->merge_bh = NULL;
        }
-       clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags);
        tape->chrdev_dir = IDETAPE_DIR_NONE;
-
-       /*
-        * On the next backup, perform the feedback loop again. (I don't want to
-        * keep sense information between backups, as some systems are
-        * constantly on, and the system load can be totally different on the
-        * next backup).
-        */
-       tape->max_stages = tape->min_pipeline;
-       if (tape->first_stage != NULL ||
-           tape->next_stage != NULL ||
-           tape->last_stage != NULL ||
-           tape->nr_stages != 0) {
-               printk(KERN_ERR "ide-tape: ide-tape pipeline bug, "
-                       "first_stage %p, next_stage %p, "
-                       "last_stage %p, nr_stages %d\n",
-                       tape->first_stage, tape->next_stage,
-                       tape->last_stage, tape->nr_stages);
-       }
 }
 
-static void idetape_restart_speed_control(ide_drive_t *drive)
+static int idetape_init_read(ide_drive_t *drive)
 {
        idetape_tape_t *tape = drive->driver_data;
-
-       tape->restart_speed_control_req = 0;
-       tape->pipeline_head = 0;
-       tape->controlled_last_pipeline_head = 0;
-       tape->controlled_previous_pipeline_head = 0;
-       tape->uncontrolled_previous_pipeline_head = 0;
-       tape->controlled_pipeline_head_speed = 5000;
-       tape->pipeline_head_speed = 5000;
-       tape->uncontrolled_pipeline_head_speed = 0;
-       tape->controlled_pipeline_head_time =
-               tape->uncontrolled_pipeline_head_time = jiffies;
-       tape->controlled_previous_head_time =
-               tape->uncontrolled_previous_head_time = jiffies;
-}
-
-static int idetape_init_read(ide_drive_t *drive, int max_stages)
-{
-       idetape_tape_t *tape = drive->driver_data;
-       idetape_stage_t *new_stage;
-       struct request rq;
        int bytes_read;
-       u16 blocks = *(u16 *)&tape->caps[12];
 
        /* Initialize read operation */
        if (tape->chrdev_dir != IDETAPE_DIR_READ) {
                if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
-                       idetape_empty_write_pipeline(drive);
+                       ide_tape_flush_merge_buffer(drive);
                        idetape_flush_tape_buffers(drive);
                }
-               if (tape->merge_stage || tape->merge_stage_size) {
-                       printk(KERN_ERR "ide-tape: merge_stage_size should be"
+               if (tape->merge_bh || tape->merge_bh_size) {
+                       printk(KERN_ERR "ide-tape: merge_bh_size should be"
                                         " 0 now\n");
-                       tape->merge_stage_size = 0;
+                       tape->merge_bh_size = 0;
                }
-               tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0);
-               if (!tape->merge_stage)
+               tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0);
+               if (!tape->merge_bh)
                        return -ENOMEM;
                tape->chrdev_dir = IDETAPE_DIR_READ;
 
@@ -2438,54 +1853,23 @@ static int idetape_init_read(ide_drive_t *drive, int max_stages)
                if (drive->dsc_overlap) {
                        bytes_read = idetape_queue_rw_tail(drive,
                                                        REQ_IDETAPE_READ, 0,
-                                                       tape->merge_stage->bh);
+                                                       tape->merge_bh);
                        if (bytes_read < 0) {
-                               __idetape_kfree_stage(tape->merge_stage);
-                               tape->merge_stage = NULL;
+                               ide_tape_kfree_buffer(tape);
+                               tape->merge_bh = NULL;
                                tape->chrdev_dir = IDETAPE_DIR_NONE;
                                return bytes_read;
                        }
                }
        }
-       if (tape->restart_speed_control_req)
-               idetape_restart_speed_control(drive);
-       idetape_init_rq(&rq, REQ_IDETAPE_READ);
-       rq.sector = tape->first_frame;
-       rq.nr_sectors = blocks;
-       rq.current_nr_sectors = blocks;
-       if (!test_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags) &&
-           tape->nr_stages < max_stages) {
-               new_stage = idetape_kmalloc_stage(tape);
-               while (new_stage != NULL) {
-                       new_stage->rq = rq;
-                       idetape_add_stage_tail(drive, new_stage);
-                       if (tape->nr_stages >= max_stages)
-                               break;
-                       new_stage = idetape_kmalloc_stage(tape);
-               }
-       }
-       if (!idetape_pipeline_active(tape)) {
-               if (tape->nr_pending_stages >= 3 * max_stages / 4) {
-                       tape->measure_insert_time = 1;
-                       tape->insert_time = jiffies;
-                       tape->insert_size = 0;
-                       tape->insert_speed = 0;
-                       idetape_plug_pipeline(drive);
-               }
-       }
+
        return 0;
 }
 
-/*
- * Called from idetape_chrdev_read() to service a character device read request
- * and add read-ahead requests to our pipeline.
- */
+/* called from idetape_chrdev_read() to service a chrdev read request. */
 static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
 {
        idetape_tape_t *tape = drive->driver_data;
-       unsigned long flags;
-       struct request *rq_ptr;
-       int bytes_read;
 
        debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks);
 
@@ -2493,39 +1877,10 @@ static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
        if (test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
                return 0;
 
-       /* Wait for the next block to reach the head of the pipeline. */
-       idetape_init_read(drive, tape->max_stages);
-       if (tape->first_stage == NULL) {
-               if (test_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags))
-                       return 0;
-               return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks,
-                                       tape->merge_stage->bh);
-       }
-       idetape_wait_first_stage(drive);
-       rq_ptr = &tape->first_stage->rq;
-       bytes_read = tape->blk_size * (rq_ptr->nr_sectors -
-                                       rq_ptr->current_nr_sectors);
-       rq_ptr->nr_sectors = 0;
-       rq_ptr->current_nr_sectors = 0;
+       idetape_init_read(drive);
 
-       if (rq_ptr->errors == IDETAPE_ERROR_EOD)
-               return 0;
-       else {
-               idetape_switch_buffers(tape, tape->first_stage);
-               if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK)
-                       set_bit(IDETAPE_FLAG_FILEMARK, &tape->flags);
-               spin_lock_irqsave(&tape->lock, flags);
-               idetape_remove_stage_head(drive);
-               spin_unlock_irqrestore(&tape->lock, flags);
-               tape->pipeline_head++;
-               idetape_calculate_speeds(drive);
-       }
-       if (bytes_read > blocks * tape->blk_size) {
-               printk(KERN_ERR "ide-tape: bug: trying to return more bytes"
-                               " than requested\n");
-               bytes_read = blocks * tape->blk_size;
-       }
-       return (bytes_read);
+       return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks,
+                                    tape->merge_bh);
 }
 
 static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
@@ -2537,8 +1892,8 @@ static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
        while (bcount) {
                unsigned int count;
 
-               bh = tape->merge_stage->bh;
-               count = min(tape->stage_size, bcount);
+               bh = tape->merge_bh;
+               count = min(tape->buffer_size, bcount);
                bcount -= count;
                blocks = count / tape->blk_size;
                while (count) {
@@ -2549,31 +1904,10 @@ static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
                        bh = bh->b_reqnext;
                }
                idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks,
-                                     tape->merge_stage->bh);
+                                     tape->merge_bh);
        }
 }
 
-static int idetape_pipeline_size(ide_drive_t *drive)
-{
-       idetape_tape_t *tape = drive->driver_data;
-       idetape_stage_t *stage;
-       struct request *rq;
-       int size = 0;
-
-       idetape_wait_for_pipeline(drive);
-       stage = tape->first_stage;
-       while (stage != NULL) {
-               rq = &stage->rq;
-               size += tape->blk_size * (rq->nr_sectors -
-                               rq->current_nr_sectors);
-               if (rq->errors == IDETAPE_ERROR_FILEMARK)
-                       size += tape->blk_size;
-               stage = stage->next;
-       }
-       size += tape->merge_stage_size;
-       return size;
-}
-
 /*
  * Rewinds the tape to the Beginning Of the current Partition (BOP). We
  * currently support only one partition.
@@ -2619,11 +1953,10 @@ static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd,
                if (copy_from_user(&config, argp, sizeof(config)))
                        return -EFAULT;
                tape->best_dsc_rw_freq = config.dsc_rw_frequency;
-               tape->max_stages = config.nr_stages;
                break;
        case 0x0350:
                config.dsc_rw_frequency = (int) tape->best_dsc_rw_freq;
-               config.nr_stages = tape->max_stages;
+               config.nr_stages = 1;
                if (copy_to_user(argp, &config, sizeof(config)))
                        return -EFAULT;
                break;
@@ -2633,19 +1966,11 @@ static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd,
        return 0;
 }
 
-/*
- * The function below is now a bit more complicated than just passing the
- * command to the tape since we may have crossed some filemarks during our
- * pipelined read-ahead mode. As a minor side effect, the pipeline enables us to
- * support MTFSFM when the filemark is in our internal pipeline even if the tape
- * doesn't support spacing over filemarks in the reverse direction.
- */
 static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
                                        int mt_count)
 {
        idetape_tape_t *tape = drive->driver_data;
        struct ide_atapi_pc pc;
-       unsigned long flags;
        int retval, count = 0;
        int sprev = !!(tape->caps[4] & 0x20);
 
@@ -2658,48 +1983,12 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
        }
 
        if (tape->chrdev_dir == IDETAPE_DIR_READ) {
-               /* its a read-ahead buffer, scan it for crossed filemarks. */
-               tape->merge_stage_size = 0;
+               tape->merge_bh_size = 0;
                if (test_and_clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
                        ++count;
-               while (tape->first_stage != NULL) {
-                       if (count == mt_count) {
-                               if (mt_op == MTFSFM)
-                                       set_bit(IDETAPE_FLAG_FILEMARK,
-                                               &tape->flags);
-                               return 0;
-                       }
-                       spin_lock_irqsave(&tape->lock, flags);
-                       if (tape->first_stage == tape->active_stage) {
-                               /*
-                                * We have reached the active stage in the read
-                                * pipeline. There is no point in allowing the
-                                * drive to continue reading any farther, so we
-                                * stop the pipeline.
-                                *
-                                * This section should be moved to a separate
-                                * subroutine because similar operations are
-                                * done in __idetape_discard_read_pipeline(),
-                                * for example.
-                                */
-                               tape->next_stage = NULL;
-                               spin_unlock_irqrestore(&tape->lock, flags);
-                               idetape_wait_first_stage(drive);
-                               tape->next_stage = tape->first_stage->next;
-                       } else
-                               spin_unlock_irqrestore(&tape->lock, flags);
-                       if (tape->first_stage->rq.errors ==
-                                       IDETAPE_ERROR_FILEMARK)
-                               ++count;
-                       idetape_remove_stage_head(drive);
-               }
-               idetape_discard_read_pipeline(drive, 0);
+               ide_tape_discard_merge_buffer(drive, 0);
        }
 
-       /*
-        * The filemark was not found in our internal pipeline; now we can issue
-        * the space command.
-        */
        switch (mt_op) {
        case MTFSF:
        case MTBSF:
@@ -2755,27 +2044,25 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
                            (count % tape->blk_size) == 0)
                                tape->user_bs_factor = count / tape->blk_size;
        }
-       rc = idetape_init_read(drive, tape->max_stages);
+       rc = idetape_init_read(drive);
        if (rc < 0)
                return rc;
        if (count == 0)
                return (0);
-       if (tape->merge_stage_size) {
-               actually_read = min((unsigned int)(tape->merge_stage_size),
+       if (tape->merge_bh_size) {
+               actually_read = min((unsigned int)(tape->merge_bh_size),
                                    (unsigned int)count);
-               if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage,
-                                              actually_read))
+               if (idetape_copy_stage_to_user(tape, buf, actually_read))
                        ret = -EFAULT;
                buf += actually_read;
-               tape->merge_stage_size -= actually_read;
+               tape->merge_bh_size -= actually_read;
                count -= actually_read;
        }
-       while (count >= tape->stage_size) {
+       while (count >= tape->buffer_size) {
                bytes_read = idetape_add_chrdev_read_request(drive, ctl);
                if (bytes_read <= 0)
                        goto finish;
-               if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage,
-                                              bytes_read))
+               if (idetape_copy_stage_to_user(tape, buf, bytes_read))
                        ret = -EFAULT;
                buf += bytes_read;
                count -= bytes_read;
@@ -2786,11 +2073,10 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
                if (bytes_read <= 0)
                        goto finish;
                temp = min((unsigned long)count, (unsigned long)bytes_read);
-               if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage,
-                                              temp))
+               if (idetape_copy_stage_to_user(tape, buf, temp))
                        ret = -EFAULT;
                actually_read += temp;
-               tape->merge_stage_size = bytes_read-temp;
+               tape->merge_bh_size = bytes_read-temp;
        }
 finish:
        if (!actually_read && test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags)) {
@@ -2821,17 +2107,17 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
        /* Initialize write operation */
        if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
                if (tape->chrdev_dir == IDETAPE_DIR_READ)
-                       idetape_discard_read_pipeline(drive, 1);
-               if (tape->merge_stage || tape->merge_stage_size) {
-                       printk(KERN_ERR "ide-tape: merge_stage_size "
+                       ide_tape_discard_merge_buffer(drive, 1);
+               if (tape->merge_bh || tape->merge_bh_size) {
+                       printk(KERN_ERR "ide-tape: merge_bh_size "
                                "should be 0 now\n");
-                       tape->merge_stage_size = 0;
+                       tape->merge_bh_size = 0;
                }
-               tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0);
-               if (!tape->merge_stage)
+               tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0);
+               if (!tape->merge_bh)
                        return -ENOMEM;
                tape->chrdev_dir = IDETAPE_DIR_WRITE;
-               idetape_init_merge_stage(tape);
+               idetape_init_merge_buffer(tape);
 
                /*
                 * Issue a write 0 command to ensure that DSC handshake is
@@ -2842,10 +2128,10 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
                if (drive->dsc_overlap) {
                        ssize_t retval = idetape_queue_rw_tail(drive,
                                                        REQ_IDETAPE_WRITE, 0,
-                                                       tape->merge_stage->bh);
+                                                       tape->merge_bh);
                        if (retval < 0) {
-                               __idetape_kfree_stage(tape->merge_stage);
-                               tape->merge_stage = NULL;
+                               ide_tape_kfree_buffer(tape);
+                               tape->merge_bh = NULL;
                                tape->chrdev_dir = IDETAPE_DIR_NONE;
                                return retval;
                        }
@@ -2853,49 +2139,44 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
        }
        if (count == 0)
                return (0);
-       if (tape->restart_speed_control_req)
-               idetape_restart_speed_control(drive);
-       if (tape->merge_stage_size) {
-               if (tape->merge_stage_size >= tape->stage_size) {
+       if (tape->merge_bh_size) {
+               if (tape->merge_bh_size >= tape->buffer_size) {
                        printk(KERN_ERR "ide-tape: bug: merge buf too big\n");
-                       tape->merge_stage_size = 0;
+                       tape->merge_bh_size = 0;
                }
                actually_written = min((unsigned int)
-                               (tape->stage_size - tape->merge_stage_size),
+                               (tape->buffer_size - tape->merge_bh_size),
                                (unsigned int)count);
-               if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf,
-                                                actually_written))
+               if (idetape_copy_stage_from_user(tape, buf, actually_written))
                                ret = -EFAULT;
                buf += actually_written;
-               tape->merge_stage_size += actually_written;
+               tape->merge_bh_size += actually_written;
                count -= actually_written;
 
-               if (tape->merge_stage_size == tape->stage_size) {
+               if (tape->merge_bh_size == tape->buffer_size) {
                        ssize_t retval;
-                       tape->merge_stage_size = 0;
+                       tape->merge_bh_size = 0;
                        retval = idetape_add_chrdev_write_request(drive, ctl);
                        if (retval <= 0)
                                return (retval);
                }
        }
-       while (count >= tape->stage_size) {
+       while (count >= tape->buffer_size) {
                ssize_t retval;
-               if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf,
-                                                tape->stage_size))
+               if (idetape_copy_stage_from_user(tape, buf, tape->buffer_size))
                        ret = -EFAULT;
-               buf += tape->stage_size;
-               count -= tape->stage_size;
+               buf += tape->buffer_size;
+               count -= tape->buffer_size;
                retval = idetape_add_chrdev_write_request(drive, ctl);
-               actually_written += tape->stage_size;
+               actually_written += tape->buffer_size;
                if (retval <= 0)
                        return (retval);
        }
        if (count) {
                actually_written += count;
-               if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf,
-                                                count))
+               if (idetape_copy_stage_from_user(tape, buf, count))
                        ret = -EFAULT;
-               tape->merge_stage_size += count;
+               tape->merge_bh_size += count;
        }
        return ret ? ret : actually_written;
 }
@@ -2919,8 +2200,7 @@ static int idetape_write_filemark(ide_drive_t *drive)
  *
  * Note: MTBSF and MTBSFM are not supported when the tape doesn't support
  * spacing over filemarks in the reverse direction. In this case, MTFSFM is also
- * usually not supported (it is supported in the rare case in which we crossed
- * the filemark during our read-ahead pipelined operation mode).
+ * usually not supported.
  *
  * The following commands are currently not supported:
  *
@@ -2936,7 +2216,6 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
        debug_log(DBG_ERR, "Handling MTIOCTOP ioctl: mt_op=%d, mt_count=%d\n",
                        mt_op, mt_count);
 
-       /* Commands which need our pipelined read-ahead stages. */
        switch (mt_op) {
        case MTFSF:
        case MTFSFM:
@@ -2953,7 +2232,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
        case MTWEOF:
                if (tape->write_prot)
                        return -EACCES;
-               idetape_discard_read_pipeline(drive, 1);
+               ide_tape_discard_merge_buffer(drive, 1);
                for (i = 0; i < mt_count; i++) {
                        retval = idetape_write_filemark(drive);
                        if (retval)
@@ -2961,12 +2240,12 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
                }
                return 0;
        case MTREW:
-               idetape_discard_read_pipeline(drive, 0);
+               ide_tape_discard_merge_buffer(drive, 0);
                if (idetape_rewind_tape(drive))
                        return -EIO;
                return 0;
        case MTLOAD:
-               idetape_discard_read_pipeline(drive, 0);
+               ide_tape_discard_merge_buffer(drive, 0);
                idetape_create_load_unload_cmd(drive, &pc,
                                               IDETAPE_LU_LOAD_MASK);
                return idetape_queue_pc_tail(drive, &pc);
@@ -2981,7 +2260,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
                                if (!idetape_queue_pc_tail(drive, &pc))
                                        tape->door_locked = DOOR_UNLOCKED;
                }
-               idetape_discard_read_pipeline(drive, 0);
+               ide_tape_discard_merge_buffer(drive, 0);
                idetape_create_load_unload_cmd(drive, &pc,
                                              !IDETAPE_LU_LOAD_MASK);
                retval = idetape_queue_pc_tail(drive, &pc);
@@ -2989,10 +2268,10 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
                        clear_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags);
                return retval;
        case MTNOP:
-               idetape_discard_read_pipeline(drive, 0);
+               ide_tape_discard_merge_buffer(drive, 0);
                return idetape_flush_tape_buffers(drive);
        case MTRETEN:
-               idetape_discard_read_pipeline(drive, 0);
+               ide_tape_discard_merge_buffer(drive, 0);
                idetape_create_load_unload_cmd(drive, &pc,
                        IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK);
                return idetape_queue_pc_tail(drive, &pc);
@@ -3014,11 +2293,11 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
                        set_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags);
                return 0;
        case MTSEEK:
-               idetape_discard_read_pipeline(drive, 0);
+               ide_tape_discard_merge_buffer(drive, 0);
                return idetape_position_tape(drive,
                        mt_count * tape->user_bs_factor, tape->partition, 0);
        case MTSETPART:
-               idetape_discard_read_pipeline(drive, 0);
+               ide_tape_discard_merge_buffer(drive, 0);
                return idetape_position_tape(drive, 0, mt_count, 0);
        case MTFSR:
        case MTBSR:
@@ -3063,13 +2342,12 @@ static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
 
        debug_log(DBG_CHRDEV, "Enter %s, cmd=%u\n", __func__, cmd);
 
-       tape->restart_speed_control_req = 1;
        if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
-               idetape_empty_write_pipeline(drive);
+               ide_tape_flush_merge_buffer(drive);
                idetape_flush_tape_buffers(drive);
        }
        if (cmd == MTIOCGET || cmd == MTIOCPOS) {
-               block_offset = idetape_pipeline_size(drive) /
+               block_offset = tape->merge_bh_size /
                        (tape->blk_size * tape->user_bs_factor);
                position = idetape_read_position(drive);
                if (position < 0)
@@ -3101,7 +2379,7 @@ static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
                return 0;
        default:
                if (tape->chrdev_dir == IDETAPE_DIR_READ)
-                       idetape_discard_read_pipeline(drive, 1);
+                       ide_tape_discard_merge_buffer(drive, 1);
                return idetape_blkdev_ioctl(drive, cmd, arg);
        }
 }
@@ -3175,9 +2453,6 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
        if (!test_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags))
                (void)idetape_rewind_tape(drive);
 
-       if (tape->chrdev_dir != IDETAPE_DIR_READ)
-               clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags);
-
        /* Read block size and write protect status from drive. */
        ide_tape_get_bsize_from_bdesc(drive);
 
@@ -3206,8 +2481,6 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
                        }
                }
        }
-       idetape_restart_speed_control(drive);
-       tape->restart_speed_control_req = 0;
        return 0;
 
 out_put_tape:
@@ -3219,13 +2492,13 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
 {
        idetape_tape_t *tape = drive->driver_data;
 
-       idetape_empty_write_pipeline(drive);
-       tape->merge_stage = __idetape_kmalloc_stage(tape, 1, 0);
-       if (tape->merge_stage != NULL) {
+       ide_tape_flush_merge_buffer(drive);
+       tape->merge_bh = ide_tape_kmalloc_buffer(tape, 1, 0);
+       if (tape->merge_bh != NULL) {
                idetape_pad_zeros(drive, tape->blk_size *
                                (tape->user_bs_factor - 1));
-               __idetape_kfree_stage(tape->merge_stage);
-               tape->merge_stage = NULL;
+               ide_tape_kfree_buffer(tape);
+               tape->merge_bh = NULL;
        }
        idetape_write_filemark(drive);
        idetape_flush_tape_buffers(drive);
@@ -3248,14 +2521,9 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
                idetape_write_release(drive, minor);
        if (tape->chrdev_dir == IDETAPE_DIR_READ) {
                if (minor < 128)
-                       idetape_discard_read_pipeline(drive, 1);
-               else
-                       idetape_wait_for_pipeline(drive);
-       }
-       if (tape->cache_stage != NULL) {
-               __idetape_kfree_stage(tape->cache_stage);
-               tape->cache_stage = NULL;
+                       ide_tape_discard_merge_buffer(drive, 1);
        }
+
        if (minor < 128 && test_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags))
                (void) idetape_rewind_tape(drive);
        if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
@@ -3392,33 +2660,15 @@ static void idetape_add_settings(ide_drive_t *drive)
 
        ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff,
                        1, 2, (u16 *)&tape->caps[16], NULL);
-       ide_add_setting(drive, "pipeline_min", SETTING_RW, TYPE_INT, 1, 0xffff,
-                       tape->stage_size / 1024, 1, &tape->min_pipeline, NULL);
-       ide_add_setting(drive, "pipeline", SETTING_RW, TYPE_INT, 1, 0xffff,
-                       tape->stage_size / 1024, 1, &tape->max_stages, NULL);
-       ide_add_setting(drive, "pipeline_max", SETTING_RW, TYPE_INT, 1, 0xffff,
-                       tape->stage_size / 1024, 1, &tape->max_pipeline, NULL);
-       ide_add_setting(drive, "pipeline_used", SETTING_READ, TYPE_INT, 0,
-                       0xffff, tape->stage_size / 1024, 1, &tape->nr_stages,
-                       NULL);
-       ide_add_setting(drive, "pipeline_pending", SETTING_READ, TYPE_INT, 0,
-                       0xffff, tape->stage_size / 1024, 1,
-                       &tape->nr_pending_stages, NULL);
        ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff,
                        1, 1, (u16 *)&tape->caps[14], NULL);
-       ide_add_setting(drive, "stage", SETTING_READ, TYPE_INT, 0, 0xffff, 1,
-                       1024, &tape->stage_size, NULL);
+       ide_add_setting(drive, "buffer_size", SETTING_READ, TYPE_INT, 0, 0xffff,
+                       1, 1024, &tape->buffer_size, NULL);
        ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN,
                        IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_freq,
                        NULL);
        ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1,
                        1, &drive->dsc_overlap, NULL);
-       ide_add_setting(drive, "pipeline_head_speed_c", SETTING_READ, TYPE_INT,
-                       0, 0xffff, 1, 1, &tape->controlled_pipeline_head_speed,
-                       NULL);
-       ide_add_setting(drive, "pipeline_head_speed_u", SETTING_READ, TYPE_INT,
-                       0, 0xffff, 1, 1,
-                       &tape->uncontrolled_pipeline_head_speed, NULL);
        ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff,
                        1, 1, &tape->avg_speed, NULL);
        ide_add_setting(drive, "debug_mask", SETTING_RW, TYPE_INT, 0, 0xffff, 1,
@@ -3441,11 +2691,10 @@ static inline void idetape_add_settings(ide_drive_t *drive) { ; }
  */
 static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
 {
-       unsigned long t1, tmid, tn, t;
+       unsigned long t;
        int speed;
-       int stage_size;
+       int buffer_size;
        u8 gcw[2];
-       struct sysinfo si;
        u16 *ctl = (u16 *)&tape->caps[12];
 
        spin_lock_init(&tape->lock);
@@ -3464,65 +2713,33 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
        tape->name[2] = '0' + minor;
        tape->chrdev_dir = IDETAPE_DIR_NONE;
        tape->pc = tape->pc_stack;
-       tape->max_insert_speed = 10000;
-       tape->speed_control = 1;
        *((unsigned short *) &gcw) = drive->id->config;
 
        /* Command packet DRQ type */
        if (((gcw[0] & 0x60) >> 5) == 1)
                set_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags);
 
-       tape->min_pipeline = 10;
-       tape->max_pipeline = 10;
-       tape->max_stages   = 10;
-
        idetape_get_inquiry_results(drive);
        idetape_get_mode_sense_results(drive);
        ide_tape_get_bsize_from_bdesc(drive);
        tape->user_bs_factor = 1;
-       tape->stage_size = *ctl * tape->blk_size;
-       while (tape->stage_size > 0xffff) {
+       tape->buffer_size = *ctl * tape->blk_size;
+       while (tape->buffer_size > 0xffff) {
                printk(KERN_NOTICE "ide-tape: decreasing stage size\n");
                *ctl /= 2;
-               tape->stage_size = *ctl * tape->blk_size;
+               tape->buffer_size = *ctl * tape->blk_size;
        }
-       stage_size = tape->stage_size;
-       tape->pages_per_stage = stage_size / PAGE_SIZE;
-       if (stage_size % PAGE_SIZE) {
-               tape->pages_per_stage++;
-               tape->excess_bh_size = PAGE_SIZE - stage_size % PAGE_SIZE;
+       buffer_size = tape->buffer_size;
+       tape->pages_per_buffer = buffer_size / PAGE_SIZE;
+       if (buffer_size % PAGE_SIZE) {
+               tape->pages_per_buffer++;
+               tape->excess_bh_size = PAGE_SIZE - buffer_size % PAGE_SIZE;
        }
 
-       /* Select the "best" DSC read/write polling freq and pipeline size. */
+       /* select the "best" DSC read/write polling freq */
        speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]);
 
-       tape->max_stages = speed * 1000 * 10 / tape->stage_size;
-
-       /* Limit memory use for pipeline to 10% of physical memory */
-       si_meminfo(&si);
-       if (tape->max_stages * tape->stage_size >
-                       si.totalram * si.mem_unit / 10)
-               tape->max_stages =
-                       si.totalram * si.mem_unit / (10 * tape->stage_size);
-
-       tape->max_stages   = min(tape->max_stages, IDETAPE_MAX_PIPELINE_STAGES);
-       tape->min_pipeline = min(tape->max_stages, IDETAPE_MIN_PIPELINE_STAGES);
-       tape->max_pipeline =
-               min(tape->max_stages * 2, IDETAPE_MAX_PIPELINE_STAGES);
-       if (tape->max_stages == 0) {
-               tape->max_stages   = 1;
-               tape->min_pipeline = 1;
-               tape->max_pipeline = 1;
-       }
-
-       t1 = (tape->stage_size * HZ) / (speed * 1000);
-       tmid = (*(u16 *)&tape->caps[16] * 32 * HZ) / (speed * 125);
-       tn = (IDETAPE_FIFO_THRESHOLD * tape->stage_size * HZ) / (speed * 1000);
-
-       if (tape->max_stages)
-               t = tn;
-       else
-               t = t1;
+       t = (IDETAPE_FIFO_THRESHOLD * tape->buffer_size * HZ) / (speed * 1000);
 
        /*
         * Ensure that the number we got makes sense; limit it within
@@ -3532,11 +2749,10 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
                                min_t(unsigned long, t, IDETAPE_DSC_RW_MAX),
                                IDETAPE_DSC_RW_MIN);
        printk(KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, "
-               "%dkB pipeline, %lums tDSC%s\n",
+               "%lums tDSC%s\n",
                drive->name, tape->name, *(u16 *)&tape->caps[14],
-               (*(u16 *)&tape->caps[16] * 512) / tape->stage_size,
-               tape->stage_size / 1024,
-               tape->max_stages * tape->stage_size / 1024,
+               (*(u16 *)&tape->caps[16] * 512) / tape->buffer_size,
+               tape->buffer_size / 1024,
                tape->best_dsc_rw_freq * 1000 / HZ,
                drive->using_dma ? ", DMA":"");
 
@@ -3560,7 +2776,7 @@ static void ide_tape_release(struct kref *kref)
        ide_drive_t *drive = tape->drive;
        struct gendisk *g = tape->disk;
 
-       BUG_ON(tape->first_stage != NULL || tape->merge_stage_size);
+       BUG_ON(tape->merge_bh_size);
 
        drive->dsc_overlap = 0;
        drive->driver_data = NULL;
index 155cc904f4eb056948745060c3e704d6a7698d29..9f9ad9fb6b89b3f7159cabe4bfd33d06790ae7c7 100644 (file)
@@ -36,6 +36,7 @@
 void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
 {
        ide_hwif_t *hwif = drive->hwif;
+       struct ide_io_ports *io_ports = &hwif->io_ports;
        struct ide_taskfile *tf = &task->tf;
        u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
 
@@ -59,34 +60,33 @@ void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
                SELECT_MASK(drive, 0);
 
        if (task->tf_flags & IDE_TFLAG_OUT_DATA)
-               hwif->OUTW((tf->hob_data << 8) | tf->data,
-                          hwif->io_ports[IDE_DATA_OFFSET]);
+               hwif->OUTW((tf->hob_data << 8) | tf->data, io_ports->data_addr);
 
        if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
-               hwif->OUTB(tf->hob_feature, hwif->io_ports[IDE_FEATURE_OFFSET]);
+               hwif->OUTB(tf->hob_feature, io_ports->feature_addr);
        if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
-               hwif->OUTB(tf->hob_nsect, hwif->io_ports[IDE_NSECTOR_OFFSET]);
+               hwif->OUTB(tf->hob_nsect, io_ports->nsect_addr);
        if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
-               hwif->OUTB(tf->hob_lbal, hwif->io_ports[IDE_SECTOR_OFFSET]);
+               hwif->OUTB(tf->hob_lbal, io_ports->lbal_addr);
        if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
-               hwif->OUTB(tf->hob_lbam, hwif->io_ports[IDE_LCYL_OFFSET]);
+               hwif->OUTB(tf->hob_lbam, io_ports->lbam_addr);
        if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
-               hwif->OUTB(tf->hob_lbah, hwif->io_ports[IDE_HCYL_OFFSET]);
+               hwif->OUTB(tf->hob_lbah, io_ports->lbah_addr);
 
        if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
-               hwif->OUTB(tf->feature, hwif->io_ports[IDE_FEATURE_OFFSET]);
+               hwif->OUTB(tf->feature, io_ports->feature_addr);
        if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
-               hwif->OUTB(tf->nsect, hwif->io_ports[IDE_NSECTOR_OFFSET]);
+               hwif->OUTB(tf->nsect, io_ports->nsect_addr);
        if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
-               hwif->OUTB(tf->lbal, hwif->io_ports[IDE_SECTOR_OFFSET]);
+               hwif->OUTB(tf->lbal, io_ports->lbal_addr);
        if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
-               hwif->OUTB(tf->lbam, hwif->io_ports[IDE_LCYL_OFFSET]);
+               hwif->OUTB(tf->lbam, io_ports->lbam_addr);
        if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
-               hwif->OUTB(tf->lbah, hwif->io_ports[IDE_HCYL_OFFSET]);
+               hwif->OUTB(tf->lbah, io_ports->lbah_addr);
 
        if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
                hwif->OUTB((tf->device & HIHI) | drive->select.all,
-                          hwif->io_ports[IDE_SELECT_OFFSET]);
+                          io_ports->device_addr);
 }
 
 int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
@@ -135,6 +135,7 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
        ide_hwif_t *hwif        = HWIF(drive);
        struct ide_taskfile *tf = &task->tf;
        ide_handler_t *handler = NULL;
+       const struct ide_dma_ops *dma_ops = hwif->dma_ops;
 
        if (task->data_phase == TASKFILE_MULTI_IN ||
            task->data_phase == TASKFILE_MULTI_OUT) {
@@ -154,8 +155,7 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
        switch (task->data_phase) {
        case TASKFILE_MULTI_OUT:
        case TASKFILE_OUT:
-               hwif->OUTBSYNC(drive, tf->command,
-                              hwif->io_ports[IDE_COMMAND_OFFSET]);
+               hwif->OUTBSYNC(drive, tf->command, hwif->io_ports.command_addr);
                ndelay(400);    /* FIXME */
                return pre_task_out_intr(drive, task->rq);
        case TASKFILE_MULTI_IN:
@@ -178,10 +178,10 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
                return ide_started;
        default:
                if (task_dma_ok(task) == 0 || drive->using_dma == 0 ||
-                   hwif->dma_setup(drive))
+                   dma_ops->dma_setup(drive))
                        return ide_stopped;
-               hwif->dma_exec_cmd(drive, tf->command);
-               hwif->dma_start(drive);
+               dma_ops->dma_exec_cmd(drive, tf->command);
+               dma_ops->dma_start(drive);
                return ide_started;
        }
 }
@@ -455,7 +455,7 @@ static ide_startstop_t task_in_intr(ide_drive_t *drive)
 
        /* Error? */
        if (stat & ERR_STAT)
-               return task_error(drive, rq, __FUNCTION__, stat);
+               return task_error(drive, rq, __func__, stat);
 
        /* Didn't want any data? Odd. */
        if (!(stat & DRQ_STAT))
@@ -467,7 +467,7 @@ static ide_startstop_t task_in_intr(ide_drive_t *drive)
        if (!hwif->nleft) {
                stat = wait_drive_not_busy(drive);
                if (!OK_STAT(stat, 0, BAD_STAT))
-                       return task_error(drive, rq, __FUNCTION__, stat);
+                       return task_error(drive, rq, __func__, stat);
                task_end_request(drive, rq, stat);
                return ide_stopped;
        }
@@ -488,11 +488,11 @@ static ide_startstop_t task_out_intr (ide_drive_t *drive)
        u8 stat = ide_read_status(drive);
 
        if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
-               return task_error(drive, rq, __FUNCTION__, stat);
+               return task_error(drive, rq, __func__, stat);
 
        /* Deal with unexpected ATA data phase. */
        if (((stat & DRQ_STAT) == 0) ^ !hwif->nleft)
-               return task_error(drive, rq, __FUNCTION__, stat);
+               return task_error(drive, rq, __func__, stat);
 
        if (!hwif->nleft) {
                task_end_request(drive, rq, stat);
@@ -675,7 +675,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
                                /* (hs): give up if multcount is not set */
                                printk(KERN_ERR "%s: %s Multimode Write " \
                                        "multcount is not set\n",
-                                       drive->name, __FUNCTION__);
+                                       drive->name, __func__);
                                err = -EPERM;
                                goto abort;
                        }
@@ -692,7 +692,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
                                /* (hs): give up if multcount is not set */
                                printk(KERN_ERR "%s: %s Multimode Read failure " \
                                        "multcount is not set\n",
-                                       drive->name, __FUNCTION__);
+                                       drive->name, __func__);
                                err = -EPERM;
                                goto abort;
                        }
index 917c72dcd33dccc806c42c20d9662750ebe52b89..999584c03d9766d8bd1a9b083167e23e2cb39965 100644 (file)
@@ -94,19 +94,8 @@ DEFINE_MUTEX(ide_cfg_mtx);
 
 int noautodma = 0;
 
-#ifdef CONFIG_BLK_DEV_IDEACPI
-int ide_noacpi = 0;
-int ide_noacpitfs = 1;
-int ide_noacpionboot = 1;
-#endif
-
-/*
- * This is declared extern in ide.h, for access by other IDE modules:
- */
 ide_hwif_t ide_hwifs[MAX_HWIFS];       /* master data repository */
 
-EXPORT_SYMBOL(ide_hwifs);
-
 static void ide_port_init_devices_data(ide_hwif_t *);
 
 /*
@@ -232,117 +221,6 @@ static int ide_system_bus_speed(void)
        return pci_dev_present(pci_default) ? 33 : 50;
 }
 
-ide_hwif_t * ide_find_port(unsigned long base)
-{
-       ide_hwif_t *hwif;
-       int i;
-
-       for (i = 0; i < MAX_HWIFS; i++) {
-               hwif = &ide_hwifs[i];
-               if (hwif->io_ports[IDE_DATA_OFFSET] == base)
-                       goto found;
-       }
-
-       for (i = 0; i < MAX_HWIFS; i++) {
-               hwif = &ide_hwifs[i];
-               if (hwif->chipset == ide_unknown)
-                       goto found;
-       }
-
-       hwif = NULL;
-found:
-       return hwif;
-}
-
-EXPORT_SYMBOL_GPL(ide_find_port);
-
-static struct resource* hwif_request_region(ide_hwif_t *hwif,
-                                           unsigned long addr, int num)
-{
-       struct resource *res = request_region(addr, num, hwif->name);
-
-       if (!res)
-               printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
-                               hwif->name, addr, addr+num-1);
-       return res;
-}
-
-/**
- *     ide_hwif_request_regions - request resources for IDE
- *     @hwif: interface to use
- *
- *     Requests all the needed resources for an interface.
- *     Right now core IDE code does this work which is deeply wrong.
- *     MMIO leaves it to the controller driver,
- *     PIO will migrate this way over time.
- */
-
-int ide_hwif_request_regions(ide_hwif_t *hwif)
-{
-       unsigned long addr;
-       unsigned int i;
-
-       if (hwif->mmio)
-               return 0;
-       addr = hwif->io_ports[IDE_CONTROL_OFFSET];
-       if (addr && !hwif_request_region(hwif, addr, 1))
-               goto control_region_busy;
-       hwif->straight8 = 0;
-       addr = hwif->io_ports[IDE_DATA_OFFSET];
-       if ((addr | 7) == hwif->io_ports[IDE_STATUS_OFFSET]) {
-               if (!hwif_request_region(hwif, addr, 8))
-                       goto data_region_busy;
-               hwif->straight8 = 1;
-               return 0;
-       }
-       for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-               addr = hwif->io_ports[i];
-               if (!hwif_request_region(hwif, addr, 1)) {
-                       while (--i)
-                               release_region(addr, 1);
-                       goto data_region_busy;
-               }
-       }
-       return 0;
-
-data_region_busy:
-       addr = hwif->io_ports[IDE_CONTROL_OFFSET];
-       if (addr)
-               release_region(addr, 1);
-control_region_busy:
-       /* If any errors are return, we drop the hwif interface. */
-       return -EBUSY;
-}
-
-/**
- *     ide_hwif_release_regions - free IDE resources
- *
- *     Note that we only release the standard ports,
- *     and do not even try to handle any extra ports
- *     allocated for weird IDE interface chipsets.
- *
- *     Note also that we don't yet handle mmio resources here. More
- *     importantly our caller should be doing this so we need to 
- *     restructure this as a helper function for drivers.
- */
-
-void ide_hwif_release_regions(ide_hwif_t *hwif)
-{
-       u32 i = 0;
-
-       if (hwif->mmio)
-               return;
-       if (hwif->io_ports[IDE_CONTROL_OFFSET])
-               release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
-       if (hwif->straight8) {
-               release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);
-               return;
-       }
-       for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
-               if (hwif->io_ports[i])
-                       release_region(hwif->io_ports[i], 1);
-}
-
 void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
 {
        ide_hwgroup_t *hwgroup = hwif->hwgroup;
@@ -409,7 +287,7 @@ EXPORT_SYMBOL_GPL(ide_port_unregister_devices);
 
 /**
  *     ide_unregister          -       free an IDE interface
- *     @index: index of interface (will change soon to a pointer)
+ *     @hwif: IDE interface
  *
  *     Perform the final unregister of an IDE interface. At the moment
  *     we don't refcount interfaces so this will also get split up.
@@ -429,19 +307,16 @@ EXPORT_SYMBOL_GPL(ide_port_unregister_devices);
  *     This is raving bonkers.
  */
 
-void ide_unregister(unsigned int index)
+void ide_unregister(ide_hwif_t *hwif)
 {
-       ide_hwif_t *hwif, *g;
+       ide_hwif_t *g;
        ide_hwgroup_t *hwgroup;
        int irq_count = 0;
 
-       BUG_ON(index >= MAX_HWIFS);
-
        BUG_ON(in_interrupt());
        BUG_ON(irqs_disabled());
        mutex_lock(&ide_cfg_mtx);
        spin_lock_irq(&ide_lock);
-       hwif = &ide_hwifs[index];
        if (!hwif->present)
                goto abort;
        __ide_port_unregister_devices(hwif);
@@ -479,12 +354,10 @@ void ide_unregister(unsigned int index)
        spin_lock_irq(&ide_lock);
 
        if (hwif->dma_base)
-               (void)ide_release_dma(hwif);
-
-       ide_hwif_release_regions(hwif);
+               ide_release_dma_engine(hwif);
 
        /* restore hwif data to pristine status */
-       ide_init_port_data(hwif, index);
+       ide_init_port_data(hwif, hwif->index);
 
 abort:
        spin_unlock_irq(&ide_lock);
@@ -495,9 +368,8 @@ EXPORT_SYMBOL(ide_unregister);
 
 void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
 {
-       memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports));
+       memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports));
        hwif->irq = hw->irq;
-       hwif->noprobe = 0;
        hwif->chipset = hw->chipset;
        hwif->gendev.parent = hw->dev;
        hwif->ack_intr = hw->ack_intr;
@@ -588,7 +460,7 @@ int set_using_dma(ide_drive_t *drive, int arg)
        if (!drive->id || !(drive->id->capability & 1))
                goto out;
 
-       if (hwif->dma_host_set == NULL)
+       if (hwif->dma_ops == NULL)
                goto out;
 
        err = -EBUSY;
@@ -627,11 +499,14 @@ out:
 int set_pio_mode(ide_drive_t *drive, int arg)
 {
        struct request rq;
+       ide_hwif_t *hwif = drive->hwif;
+       const struct ide_port_ops *port_ops = hwif->port_ops;
 
        if (arg < 0 || arg > 255)
                return -EINVAL;
 
-       if (drive->hwif->set_pio_mode == NULL)
+       if (port_ops == NULL || port_ops->set_pio_mode == NULL ||
+           (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
                return -ENOSYS;
 
        if (drive->special.b.set_tune)
@@ -953,16 +828,6 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m
        return 0;       /* zero = nothing matched */
 }
 
-extern int probe_ali14xx;
-extern int probe_umc8672;
-extern int probe_dtc2278;
-extern int probe_ht6560b;
-extern int probe_qd65xx;
-extern int cmd640_vlb;
-extern int probe_4drives;
-
-static int __initdata is_chipset_set;
-
 /*
  * ide_setup() gets called VERY EARLY during initialization,
  * to handle kernel "command line" strings beginning with "hdx=" or "ide".
@@ -971,14 +836,12 @@ static int __initdata is_chipset_set;
  */
 static int __init ide_setup(char *s)
 {
-       int i, vals[3];
        ide_hwif_t *hwif;
        ide_drive_t *drive;
        unsigned int hw, unit;
+       int vals[3];
        const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1);
-       const char max_hwif  = '0' + (MAX_HWIFS - 1);
 
-       
        if (strncmp(s,"hd",2) == 0 && s[2] == '=')      /* hd= is for hd.c   */
                return 0;                               /* driver and not us */
 
@@ -994,7 +857,7 @@ static int __init ide_setup(char *s)
 
                printk(" : Enabled support for IDE doublers\n");
                ide_doubler = 1;
-               return 1;
+               goto obsolete_option;
        }
 #endif /* CONFIG_BLK_DEV_IDEDOUBLER */
 
@@ -1008,17 +871,17 @@ static int __init ide_setup(char *s)
        if (!strcmp(s, "ide=noacpi")) {
                //printk(" : Disable IDE ACPI support.\n");
                ide_noacpi = 1;
-               return 1;
+               goto obsolete_option;
        }
        if (!strcmp(s, "ide=acpigtf")) {
                //printk(" : Enable IDE ACPI _GTF support.\n");
-               ide_noacpitfs = 0;
-               return 1;
+               ide_acpigtf = 1;
+               goto obsolete_option;
        }
        if (!strcmp(s, "ide=acpionboot")) {
                //printk(" : Call IDE ACPI methods on boot.\n");
-               ide_noacpionboot = 0;
-               return 1;
+               ide_acpionboot = 1;
+               goto obsolete_option;
        }
 #endif /* CONFIG_BLK_DEV_IDEACPI */
 
@@ -1028,7 +891,7 @@ static int __init ide_setup(char *s)
        if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {
                const char *hd_words[] = {
                        "none", "noprobe", "nowerr", "cdrom", "nodma",
-                       "autotune", "noautotune", "-8", "-9", "-10",
+                       "-6", "-7", "-8", "-9", "-10",
                        "noflush", "remap", "remap63", "scsi", NULL };
                unit = s[2] - 'a';
                hw   = unit / MAX_DRIVES;
@@ -1043,30 +906,22 @@ static int __init ide_setup(char *s)
                        case -1: /* "none" */
                        case -2: /* "noprobe" */
                                drive->noprobe = 1;
-                               goto done;
+                               goto obsolete_option;
                        case -3: /* "nowerr" */
                                drive->bad_wstat = BAD_R_STAT;
-                               hwif->noprobe = 0;
-                               goto done;
+                               goto obsolete_option;
                        case -4: /* "cdrom" */
                                drive->present = 1;
                                drive->media = ide_cdrom;
                                /* an ATAPI device ignores DRDY */
                                drive->ready_stat = 0;
-                               hwif->noprobe = 0;
-                               goto done;
+                               goto obsolete_option;
                        case -5: /* nodma */
                                drive->nodma = 1;
-                               goto done;
-                       case -6: /* "autotune" */
-                               drive->autotune = IDE_TUNE_AUTO;
-                               goto obsolete_option;
-                       case -7: /* "noautotune" */
-                               drive->autotune = IDE_TUNE_NOAUTO;
                                goto obsolete_option;
                        case -11: /* noflush */
                                drive->noflush = 1;
-                               goto done;
+                               goto obsolete_option;
                        case -12: /* "remap" */
                                drive->remap_0_to_1 = 1;
                                goto obsolete_option;
@@ -1084,8 +939,7 @@ static int __init ide_setup(char *s)
                                drive->sect     = drive->bios_sect = vals[2];
                                drive->present  = 1;
                                drive->forced_geom = 1;
-                               hwif->noprobe = 0;
-                               goto done;
+                               goto obsolete_option;
                        default:
                                goto bad_option;
                }
@@ -1103,126 +957,15 @@ static int __init ide_setup(char *s)
                        idebus_parameter = vals[0];
                } else
                        printk(" -- BAD BUS SPEED! Expected value from 20 to 66");
-               goto done;
+               goto obsolete_option;
        }
-       /*
-        * Look for interface options:  "idex="
-        */
-       if (s[3] >= '0' && s[3] <= max_hwif) {
-               /*
-                * Be VERY CAREFUL changing this: note hardcoded indexes below
-                * (-8, -9, -10) are reserved to ease the hardcoding.
-                */
-               static const char *ide_words[] = {
-                       "minus1", "serialize", "minus3", "minus4",
-                       "reset", "minus6", "ata66", "minus8", "minus9",
-                       "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb",
-                       "dtc2278", "umc8672", "ali14xx", NULL };
-
-               hw = s[3] - '0';
-               hwif = &ide_hwifs[hw];
-               i = match_parm(&s[4], ide_words, vals, 3);
 
-               /*
-                * Cryptic check to ensure chipset not already set for hwif.
-                * Note: we can't depend on hwif->chipset here.
-                */
-               if (i >= -18 && i <= -11) {
-                       /* chipset already specified */
-                       if (is_chipset_set)
-                               goto bad_option;
-                       /* these drivers are for "ide0=" only */
-                       if (hw != 0)
-                               goto bad_hwif;
-                       is_chipset_set = 1;
-                       printk("\n");
-               }
-
-               switch (i) {
-#ifdef CONFIG_BLK_DEV_ALI14XX
-                       case -17: /* "ali14xx" */
-                               probe_ali14xx = 1;
-                               goto obsolete_option;
-#endif
-#ifdef CONFIG_BLK_DEV_UMC8672
-                       case -16: /* "umc8672" */
-                               probe_umc8672 = 1;
-                               goto obsolete_option;
-#endif
-#ifdef CONFIG_BLK_DEV_DTC2278
-                       case -15: /* "dtc2278" */
-                               probe_dtc2278 = 1;
-                               goto obsolete_option;
-#endif
-#ifdef CONFIG_BLK_DEV_CMD640
-                       case -14: /* "cmd640_vlb" */
-                               cmd640_vlb = 1;
-                               goto obsolete_option;
-#endif
-#ifdef CONFIG_BLK_DEV_HT6560B
-                       case -13: /* "ht6560b" */
-                               probe_ht6560b = 1;
-                               goto obsolete_option;
-#endif
-#ifdef CONFIG_BLK_DEV_QD65XX
-                       case -12: /* "qd65xx" */
-                               probe_qd65xx = 1;
-                               goto obsolete_option;
-#endif
-#ifdef CONFIG_BLK_DEV_4DRIVES
-                       case -11: /* "four" drives on one set of ports */
-                               probe_4drives = 1;
-                               goto obsolete_option;
-#endif
-                       case -10: /* minus10 */
-                       case -9: /* minus9 */
-                       case -8: /* minus8 */
-                       case -6:
-                       case -4:
-                       case -3:
-                               goto bad_option;
-                       case -7: /* ata66 */
-#ifdef CONFIG_BLK_DEV_IDEPCI
-                               /*
-                                * Use ATA_CBL_PATA40_SHORT so drive side
-                                * cable detection is also overriden.
-                                */
-                               hwif->cbl = ATA_CBL_PATA40_SHORT;
-                               goto obsolete_option;
-#else
-                               goto bad_hwif;
-#endif
-                       case -5: /* "reset" */
-                               hwif->reset = 1;
-                               goto obsolete_option;
-                       case -2: /* "serialize" */
-                               hwif->mate = &ide_hwifs[hw^1];
-                               hwif->mate->mate = hwif;
-                               hwif->serialized = hwif->mate->serialized = 1;
-                               goto obsolete_option;
-
-                       case -1:
-                       case 0:
-                       case 1:
-                       case 2:
-                       case 3:
-                               goto bad_option;
-                       default:
-                               printk(" -- SUPPORT NOT CONFIGURED IN THIS KERNEL\n");
-                               return 1;
-               }
-       }
 bad_option:
        printk(" -- BAD OPTION\n");
        return 1;
 obsolete_option:
        printk(" -- OBSOLETE OPTION, WILL BE REMOVED SOON!\n");
        return 1;
-bad_hwif:
-       printk("-- NOT SUPPORTED ON ide%d", hw);
-done:
-       printk("\n");
-       return 1;
 }
 
 EXPORT_SYMBOL(ide_lock);
@@ -1358,6 +1101,185 @@ static void ide_port_class_release(struct device *portdev)
        put_device(&hwif->gendev);
 }
 
+int ide_vlb_clk;
+EXPORT_SYMBOL_GPL(ide_vlb_clk);
+
+module_param_named(vlb_clock, ide_vlb_clk, int, 0);
+MODULE_PARM_DESC(vlb_clock, "VLB clock frequency (in MHz)");
+
+int ide_pci_clk;
+EXPORT_SYMBOL_GPL(ide_pci_clk);
+
+module_param_named(pci_clock, ide_pci_clk, int, 0);
+MODULE_PARM_DESC(pci_clock, "PCI bus clock frequency (in MHz)");
+
+static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp)
+{
+       int a, b, i, j = 1;
+       unsigned int *dev_param_mask = (unsigned int *)kp->arg;
+
+       if (sscanf(s, "%d.%d:%d", &a, &b, &j) != 3 &&
+           sscanf(s, "%d.%d", &a, &b) != 2)
+               return -EINVAL;
+
+       i = a * MAX_DRIVES + b;
+
+       if (i >= MAX_HWIFS * MAX_DRIVES || j < 0 || j > 1)
+               return -EINVAL;
+
+       if (j)
+               *dev_param_mask |= (1 << i);
+       else
+               *dev_param_mask &= (1 << i);
+
+       return 0;
+}
+
+static unsigned int ide_nodma;
+
+module_param_call(nodma, ide_set_dev_param_mask, NULL, &ide_nodma, 0);
+MODULE_PARM_DESC(nodma, "disallow DMA for a device");
+
+static unsigned int ide_noflush;
+
+module_param_call(noflush, ide_set_dev_param_mask, NULL, &ide_noflush, 0);
+MODULE_PARM_DESC(noflush, "disable flush requests for a device");
+
+static unsigned int ide_noprobe;
+
+module_param_call(noprobe, ide_set_dev_param_mask, NULL, &ide_noprobe, 0);
+MODULE_PARM_DESC(noprobe, "skip probing for a device");
+
+static unsigned int ide_nowerr;
+
+module_param_call(nowerr, ide_set_dev_param_mask, NULL, &ide_nowerr, 0);
+MODULE_PARM_DESC(nowerr, "ignore the WRERR_STAT bit for a device");
+
+static unsigned int ide_cdroms;
+
+module_param_call(cdrom, ide_set_dev_param_mask, NULL, &ide_cdroms, 0);
+MODULE_PARM_DESC(cdrom, "force device as a CD-ROM");
+
+struct chs_geom {
+       unsigned int    cyl;
+       u8              head;
+       u8              sect;
+};
+
+static unsigned int ide_disks;
+static struct chs_geom ide_disks_chs[MAX_HWIFS * MAX_DRIVES];
+
+static int ide_set_disk_chs(const char *str, struct kernel_param *kp)
+{
+       int a, b, c = 0, h = 0, s = 0, i, j = 1;
+
+       if (sscanf(str, "%d.%d:%d,%d,%d", &a, &b, &c, &h, &s) != 5 &&
+           sscanf(str, "%d.%d:%d", &a, &b, &j) != 3)
+               return -EINVAL;
+
+       i = a * MAX_DRIVES + b;
+
+       if (i >= MAX_HWIFS * MAX_DRIVES || j < 0 || j > 1)
+               return -EINVAL;
+
+       if (c > INT_MAX || h > 255 || s > 255)
+               return -EINVAL;
+
+       if (j)
+               ide_disks |= (1 << i);
+       else
+               ide_disks &= (1 << i);
+
+       ide_disks_chs[i].cyl  = c;
+       ide_disks_chs[i].head = h;
+       ide_disks_chs[i].sect = s;
+
+       return 0;
+}
+
+module_param_call(chs, ide_set_disk_chs, NULL, NULL, 0);
+MODULE_PARM_DESC(chs, "force device as a disk (using CHS)");
+
+static void ide_dev_apply_params(ide_drive_t *drive)
+{
+       int i = drive->hwif->index * MAX_DRIVES + drive->select.b.unit;
+
+       if (ide_nodma & (1 << i)) {
+               printk(KERN_INFO "ide: disallowing DMA for %s\n", drive->name);
+               drive->nodma = 1;
+       }
+       if (ide_noflush & (1 << i)) {
+               printk(KERN_INFO "ide: disabling flush requests for %s\n",
+                                drive->name);
+               drive->noflush = 1;
+       }
+       if (ide_noprobe & (1 << i)) {
+               printk(KERN_INFO "ide: skipping probe for %s\n", drive->name);
+               drive->noprobe = 1;
+       }
+       if (ide_nowerr & (1 << i)) {
+               printk(KERN_INFO "ide: ignoring the WRERR_STAT bit for %s\n",
+                                drive->name);
+               drive->bad_wstat = BAD_R_STAT;
+       }
+       if (ide_cdroms & (1 << i)) {
+               printk(KERN_INFO "ide: forcing %s as a CD-ROM\n", drive->name);
+               drive->present = 1;
+               drive->media = ide_cdrom;
+               /* an ATAPI device ignores DRDY */
+               drive->ready_stat = 0;
+       }
+       if (ide_disks & (1 << i)) {
+               drive->cyl  = drive->bios_cyl  = ide_disks_chs[i].cyl;
+               drive->head = drive->bios_head = ide_disks_chs[i].head;
+               drive->sect = drive->bios_sect = ide_disks_chs[i].sect;
+               drive->forced_geom = 1;
+               printk(KERN_INFO "ide: forcing %s as a disk (%d/%d/%d)\n",
+                                drive->name,
+                                drive->cyl, drive->head, drive->sect);
+               drive->present = 1;
+               drive->media = ide_disk;
+               drive->ready_stat = READY_STAT;
+       }
+}
+
+static unsigned int ide_ignore_cable;
+
+static int ide_set_ignore_cable(const char *s, struct kernel_param *kp)
+{
+       int i, j = 1;
+
+       if (sscanf(s, "%d:%d", &i, &j) != 2 && sscanf(s, "%d", &i) != 1)
+               return -EINVAL;
+
+       if (i >= MAX_HWIFS || j < 0 || j > 1)
+               return -EINVAL;
+
+       if (j)
+               ide_ignore_cable |= (1 << i);
+       else
+               ide_ignore_cable &= (1 << i);
+
+       return 0;
+}
+
+module_param_call(ignore_cable, ide_set_ignore_cable, NULL, NULL, 0);
+MODULE_PARM_DESC(ignore_cable, "ignore cable detection");
+
+void ide_port_apply_params(ide_hwif_t *hwif)
+{
+       int i;
+
+       if (ide_ignore_cable & (1 << hwif->index)) {
+               printk(KERN_INFO "ide: ignoring cable detection for %s\n",
+                                hwif->name);
+               hwif->cbl = ATA_CBL_PATA40_SHORT;
+       }
+
+       for (i = 0; i < MAX_DRIVES; i++)
+               ide_dev_apply_params(&hwif->drives[i]);
+}
+
 /*
  * This is gets invoked once during initialization, to set *everything* up
  */
@@ -1424,11 +1346,6 @@ int __init init_module (void)
 
 void __exit cleanup_module (void)
 {
-       int index;
-
-       for (index = 0; index < MAX_HWIFS; ++index)
-               ide_unregister(index);
-
        proc_ide_destroy();
 
        class_destroy(ide_port_class);
index bc8b1f8de614d6aef0ae6ab5fd1beaacc13b05d8..90c65cf97448c3fc7e72313f7bb1dbfcd7e4e0fb 100644 (file)
@@ -49,6 +49,8 @@
 
 #include <asm/io.h>
 
+#define DRV_NAME "ali14xx"
+
 /* port addresses for auto-detection */
 #define ALI_NUM_PORTS 4
 static const int ports[ALI_NUM_PORTS] __initdata =
@@ -86,7 +88,7 @@ static u8 regOff;     /* output to base port to close registers */
 /*
  * Read a controller register.
  */
-static inline u8 inReg (u8 reg)
+static inline u8 inReg(u8 reg)
 {
        outb_p(reg, regPort);
        return inb(dataPort);
@@ -95,7 +97,7 @@ static inline u8 inReg (u8 reg)
 /*
  * Write a controller register.
  */
-static void outReg (u8 data, u8 reg)
+static void outReg(u8 data, u8 reg)
 {
        outb_p(reg, regPort);
        outb_p(data, dataPort);
@@ -114,7 +116,7 @@ static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
        int time1, time2;
        u8 param1, param2, param3, param4;
        unsigned long flags;
-       int bus_speed = system_bus_clock();
+       int bus_speed = ide_vlb_clk ? ide_vlb_clk : system_bus_clock();
 
        /* calculate timing, according to PIO mode */
        time1 = ide_pio_cycle_time(drive, pio);
@@ -143,7 +145,7 @@ static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
 /*
  * Auto-detect the IDE controller port.
  */
-static int __init findPort (void)
+static int __init findPort(void)
 {
        int i;
        u8 t;
@@ -175,7 +177,8 @@ static int __init findPort (void)
 /*
  * Initialize controller registers with default values.
  */
-static int __init initRegisters (void) {
+static int __init initRegisters(void)
+{
        const RegInitializer *p;
        u8 t;
        unsigned long flags;
@@ -191,17 +194,20 @@ static int __init initRegisters (void) {
        return t;
 }
 
+static const struct ide_port_ops ali14xx_port_ops = {
+       .set_pio_mode           = ali14xx_set_pio_mode,
+};
+
 static const struct ide_port_info ali14xx_port_info = {
+       .name                   = DRV_NAME,
        .chipset                = ide_ali14xx,
-       .host_flags             = IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE,
+       .port_ops               = &ali14xx_port_ops,
+       .host_flags             = IDE_HFLAG_NO_DMA,
        .pio_mask               = ATA_PIO4,
 };
 
 static int __init ali14xx_probe(void)
 {
-       static u8 idx[4] = { 0, 1, 0xff, 0xff };
-       hw_regs_t hw[2];
-
        printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n",
                          basePort, regOn);
 
@@ -211,26 +217,10 @@ static int __init ali14xx_probe(void)
                return 1;
        }
 
-       memset(&hw, 0, sizeof(hw));
-
-       ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
-       hw[0].irq = 14;
-
-       ide_std_init_ports(&hw[1], 0x170, 0x376);
-       hw[1].irq = 15;
-
-       ide_init_port_hw(&ide_hwifs[0], &hw[0]);
-       ide_init_port_hw(&ide_hwifs[1], &hw[1]);
-
-       ide_hwifs[0].set_pio_mode = &ali14xx_set_pio_mode;
-       ide_hwifs[1].set_pio_mode = &ali14xx_set_pio_mode;
-
-       ide_device_add(idx, &ali14xx_port_info);
-
-       return 0;
+       return ide_legacy_device_add(&ali14xx_port_info, 0);
 }
 
-int probe_ali14xx = 0;
+static int probe_ali14xx;
 
 module_param_named(probe, probe_ali14xx, bool, 0);
 MODULE_PARM_DESC(probe, "probe for ALI M14xx chipsets");
index fdd3791e465f0f5f028f58f907548b8cf7140cfe..5c730e4dd735b9c7f32b9111e037f86762768b88 100644 (file)
@@ -102,7 +102,7 @@ static int buddha_ack_intr(ide_hwif_t *hwif)
 {
     unsigned char ch;
 
-    ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
+    ch = z_readb(hwif->io_ports.irq_addr);
     if (!(ch & 0x80))
            return 0;
     return 1;
@@ -112,9 +112,9 @@ static int xsurf_ack_intr(ide_hwif_t *hwif)
 {
     unsigned char ch;
 
-    ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
+    ch = z_readb(hwif->io_ports.irq_addr);
     /* X-Surf needs a 0 written to IRQ register to ensure ISA bit A11 stays at 0 */
-    z_writeb(0, hwif->io_ports[IDE_IRQ_OFFSET]); 
+    z_writeb(0, hwif->io_ports.irq_addr);
     if (!(ch & 0x80))
            return 0;
     return 1;
@@ -128,13 +128,13 @@ static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base,
 
        memset(hw, 0, sizeof(*hw));
 
-       hw->io_ports[IDE_DATA_OFFSET] = base;
+       hw->io_ports.data_addr = base;
 
        for (i = 1; i < 8; i++)
-               hw->io_ports[i] = base + 2 + i * 4;
+               hw->io_ports_array[i] = base + 2 + i * 4;
 
-       hw->io_ports[IDE_CONTROL_OFFSET] = ctl;
-       hw->io_ports[IDE_IRQ_OFFSET] = irq_port;
+       hw->io_ports.ctl_addr = ctl;
+       hw->io_ports.irq_addr = irq_port;
 
        hw->irq = IRQ_AMIGA_PORTS;
        hw->ack_intr = ack_intr;
@@ -221,15 +221,13 @@ fail_base2:
 
                        buddha_setup_ports(&hw, base, ctl, irq_port, ack_intr);
 
-                       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+                       hwif = ide_find_port();
                        if (hwif) {
                                u8 index = hwif->index;
 
                                ide_init_port_data(hwif, index);
                                ide_init_port_hw(hwif, &hw);
 
-                               hwif->mmio = 1;
-
                                idx[i] = index;
                        }
                }
index 5f69cd2ea6f718da8e3e97f26e24603bf96b9153..af791a02a1201948334c22b2ad3079c2f69762cd 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <asm/io.h>
 
+#define DRV_NAME "dtc2278"
+
 /*
  * Changing this #undef to #define may solve start up problems in some systems.
  */
@@ -86,30 +88,26 @@ static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio)
        }
 }
 
+static const struct ide_port_ops dtc2278_port_ops = {
+       .set_pio_mode           = dtc2278_set_pio_mode,
+};
+
 static const struct ide_port_info dtc2278_port_info __initdata = {
+       .name                   = DRV_NAME,
        .chipset                = ide_dtc2278,
+       .port_ops               = &dtc2278_port_ops,
        .host_flags             = IDE_HFLAG_SERIALIZE |
                                  IDE_HFLAG_NO_UNMASK_IRQS |
                                  IDE_HFLAG_IO_32BIT |
                                  /* disallow ->io_32bit changes */
                                  IDE_HFLAG_NO_IO_32BIT |
-                                 IDE_HFLAG_NO_DMA |
-                                 IDE_HFLAG_NO_AUTOTUNE,
+                                 IDE_HFLAG_NO_DMA,
        .pio_mask               = ATA_PIO4,
 };
 
 static int __init dtc2278_probe(void)
 {
        unsigned long flags;
-       ide_hwif_t *hwif, *mate;
-       static u8 idx[4] = { 0, 1, 0xff, 0xff };
-       hw_regs_t hw[2];
-
-       hwif = &ide_hwifs[0];
-       mate = &ide_hwifs[1];
-
-       if (hwif->chipset != ide_unknown || mate->chipset != ide_unknown)
-               return 1;
 
        local_irq_save(flags);
        /*
@@ -129,25 +127,10 @@ static int __init dtc2278_probe(void)
 #endif
        local_irq_restore(flags);
 
-       memset(&hw, 0, sizeof(hw));
-
-       ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
-       hw[0].irq = 14;
-
-       ide_std_init_ports(&hw[1], 0x170, 0x376);
-       hw[1].irq = 15;
-
-       ide_init_port_hw(hwif, &hw[0]);
-       ide_init_port_hw(mate, &hw[1]);
-
-       hwif->set_pio_mode = &dtc2278_set_pio_mode;
-
-       ide_device_add(idx, &dtc2278_port_info);
-
-       return 0;
+       return ide_legacy_device_add(&dtc2278_port_info, 0);
 }
 
-int probe_dtc2278 = 0;
+static int probe_dtc2278;
 
 module_param_named(probe, probe_dtc2278, bool, 0);
 MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets");
index e950afa5939c545f2b615df5f785dbea89692296..56cdaa0eeea5325dee7c1441f9dcb00e51d1dce4 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/atariints.h>
 #include <asm/atari_stdma.h>
 
+#define DRV_NAME "falconide"
 
     /*
      *  Base of the IDE interface
@@ -49,12 +50,12 @@ static void __init falconide_setup_ports(hw_regs_t *hw)
 
        memset(hw, 0, sizeof(*hw));
 
-       hw->io_ports[IDE_DATA_OFFSET] = ATA_HD_BASE;
+       hw->io_ports.data_addr = ATA_HD_BASE;
 
        for (i = 1; i < 8; i++)
-               hw->io_ports[i] = ATA_HD_BASE + 1 + i * 4;
+               hw->io_ports_array[i] = ATA_HD_BASE + 1 + i * 4;
 
-       hw->io_ports[IDE_CONTROL_OFFSET] = ATA_HD_BASE + ATA_HD_CONTROL;
+       hw->io_ports.ctl_addr = ATA_HD_BASE + ATA_HD_CONTROL;
 
        hw->irq = IRQ_MFP_IDE;
        hw->ack_intr = NULL;
@@ -74,9 +75,14 @@ static int __init falconide_init(void)
 
        printk(KERN_INFO "ide: Falcon IDE controller\n");
 
+       if (!request_mem_region(ATA_HD_BASE, 0x40, DRV_NAME)) {
+               printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
+               return -EBUSY;
+       }
+
        falconide_setup_ports(&hw);
 
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif) {
                u8 index = hwif->index;
                u8 idx[4] = { index, 0xff, 0xff, 0xff };
index e3b4638cc88389e85ade16a074401a6b74d256e4..a9c2593a898c30a1e39e2d4b910e73e9ae29817e 100644 (file)
@@ -63,6 +63,8 @@
 #define GAYLE_HAS_CONTROL_REG  (!ide_doubler)
 #define GAYLE_IDEREG_SIZE      (ide_doubler ? 0x1000 : 0x2000)
 int ide_doubler = 0;   /* support IDE doublers? */
+module_param_named(doubler, ide_doubler, bool, 0);
+MODULE_PARM_DESC(doubler, "enable support for IDE doublers");
 #endif /* CONFIG_BLK_DEV_IDEDOUBLER */
 
 
@@ -74,7 +76,7 @@ static int gayle_ack_intr_a4000(ide_hwif_t *hwif)
 {
     unsigned char ch;
 
-    ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
+    ch = z_readb(hwif->io_ports.irq_addr);
     if (!(ch & GAYLE_IRQ_IDE))
        return 0;
     return 1;
@@ -84,11 +86,11 @@ static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
 {
     unsigned char ch;
 
-    ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
+    ch = z_readb(hwif->io_ports.irq_addr);
     if (!(ch & GAYLE_IRQ_IDE))
        return 0;
-    (void)z_readb(hwif->io_ports[IDE_STATUS_OFFSET]);
-    z_writeb(0x7c, hwif->io_ports[IDE_IRQ_OFFSET]);
+    (void)z_readb(hwif->io_ports.status_addr);
+    z_writeb(0x7c, hwif->io_ports.irq_addr);
     return 1;
 }
 
@@ -100,13 +102,13 @@ static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base,
 
        memset(hw, 0, sizeof(*hw));
 
-       hw->io_ports[IDE_DATA_OFFSET] = base;
+       hw->io_ports.data_addr = base;
 
        for (i = 1; i < 8; i++)
-               hw->io_ports[i] = base + 2 + i * 4;
+               hw->io_ports_array[i] = base + 2 + i * 4;
 
-       hw->io_ports[IDE_CONTROL_OFFSET] = ctl;
-       hw->io_ports[IDE_IRQ_OFFSET] = irq_port;
+       hw->io_ports.ctl_addr = ctl;
+       hw->io_ports.irq_addr = irq_port;
 
        hw->irq = IRQ_AMIGA_PORTS;
        hw->ack_intr = ack_intr;
@@ -175,15 +177,13 @@ found:
 
        gayle_setup_ports(&hw, base, ctrlport, irqport, ack_intr);
 
-       hwif = ide_find_port(base);
+       hwif = ide_find_port();
        if (hwif) {
            u8 index = hwif->index;
 
            ide_init_port_data(hwif, index);
            ide_init_port_hw(hwif, &hw);
 
-           hwif->mmio = 1;
-
            idx[i] = index;
        } else
            release_mem_region(res_start, res_n);
index 0b0d867319278af5e652d1310f887f0dafc915fa..abdedf56643eb16f9daaa85caa05d41e79a1746a 100644 (file)
@@ -122,12 +122,12 @@ static int hd_error;
  *  This struct defines the HD's and their types.
  */
 struct hd_i_struct {
-       unsigned int head,sect,cyl,wpcom,lzone,ctl;
+       unsigned int head, sect, cyl, wpcom, lzone, ctl;
        int unit;
        int recalibrate;
        int special_op;
 };
-       
+
 #ifdef HD_TYPE
 static struct hd_i_struct hd_info[] = { HD_TYPE };
 static int NR_HD = ARRAY_SIZE(hd_info);
@@ -168,7 +168,7 @@ unsigned long read_timer(void)
 
        spin_lock_irqsave(&i8253_lock, flags);
        t = jiffies * 11932;
-       outb_p(0, 0x43);
+       outb_p(0, 0x43);
        i = inb_p(0x40);
        i |= inb(0x40) << 8;
        spin_unlock_irqrestore(&i8253_lock, flags);
@@ -183,7 +183,7 @@ static void __init hd_setup(char *str, int *ints)
        if (ints[0] != 3)
                return;
        if (hd_info[0].head != 0)
-               hdind=1;
+               hdind = 1;
        hd_info[hdind].head = ints[2];
        hd_info[hdind].sect = ints[3];
        hd_info[hdind].cyl = ints[1];
@@ -193,7 +193,7 @@ static void __init hd_setup(char *str, int *ints)
        NR_HD = hdind+1;
 }
 
-static void dump_status (const char *msg, unsigned int stat)
+static void dump_status(const char *msg, unsigned int stat)
 {
        char *name = "hd?";
        if (CURRENT)
@@ -291,7 +291,6 @@ static int controller_ready(unsigned int drive, unsigned int head)
        return 0;
 }
 
-               
 static void hd_out(struct hd_i_struct *disk,
                   unsigned int nsect,
                   unsigned int sect,
@@ -313,15 +312,15 @@ static void hd_out(struct hd_i_struct *disk,
                return;
        }
        SET_HANDLER(intr_addr);
-       outb_p(disk->ctl,HD_CMD);
-       port=HD_DATA;
-       outb_p(disk->wpcom>>2,++port);
-       outb_p(nsect,++port);
-       outb_p(sect,++port);
-       outb_p(cyl,++port);
-       outb_p(cyl>>8,++port);
-       outb_p(0xA0|(disk->unit<<4)|head,++port);
-       outb_p(cmd,++port);
+       outb_p(disk->ctl, HD_CMD);
+       port = HD_DATA;
+       outb_p(disk->wpcom >> 2, ++port);
+       outb_p(nsect, ++port);
+       outb_p(sect, ++port);
+       outb_p(cyl, ++port);
+       outb_p(cyl >> 8, ++port);
+       outb_p(0xA0 | (disk->unit << 4) | head, ++port);
+       outb_p(cmd, ++port);
 }
 
 static void hd_request (void);
@@ -344,14 +343,14 @@ static void reset_controller(void)
 {
        int     i;
 
-       outb_p(4,HD_CMD);
-       for(i = 0; i < 1000; i++) barrier();
-       outb_p(hd_info[0].ctl & 0x0f,HD_CMD);
-       for(i = 0; i < 1000; i++) barrier();
+       outb_p(4, HD_CMD);
+       for (i = 0; i < 1000; i++) barrier();
+       outb_p(hd_info[0].ctl & 0x0f, HD_CMD);
+       for (i = 0; i < 1000; i++) barrier();
        if (drive_busy())
                printk("hd: controller still busy\n");
        else if ((hd_error = inb(HD_ERROR)) != 1)
-               printk("hd: controller reset failed: %02x\n",hd_error);
+               printk("hd: controller reset failed: %02x\n", hd_error);
 }
 
 static void reset_hd(void)
@@ -371,8 +370,8 @@ repeat:
        if (++i < NR_HD) {
                struct hd_i_struct *disk = &hd_info[i];
                disk->special_op = disk->recalibrate = 1;
-               hd_out(disk,disk->sect,disk->sect,disk->head-1,
-                       disk->cyl,WIN_SPECIFY,&reset_hd);
+               hd_out(disk, disk->sect, disk->sect, disk->head-1,
+                       disk->cyl, WIN_SPECIFY, &reset_hd);
                if (reset)
                        goto repeat;
        } else
@@ -393,7 +392,7 @@ static void unexpected_hd_interrupt(void)
        unsigned int stat = inb_p(HD_STATUS);
 
        if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) {
-               dump_status ("unexpected interrupt", stat);
+               dump_status("unexpected interrupt", stat);
                SET_TIMER;
        }
 }
@@ -453,7 +452,7 @@ static void read_intr(void)
        return;
 ok_to_read:
        req = CURRENT;
-       insw(HD_DATA,req->buffer,256);
+       insw(HD_DATA, req->buffer, 256);
        req->sector++;
        req->buffer += 512;
        req->errors = 0;
@@ -507,7 +506,7 @@ ok_to_write:
                end_request(req, 1);
        if (i > 0) {
                SET_HANDLER(&write_intr);
-               outsw(HD_DATA,req->buffer,256);
+               outsw(HD_DATA, req->buffer, 256);
                local_irq_enable();
        } else {
 #if (HD_DELAY > 0)
@@ -560,11 +559,11 @@ static int do_special_op(struct hd_i_struct *disk, struct request *req)
 {
        if (disk->recalibrate) {
                disk->recalibrate = 0;
-               hd_out(disk,disk->sect,0,0,0,WIN_RESTORE,&recal_intr);
+               hd_out(disk, disk->sect, 0, 0, 0, WIN_RESTORE, &recal_intr);
                return reset;
        }
        if (disk->head > 16) {
-               printk ("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name);
+               printk("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name);
                end_request(req, 0);
        }
        disk->special_op = 0;
@@ -633,19 +632,21 @@ repeat:
        if (blk_fs_request(req)) {
                switch (rq_data_dir(req)) {
                case READ:
-                       hd_out(disk,nsect,sec,head,cyl,WIN_READ,&read_intr);
+                       hd_out(disk, nsect, sec, head, cyl, WIN_READ,
+                               &read_intr);
                        if (reset)
                                goto repeat;
                        break;
                case WRITE:
-                       hd_out(disk,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
+                       hd_out(disk, nsect, sec, head, cyl, WIN_WRITE,
+                               &write_intr);
                        if (reset)
                                goto repeat;
                        if (wait_DRQ()) {
                                bad_rw_intr();
                                goto repeat;
                        }
-                       outsw(HD_DATA,req->buffer,256);
+                       outsw(HD_DATA, req->buffer, 256);
                        break;
                default:
                        printk("unknown hd-command\n");
@@ -655,7 +656,7 @@ repeat:
        }
 }
 
-static void do_hd_request (struct request_queue * q)
+static void do_hd_request(struct request_queue *q)
 {
        disable_irq(HD_IRQ);
        hd_request();
@@ -708,12 +709,12 @@ static int __init hd_init(void)
 {
        int drive;
 
-       if (register_blkdev(MAJOR_NR,"hd"))
+       if (register_blkdev(MAJOR_NR, "hd"))
                return -1;
 
        hd_queue = blk_init_queue(do_hd_request, &hd_lock);
        if (!hd_queue) {
-               unregister_blkdev(MAJOR_NR,"hd");
+               unregister_blkdev(MAJOR_NR, "hd");
                return -ENOMEM;
        }
 
@@ -742,7 +743,7 @@ static int __init hd_init(void)
                goto out;
        }
 
-       for (drive=0 ; drive < NR_HD ; drive++) {
+       for (drive = 0 ; drive < NR_HD ; drive++) {
                struct gendisk *disk = alloc_disk(64);
                struct hd_i_struct *p = &hd_info[drive];
                if (!disk)
@@ -756,7 +757,7 @@ static int __init hd_init(void)
                disk->queue = hd_queue;
                p->unit = drive;
                hd_gendisk[drive] = disk;
-               printk ("%s: %luMB, CHS=%d/%d/%d\n",
+               printk("%s: %luMB, CHS=%d/%d/%d\n",
                        disk->disk_name, (unsigned long)get_capacity(disk)/2048,
                        p->cyl, p->head, p->sect);
        }
@@ -776,7 +777,7 @@ static int __init hd_init(void)
        }
 
        /* Let them fly */
-       for(drive=0; drive < NR_HD; drive++)
+       for (drive = 0; drive < NR_HD; drive++)
                add_disk(hd_gendisk[drive]);
 
        return 0;
@@ -791,7 +792,7 @@ out1:
        NR_HD = 0;
 out:
        del_timer(&device_timer);
-       unregister_blkdev(MAJOR_NR,"hd");
+       unregister_blkdev(MAJOR_NR, "hd");
        blk_cleanup_queue(hd_queue);
        return -1;
 Enomem:
@@ -800,7 +801,8 @@ Enomem:
        goto out;
 }
 
-static int __init parse_hd_setup (char *line) {
+static int __init parse_hd_setup(char *line)
+{
        int ints[6];
 
        (void) get_options(line, ARRAY_SIZE(ints), ints);
index 88fe9070c9c30668878ac79eb75853ab4cbe0392..4fe516df9f74f3d40d2cc9abaa44000c80b891fb 100644 (file)
@@ -35,6 +35,7 @@
  *  Try:  http://www.maf.iki.fi/~maf/ht6560b/
  */
 
+#define DRV_NAME       "ht6560b"
 #define HT6560B_VERSION "v0.08"
 
 #include <linux/module.h>
@@ -156,8 +157,8 @@ static void ht6560b_selectproc (ide_drive_t *drive)
                /*
                 * Set timing for this drive:
                 */
-               outb(timing, hwif->io_ports[IDE_SELECT_OFFSET]);
-               (void)inb(hwif->io_ports[IDE_STATUS_OFFSET]);
+               outb(timing, hwif->io_ports.device_addr);
+               (void)inb(hwif->io_ports.status_addr);
 #ifdef DEBUG
                printk("ht6560b: %s: select=%#x timing=%#x\n",
                        drive->name, select, timing);
@@ -211,8 +212,8 @@ static u8 ht_pio2timings(ide_drive_t *drive, const u8 pio)
 {
        int active_time, recovery_time;
        int active_cycles, recovery_cycles;
-       int bus_speed = system_bus_clock();
-       
+       int bus_speed = ide_vlb_clk ? ide_vlb_clk : system_bus_clock();
+
         if (pio) {
                unsigned int cycle_time;
 
@@ -322,66 +323,44 @@ static void __init ht6560b_port_init_devs(ide_hwif_t *hwif)
        hwif->drives[1].drive_data = t;
 }
 
-int probe_ht6560b = 0;
+static int probe_ht6560b;
 
 module_param_named(probe, probe_ht6560b, bool, 0);
 MODULE_PARM_DESC(probe, "probe for HT6560B chipset");
 
+static const struct ide_port_ops ht6560b_port_ops = {
+       .port_init_devs         = ht6560b_port_init_devs,
+       .set_pio_mode           = ht6560b_set_pio_mode,
+       .selectproc             = ht6560b_selectproc,
+};
+
 static const struct ide_port_info ht6560b_port_info __initdata = {
+       .name                   = DRV_NAME,
        .chipset                = ide_ht6560b,
+       .port_ops               = &ht6560b_port_ops,
        .host_flags             = IDE_HFLAG_SERIALIZE | /* is this needed? */
                                  IDE_HFLAG_NO_DMA |
-                                 IDE_HFLAG_NO_AUTOTUNE |
                                  IDE_HFLAG_ABUSE_PREFETCH,
        .pio_mask               = ATA_PIO4,
 };
 
 static int __init ht6560b_init(void)
 {
-       ide_hwif_t *hwif, *mate;
-       static u8 idx[4] = { 0, 1, 0xff, 0xff };
-       hw_regs_t hw[2];
-
        if (probe_ht6560b == 0)
                return -ENODEV;
 
-       hwif = &ide_hwifs[0];
-       mate = &ide_hwifs[1];
-
-       if (!request_region(HT_CONFIG_PORT, 1, hwif->name)) {
+       if (!request_region(HT_CONFIG_PORT, 1, DRV_NAME)) {
                printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n",
-                       __FUNCTION__);
+                       __func__);
                return -ENODEV;
        }
 
        if (!try_to_init_ht6560b()) {
-               printk(KERN_NOTICE "%s: HBA not found\n", __FUNCTION__);
+               printk(KERN_NOTICE "%s: HBA not found\n", __func__);
                goto release_region;
        }
 
-       memset(&hw, 0, sizeof(hw));
-
-       ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
-       hw[0].irq = 14;
-
-       ide_std_init_ports(&hw[1], 0x170, 0x376);
-       hw[1].irq = 15;
-
-       ide_init_port_hw(hwif, &hw[0]);
-       ide_init_port_hw(mate, &hw[1]);
-
-       hwif->selectproc = &ht6560b_selectproc;
-       hwif->set_pio_mode = &ht6560b_set_pio_mode;
-
-       mate->selectproc = &ht6560b_selectproc;
-       mate->set_pio_mode = &ht6560b_set_pio_mode;
-
-       hwif->port_init_devs = ht6560b_port_init_devs;
-       mate->port_init_devs = ht6560b_port_init_devs;
-
-       ide_device_add(idx, &ht6560b_port_info);
-
-       return 0;
+       return ide_legacy_device_add(&ht6560b_port_info, 0);
 
 release_region:
        release_region(HT_CONFIG_PORT, 1);
index ecd7f3553554e8f9c17da4537fd46818dd9feabe..ecae916a3385f15c8725199a3eb18fe3733a79e4 100644 (file)
@@ -4,7 +4,9 @@
 #include <linux/module.h>
 #include <linux/ide.h>
 
-int probe_4drives = 0;
+#define DRV_NAME "ide-4drives"
+
+static int probe_4drives;
 
 module_param_named(probe, probe_4drives, bool, 0);
 MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port");
@@ -12,31 +14,51 @@ MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port");
 static int __init ide_4drives_init(void)
 {
        ide_hwif_t *hwif, *mate;
-       u8 idx[4] = { 0, 1, 0xff, 0xff };
+       unsigned long base = 0x1f0, ctl = 0x3f6;
+       u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
        hw_regs_t hw;
 
        if (probe_4drives == 0)
                return -ENODEV;
 
-       hwif = &ide_hwifs[0];
-       mate = &ide_hwifs[1];
+       if (!request_region(base, 8, DRV_NAME)) {
+               printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
+                               DRV_NAME, base, base + 7);
+               return -EBUSY;
+       }
+
+       if (!request_region(ctl, 1, DRV_NAME)) {
+               printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
+                               DRV_NAME, ctl);
+               release_region(base, 8);
+               return -EBUSY;
+       }
 
        memset(&hw, 0, sizeof(hw));
 
-       ide_std_init_ports(&hw, 0x1f0, 0x3f6);
+       ide_std_init_ports(&hw, base, ctl);
        hw.irq = 14;
        hw.chipset = ide_4drives;
 
-       ide_init_port_hw(hwif, &hw);
-       ide_init_port_hw(mate, &hw);
-
-       mate->drives[0].select.all ^= 0x20;
-       mate->drives[1].select.all ^= 0x20;
-
-       hwif->mate = mate;
-       mate->mate = hwif;
-
-       hwif->serialized = mate->serialized = 1;
+       hwif = ide_find_port();
+       if (hwif) {
+               ide_init_port_hw(hwif, &hw);
+               idx[0] = hwif->index;
+       }
+
+       mate = ide_find_port();
+       if (mate) {
+               ide_init_port_hw(mate, &hw);
+               mate->drives[0].select.all ^= 0x20;
+               mate->drives[1].select.all ^= 0x20;
+               idx[1] = mate->index;
+
+               if (hwif) {
+                       hwif->mate = mate;
+                       mate->mate = hwif;
+                       hwif->serialized = mate->serialized = 1;
+               }
+       }
 
        ide_device_add(idx, NULL);
 
index 9a23b94f293950f960a0e7aa8ea85d14002fee93..aa2ea3deac85a14ac724501690fad4f2976975d1 100644 (file)
@@ -51,6 +51,8 @@
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
 
+#define DRV_NAME "ide-cs"
+
 /*====================================================================*/
 
 /* Module parameters */
@@ -72,16 +74,11 @@ static char *version =
 
 /*====================================================================*/
 
-static const char ide_major[] = {
-    IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR,
-    IDE4_MAJOR, IDE5_MAJOR
-};
-
 typedef struct ide_info_t {
        struct pcmcia_device    *p_dev;
+       ide_hwif_t              *hwif;
     int                ndev;
     dev_node_t node;
-    int                hd;
 } ide_info_t;
 
 static void ide_release(struct pcmcia_device *);
@@ -136,45 +133,71 @@ static int ide_probe(struct pcmcia_device *link)
 
 static void ide_detach(struct pcmcia_device *link)
 {
+    ide_info_t *info = link->priv;
+    ide_hwif_t *hwif = info->hwif;
+
     DEBUG(0, "ide_detach(0x%p)\n", link);
 
     ide_release(link);
 
-    kfree(link->priv);
+    release_region(hwif->io_ports.ctl_addr, 1);
+    release_region(hwif->io_ports.data_addr, 8);
+
+    kfree(info);
 } /* ide_detach */
 
-static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle)
+static const struct ide_port_ops idecs_port_ops = {
+       .quirkproc              = ide_undecoded_slave,
+};
+
+static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl,
+                               unsigned long irq, struct pcmcia_device *handle)
 {
     ide_hwif_t *hwif;
     hw_regs_t hw;
     int i;
     u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
 
+    if (!request_region(io, 8, DRV_NAME)) {
+       printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
+                       DRV_NAME, io, io + 7);
+       return NULL;
+    }
+
+    if (!request_region(ctl, 1, DRV_NAME)) {
+       printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
+                       DRV_NAME, ctl);
+       release_region(io, 8);
+       return NULL;
+    }
+
     memset(&hw, 0, sizeof(hw));
     ide_std_init_ports(&hw, io, ctl);
     hw.irq = irq;
     hw.chipset = ide_pci;
     hw.dev = &handle->dev;
 
-    hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+    hwif = ide_find_port();
     if (hwif == NULL)
-       return -1;
+       goto out_release;
 
     i = hwif->index;
 
-    if (hwif->present)
-       ide_unregister(i);
-    else
-       ide_init_port_data(hwif, i);
-
+    ide_init_port_data(hwif, i);
     ide_init_port_hw(hwif, &hw);
-    hwif->quirkproc = &ide_undecoded_slave;
+    hwif->port_ops = &idecs_port_ops;
 
     idx[0] = i;
 
     ide_device_add(idx, NULL);
 
-    return hwif->present ? i : -1;
+    if (hwif->present)
+       return hwif;
+
+out_release:
+    release_region(ctl, 1);
+    release_region(io, 8);
+    return NULL;
 }
 
 /*======================================================================
@@ -199,8 +222,9 @@ static int ide_config(struct pcmcia_device *link)
        cistpl_cftable_entry_t dflt;
     } *stk = NULL;
     cistpl_cftable_entry_t *cfg;
-    int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0;
+    int i, pass, last_ret = 0, last_fn = 0, is_kme = 0;
     unsigned long io_base, ctl_base;
+    ide_hwif_t *hwif;
 
     DEBUG(0, "ide_config(0x%p)\n", link);
 
@@ -296,14 +320,15 @@ static int ide_config(struct pcmcia_device *link)
        outb(0x81, ctl_base+1);
 
     /* retry registration in case device is still spinning up */
-    for (hd = -1, i = 0; i < 10; i++) {
-       hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
-       if (hd >= 0) break;
+    for (i = 0; i < 10; i++) {
+       hwif = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
+       if (hwif)
+           break;
        if (link->io.NumPorts1 == 0x20) {
            outb(0x02, ctl_base + 0x10);
-           hd = idecs_register(io_base + 0x10, ctl_base + 0x10,
-                               link->irq.AssignedIRQ, link);
-           if (hd >= 0) {
+           hwif = idecs_register(io_base + 0x10, ctl_base + 0x10,
+                                 link->irq.AssignedIRQ, link);
+           if (hwif) {
                io_base += 0x10;
                ctl_base += 0x10;
                break;
@@ -312,7 +337,7 @@ static int ide_config(struct pcmcia_device *link)
        msleep(100);
     }
 
-    if (hd < 0) {
+    if (hwif == NULL) {
        printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx"
               ", irq %u failed\n", io_base, ctl_base,
               link->irq.AssignedIRQ);
@@ -320,10 +345,10 @@ static int ide_config(struct pcmcia_device *link)
     }
 
     info->ndev = 1;
-    sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2));
-    info->node.major = ide_major[hd];
+    sprintf(info->node.dev_name, "hd%c", 'a' + hwif->index * 2);
+    info->node.major = hwif->major;
     info->node.minor = 0;
-    info->hd = hd;
+    info->hwif = hwif;
     link->dev_node = &info->node;
     printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
           info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
@@ -354,13 +379,14 @@ failed:
 void ide_release(struct pcmcia_device *link)
 {
     ide_info_t *info = link->priv;
+    ide_hwif_t *hwif = info->hwif;
 
     DEBUG(0, "ide_release(0x%p)\n", link);
 
     if (info->ndev) {
        /* FIXME: if this fails we need to queue the cleanup somehow
           -- need to investigate the required PCMCIA magic */
-       ide_unregister(info->hd);
+       ide_unregister(hwif);
     }
     info->ndev = 0;
 
index 249651e2da424f2b9b6ccb409b6b6bd046b46ccc..8279dc7ca4c0086fc8ca4b5551012cd6d316306c 100644 (file)
@@ -30,14 +30,14 @@ static void __devinit plat_ide_setup_ports(hw_regs_t *hw,
        unsigned long port = (unsigned long)base;
        int i;
 
-       hw->io_ports[IDE_DATA_OFFSET] = port;
+       hw->io_ports.data_addr = port;
 
        port += (1 << pdata->ioport_shift);
-       for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET;
+       for (i = 1; i <= 7;
             i++, port += (1 << pdata->ioport_shift))
-               hw->io_ports[i] = port;
+               hw->io_ports_array[i] = port;
 
-       hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
+       hw->io_ports.ctl_addr = (unsigned long)ctrl;
 
        hw->irq = irq;
 
@@ -89,7 +89,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
                        res_alt->start, res_alt->end - res_alt->start + 1);
        }
 
-       hwif = ide_find_port((unsigned long)base);
+       hwif = ide_find_port();
        if (!hwif) {
                ret = -ENODEV;
                goto out;
@@ -101,10 +101,8 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
 
        ide_init_port_hw(hwif, &hw);
 
-       if (mmio) {
-               hwif->mmio = 1;
+       if (mmio)
                default_hwif_mmiops(hwif);
-       }
 
        idx[0] = hwif->index;
 
@@ -122,7 +120,7 @@ static int __devexit plat_ide_remove(struct platform_device *pdev)
 {
        ide_hwif_t *hwif = pdev->dev.driver_data;
 
-       ide_unregister(hwif->index);
+       ide_unregister(hwif);
 
        return 0;
 }
@@ -130,6 +128,7 @@ static int __devexit plat_ide_remove(struct platform_device *pdev)
 static struct platform_driver platform_ide_driver = {
        .driver = {
                .name = "pata_platform",
+               .owner = THIS_MODULE,
        },
        .probe = plat_ide_probe,
        .remove = __devexit_p(plat_ide_remove),
@@ -147,6 +146,7 @@ static void __exit platform_ide_exit(void)
 
 MODULE_DESCRIPTION("Platform IDE driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pata_platform");
 
 module_init(platform_ide_init);
 module_exit(platform_ide_exit);
index eaf5dbe58bc24eeca32e09349348ff29dc35cbc1..1f527bbf8d96f9ebb34637223bce6bb07a8db82b 100644 (file)
@@ -72,9 +72,9 @@ static void __init macide_setup_ports(hw_regs_t *hw, unsigned long base,
        memset(hw, 0, sizeof(*hw));
 
        for (i = 0; i < 8; i++)
-               hw->io_ports[i] = base + i * 4;
+               hw->io_ports_array[i] = base + i * 4;
 
-       hw->io_ports[IDE_CONTROL_OFFSET] = base + IDE_CONTROL;
+       hw->io_ports.ctl_addr = base + IDE_CONTROL;
 
        hw->irq = irq;
        hw->ack_intr = ack_intr;
@@ -120,7 +120,7 @@ static int __init macide_init(void)
 
        macide_setup_ports(&hw, base, irq, ack_intr);
 
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif) {
                u8 index = hwif->index;
                u8 idx[4] = { index, 0xff, 0xff, 0xff };
@@ -128,8 +128,6 @@ static int __init macide_init(void)
                ide_init_port_data(hwif, index);
                ide_init_port_hw(hwif, &hw);
 
-               hwif->mmio = 1;
-
                ide_device_add(idx, NULL);
        }
 
index 2da28759686ec5be154c241a4a5ac6875ac3f4b3..a3573d40b4b77e524539faf2129f93f7c1de273e 100644 (file)
@@ -80,10 +80,10 @@ void q40_ide_setup_ports ( hw_regs_t *hw,
        for (i = 0; i < IDE_NR_PORTS; i++) {
                /* BIG FAT WARNING: 
                   assumption: only DATA port is ever used in 16 bit mode */
-               if ( i==0 )
-                       hw->io_ports[i] = Q40_ISA_IO_W(base + offsets[i]);
+               if (i == 0)
+                       hw->io_ports_array[i] = Q40_ISA_IO_W(base + offsets[i]);
                else
-                       hw->io_ports[i] = Q40_ISA_IO_B(base + offsets[i]);
+                       hw->io_ports_array[i] = Q40_ISA_IO_B(base + offsets[i]);
        }
 
        hw->irq = irq;
@@ -137,11 +137,10 @@ static int __init q40ide_init(void)
 //                     m68kide_iops,
                        q40ide_default_irq(pcide_bases[i]));
 
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif) {
                ide_init_port_data(hwif, hwif->index);
                ide_init_port_hw(hwif, &hw);
-               hwif->mmio = 1;
 
                idx[i] = hwif->index;
        }
index 7016bdf4fcc16ae811b89776ea22467d535431a4..6424af154325d9f1c0776b37f7cb7aac7d932593 100644 (file)
  *
  * QDI QD6500/QD6580 EIDE controller fast support
  *
- * Please set local bus speed using kernel parameter idebus
- *     for example, "idebus=33" stands for 33Mhz VLbus
  * To activate controller support, use "ide0=qd65xx"
- * To enable tuning, use "hda=autotune hdb=autotune"
- * To enable 2nd channel tuning (qd6580 only), use "hdc=autotune hdd=autotune"
  */
 
 /*
@@ -37,6 +33,8 @@
 #include <asm/system.h>
 #include <asm/io.h>
 
+#define DRV_NAME "qd65xx"
+
 #include "qd65xx.h"
 
 /*
 static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */
 
 /*
- * qd_select:
+ * qd65xx_select:
  *
- * This routine is invoked from ide.c to prepare for access to a given drive.
+ * This routine is invoked to prepare for access to a given drive.
  */
 
-static void qd_select (ide_drive_t *drive)
+static void qd65xx_select(ide_drive_t *drive)
 {
        u8 index = ((   (QD_TIMREG(drive)) & 0x80 ) >> 7) |
                        (QD_TIMREG(drive) & 0x02);
@@ -112,17 +110,18 @@ static void qd_select (ide_drive_t *drive)
 
 static u8 qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time)
 {
-       u8 active_cycle,recovery_cycle;
+       int clk = ide_vlb_clk ? ide_vlb_clk : system_bus_clock();
+       u8 act_cyc, rec_cyc;
 
-       if (system_bus_clock()<=33) {
-               active_cycle =   9  - IDE_IN(active_time   * system_bus_clock() / 1000 + 1, 2, 9);
-               recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 0, 15);
+       if (clk <= 33) {
+               act_cyc =  9 - IDE_IN(active_time   * clk / 1000 + 1, 2,  9);
+               rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 0, 15);
        } else {
-               active_cycle =   8  - IDE_IN(active_time   * system_bus_clock() / 1000 + 1, 1, 8);
-               recovery_cycle = 18 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 3, 18);
+               act_cyc =  8 - IDE_IN(active_time   * clk / 1000 + 1, 1,  8);
+               rec_cyc = 18 - IDE_IN(recovery_time * clk / 1000 + 1, 3, 18);
        }
 
-       return((recovery_cycle<<4) | 0x08 | active_cycle);
+       return (rec_cyc << 4) | 0x08 | act_cyc;
 }
 
 /*
@@ -133,10 +132,13 @@ static u8 qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery
 
 static u8 qd6580_compute_timing (int active_time, int recovery_time)
 {
-       u8 active_cycle   = 17 - IDE_IN(active_time   * system_bus_clock() / 1000 + 1, 2, 17);
-       u8 recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 2, 15);
+       int clk = ide_vlb_clk ? ide_vlb_clk : system_bus_clock();
+       u8 act_cyc, rec_cyc;
+
+       act_cyc = 17 - IDE_IN(active_time   * clk / 1000 + 1, 2, 17);
+       rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 2, 15);
 
-       return((recovery_cycle<<4) | active_cycle);
+       return (rec_cyc << 4) | act_cyc;
 }
 
 /*
@@ -167,37 +169,16 @@ static int qd_find_disk_type (ide_drive_t *drive,
        return 0;
 }
 
-/*
- * qd_timing_ok:
- *
- * check whether timings don't conflict
- */
-
-static int qd_timing_ok (ide_drive_t drives[])
-{
-       return (IDE_IMPLY(drives[0].present && drives[1].present,
-                       IDE_IMPLY(QD_TIMREG(drives) == QD_TIMREG(drives+1),
-                                 QD_TIMING(drives) == QD_TIMING(drives+1))));
-       /* if same timing register, must be same timing */
-}
-
 /*
  * qd_set_timing:
  *
- * records the timing, and enables selectproc as needed
+ * records the timing
  */
 
 static void qd_set_timing (ide_drive_t *drive, u8 timing)
 {
-       ide_hwif_t *hwif = HWIF(drive);
-
        drive->drive_data &= 0xff00;
        drive->drive_data |= timing;
-       if (qd_timing_ok(hwif->drives)) {
-               qd_select(drive); /* selects once */
-               hwif->selectproc = NULL;
-       } else
-               hwif->selectproc = &qd_select;
 
        printk(KERN_DEBUG "%s: %#x\n", drive->name, timing);
 }
@@ -225,10 +206,11 @@ static void qd6500_set_pio_mode(ide_drive_t *drive, const u8 pio)
 
 static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-       int base = HWIF(drive)->select_data;
+       ide_hwif_t *hwif = drive->hwif;
        unsigned int cycle_time;
        int active_time   = 175;
        int recovery_time = 415; /* worst case values from the dos driver */
+       u8 base = (hwif->config_data & 0xff00) >> 8;
 
        if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) {
                cycle_time = ide_pio_cycle_time(drive, pio);
@@ -299,21 +281,10 @@ static int __init qd_testreg(int port)
        return (readreg != QD_TESTVAL);
 }
 
-/*
- * qd_setup:
- *
- * called to setup an ata channel : adjusts attributes & links for tuning
- */
-
-static void __init qd_setup(ide_hwif_t *hwif, int base, int config)
-{
-       hwif->select_data = base;
-       hwif->config_data = config;
-}
-
 static void __init qd6500_port_init_devs(ide_hwif_t *hwif)
 {
-       u8 base = hwif->select_data, config = QD_CONFIG(hwif);
+       u8 base = (hwif->config_data & 0xff00) >> 8;
+       u8 config = QD_CONFIG(hwif);
 
        hwif->drives[0].drive_data = QD6500_DEF_DATA;
        hwif->drives[1].drive_data = QD6500_DEF_DATA;
@@ -322,9 +293,10 @@ static void __init qd6500_port_init_devs(ide_hwif_t *hwif)
 static void __init qd6580_port_init_devs(ide_hwif_t *hwif)
 {
        u16 t1, t2;
-       u8 base = hwif->select_data, config = QD_CONFIG(hwif);
+       u8 base = (hwif->config_data & 0xff00) >> 8;
+       u8 config = QD_CONFIG(hwif);
 
-       if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) {
+       if (hwif->host_flags & IDE_HFLAG_SINGLE) {
                t1 = QD6580_DEF_DATA;
                t2 = QD6580_DEF_DATA2;
        } else
@@ -334,11 +306,23 @@ static void __init qd6580_port_init_devs(ide_hwif_t *hwif)
        hwif->drives[1].drive_data = t2;
 }
 
+static const struct ide_port_ops qd6500_port_ops = {
+       .port_init_devs         = qd6500_port_init_devs,
+       .set_pio_mode           = qd6500_set_pio_mode,
+       .selectproc             = qd65xx_select,
+};
+
+static const struct ide_port_ops qd6580_port_ops = {
+       .port_init_devs         = qd6580_port_init_devs,
+       .set_pio_mode           = qd6580_set_pio_mode,
+       .selectproc             = qd65xx_select,
+};
+
 static const struct ide_port_info qd65xx_port_info __initdata = {
+       .name                   = DRV_NAME,
        .chipset                = ide_qd65xx,
        .host_flags             = IDE_HFLAG_IO_32BIT |
-                                 IDE_HFLAG_NO_DMA |
-                                 IDE_HFLAG_NO_AUTOTUNE,
+                                 IDE_HFLAG_NO_DMA,
        .pio_mask               = ATA_PIO4,
 };
 
@@ -351,65 +335,41 @@ static const struct ide_port_info qd65xx_port_info __initdata = {
 
 static int __init qd_probe(int base)
 {
-       ide_hwif_t *hwif;
-       u8 config, unit;
-       u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-       hw_regs_t hw[2];
+       int rc;
+       u8 config, unit, control;
+       struct ide_port_info d = qd65xx_port_info;
 
        config = inb(QD_CONFIG_PORT);
 
        if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) )
-               return 1;
+               return -ENODEV;
 
        unit = ! (config & QD_CONFIG_IDE_BASEPORT);
 
-       memset(&hw, 0, sizeof(hw));
+       if (unit)
+               d.host_flags |= IDE_HFLAG_QD_2ND_PORT;
 
-       ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
-       hw[0].irq = 14;
+       switch (config & 0xf0) {
+       case QD_CONFIG_QD6500:
+               if (qd_testreg(base))
+                        return -ENODEV;        /* bad register */
 
-       ide_std_init_ports(&hw[1], 0x170, 0x376);
-       hw[1].irq = 15;
-
-       if ((config & 0xf0) == QD_CONFIG_QD6500) {
-
-               if (qd_testreg(base)) return 1;         /* bad register */
-
-               /* qd6500 found */
-
-               hwif = &ide_hwifs[unit];
-               printk(KERN_NOTICE "%s: qd6500 at %#x\n", hwif->name, base);
-               printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n",
-                       config, QD_ID3);
-               
                if (config & QD_CONFIG_DISABLED) {
                        printk(KERN_WARNING "qd6500 is disabled !\n");
-                       return 1;
+                       return -ENODEV;
                }
 
-               ide_init_port_hw(hwif, &hw[unit]);
-
-               qd_setup(hwif, base, config);
-
-               hwif->port_init_devs = qd6500_port_init_devs;
-               hwif->set_pio_mode = &qd6500_set_pio_mode;
-
-               idx[unit] = unit;
-
-               ide_device_add(idx, &qd65xx_port_info);
-
-               return 1;
-       }
-
-       if (((config & 0xf0) == QD_CONFIG_QD6580_A) ||
-           ((config & 0xf0) == QD_CONFIG_QD6580_B)) {
-
-               u8 control;
-
-               if (qd_testreg(base) || qd_testreg(base+0x02)) return 1;
-                       /* bad registers */
+               printk(KERN_NOTICE "qd6500 at %#x\n", base);
+               printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n",
+                       config, QD_ID3);
 
-               /* qd6580 found */
+               d.port_ops = &qd6500_port_ops;
+               d.host_flags |= IDE_HFLAG_SINGLE;
+               break;
+       case QD_CONFIG_QD6580_A:
+       case QD_CONFIG_QD6580_B:
+               if (qd_testreg(base) || qd_testreg(base + 0x02))
+                       return -ENODEV; /* bad registers */
 
                control = inb(QD_CONTROL_PORT);
 
@@ -419,74 +379,44 @@ static int __init qd_probe(int base)
 
                outb(QD_DEF_CONTR, QD_CONTROL_PORT);
 
-               if (control & QD_CONTR_SEC_DISABLED) {
-                       /* secondary disabled */
-
-                       hwif = &ide_hwifs[unit];
-                       printk(KERN_INFO "%s: qd6580: single IDE board\n",
-                                        hwif->name);
-
-                       ide_init_port_hw(hwif, &hw[unit]);
-
-                       qd_setup(hwif, base, config | (control << 8));
-
-                       hwif->port_init_devs = qd6580_port_init_devs;
-                       hwif->set_pio_mode = &qd6580_set_pio_mode;
-
-                       idx[unit] = unit;
+               d.port_ops = &qd6580_port_ops;
+               if (control & QD_CONTR_SEC_DISABLED)
+                       d.host_flags |= IDE_HFLAG_SINGLE;
 
-                       ide_device_add(idx, &qd65xx_port_info);
-
-                       return 1;
-               } else {
-                       ide_hwif_t *mate;
-
-                       hwif = &ide_hwifs[0];
-                       mate = &ide_hwifs[1];
-                       /* secondary enabled */
-                       printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n",
-                                       hwif->name, mate->name);
-
-                       ide_init_port_hw(hwif, &hw[0]);
-                       ide_init_port_hw(mate, &hw[1]);
-
-                       qd_setup(hwif, base, config | (control << 8));
-
-                       hwif->port_init_devs = qd6580_port_init_devs;
-                       hwif->set_pio_mode = &qd6580_set_pio_mode;
-
-                       qd_setup(mate, base, config | (control << 8));
-
-                       mate->port_init_devs = qd6580_port_init_devs;
-                       mate->set_pio_mode = &qd6580_set_pio_mode;
+               printk(KERN_INFO "qd6580: %s IDE board\n",
+                       (control & QD_CONTR_SEC_DISABLED) ? "single" : "dual");
+               break;
+       default:
+               return -ENODEV;
+       }
 
-                       idx[0] = 0;
-                       idx[1] = 1;
+       rc = ide_legacy_device_add(&d, (base << 8) | config);
 
-                       ide_device_add(idx, &qd65xx_port_info);
+       if (d.host_flags & IDE_HFLAG_SINGLE)
+               return (rc == 0) ? 1 : rc;
 
-                       return 0; /* no other qd65xx possible */
-               }
-       }
-       /* no qd65xx found */
-       return 1;
+       return rc;
 }
 
-int probe_qd65xx = 0;
+static int probe_qd65xx;
 
 module_param_named(probe, probe_qd65xx, bool, 0);
 MODULE_PARM_DESC(probe, "probe for QD65xx chipsets");
 
 static int __init qd65xx_init(void)
 {
+       int rc1, rc2 = -ENODEV;
+
        if (probe_qd65xx == 0)
                return -ENODEV;
 
-       if (qd_probe(0x30))
-               qd_probe(0xb0);
-       if (ide_hwifs[0].chipset != ide_qd65xx &&
-           ide_hwifs[1].chipset != ide_qd65xx)
+       rc1 = qd_probe(0x30);
+       if (rc1)
+               rc2 = qd_probe(0xb0);
+
+       if (rc1 < 0 && rc2 < 0)
                return -ENODEV;
+
        return 0;
 }
 
index 28dd50a15d55af3ad1ccb566f04a76f28d8c9740..c83dea85e621fbba01a60fa7a000ba8269587b57 100644 (file)
@@ -30,7 +30,6 @@
 #define QD_ID3                 ((config & QD_CONFIG_ID3)!=0)
 
 #define QD_CONFIG(hwif)                ((hwif)->config_data & 0x00ff)
-#define QD_CONTROL(hwif)       (((hwif)->config_data & 0xff00) >> 8)
 
 #define QD_TIMING(drive)       (byte)(((drive)->drive_data) & 0x00ff)
 #define QD_TIMREG(drive)       (byte)((((drive)->drive_data) & 0xff00) >> 8)
index bc1944811b99b9a2b055a29b6455accc16692bd1..b54a14a577550acf3af76bfceaadf3c221433c90 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 /*
- * VLB Controller Support from 
+ * VLB Controller Support from
  * Wolfram Podien
  * Rohoefe 3
  * D28832 Achim
@@ -32,7 +32,7 @@
  * #define UMC_DRIVE0 11
  * in the beginning of the driver, which sets the speed of drive 0 to 11 (there
  * are some lines present). 0 - 11 are allowed speed values. These values are
- * the results from the DOS speed test program supplied from UMC. 11 is the 
+ * the results from the DOS speed test program supplied from UMC. 11 is the
  * highest speed (about PIO mode 3)
  */
 #define REALLY_SLOW_IO         /* some systems can safely undef this */
@@ -51,6 +51,8 @@
 
 #include <asm/io.h>
 
+#define DRV_NAME "umc8672"
+
 /*
  * Default speeds.  These can be changed with "auto-tune" and/or hdparm.
  */
 #define UMC_DRIVE3      1              /* In case of crash reduce speed */
 
 static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3};
-static const u8 pio_to_umc [5] = {0,3,7,10,11};        /* rough guesses */
+static const u8 pio_to_umc [5] = {0, 3, 7, 10, 11};    /* rough guesses */
 
 /*       0    1    2    3    4    5    6    7    8    9    10   11      */
 static const u8 speedtab [3][12] = {
-       {0xf, 0xb, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 },
-       {0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 },
-       {0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}};
+       {0x0f, 0x0b, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1},
+       {0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1},
+       {0xff, 0xcb, 0xc0, 0x58, 0x36, 0x33, 0x23, 0x22, 0x21, 0x11, 0x10, 0x0}
+};
 
-static void out_umc (char port,char wert)
+static void out_umc(char port, char wert)
 {
-       outb_p(port,0x108);
-       outb_p(wert,0x109);
+       outb_p(port, 0x108);
+       outb_p(wert, 0x109);
 }
 
-static inline u8 in_umc (char port)
+static inline u8 in_umc(char port)
 {
-       outb_p(port,0x108);
+       outb_p(port, 0x108);
        return inb_p(0x109);
 }
 
-static void umc_set_speeds (u8 speeds[])
+static void umc_set_speeds(u8 speeds[])
 {
        int i, tmp;
 
-       outb_p(0x5A,0x108); /* enable umc */
+       outb_p(0x5A, 0x108); /* enable umc */
 
-       out_umc (0xd7,(speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4)));
-       out_umc (0xd6,(speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4)));
+       out_umc(0xd7, (speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4)));
+       out_umc(0xd6, (speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4)));
        tmp = 0;
-       for (i = 3; i >= 0; i--) {
+       for (i = 3; i >= 0; i--)
                tmp = (tmp << 2) | speedtab[1][speeds[i]];
+       out_umc(0xdc, tmp);
+       for (i = 0; i < 4; i++) {
+               out_umc(0xd0 + i, speedtab[2][speeds[i]]);
+               out_umc(0xd8 + i, speedtab[2][speeds[i]]);
        }
-       out_umc (0xdc,tmp);
-       for (i = 0;i < 4; i++) {
-               out_umc (0xd0+i,speedtab[2][speeds[i]]);
-               out_umc (0xd8+i,speedtab[2][speeds[i]]);
-       }
-       outb_p(0xa5,0x108); /* disable umc */
+       outb_p(0xa5, 0x108); /* disable umc */
 
-       printk ("umc8672: drive speeds [0 to 11]: %d %d %d %d\n",
+       printk("umc8672: drive speeds [0 to 11]: %d %d %d %d\n",
                speeds[0], speeds[1], speeds[2], speeds[3]);
 }
 
 static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
+       ide_hwif_t *hwif = drive->hwif;
        unsigned long flags;
-       ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup;
 
        printk("%s: setting umc8672 to PIO mode%d (speed %d)\n",
                drive->name, pio, pio_to_umc[pio]);
        spin_lock_irqsave(&ide_lock, flags);
-       if (hwgroup && hwgroup->handler != NULL) {
+       if (hwif->mate && hwif->mate->hwgroup->handler) {
                printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n");
        } else {
                current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
-               umc_set_speeds (current_speeds);
+               umc_set_speeds(current_speeds);
        }
        spin_unlock_irqrestore(&ide_lock, flags);
 }
 
+static const struct ide_port_ops umc8672_port_ops = {
+       .set_pio_mode           = umc_set_pio_mode,
+};
+
 static const struct ide_port_info umc8672_port_info __initdata = {
+       .name                   = DRV_NAME,
        .chipset                = ide_umc8672,
-       .host_flags             = IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE,
+       .port_ops               = &umc8672_port_ops,
+       .host_flags             = IDE_HFLAG_NO_DMA,
        .pio_mask               = ATA_PIO4,
 };
 
 static int __init umc8672_probe(void)
 {
        unsigned long flags;
-       static u8 idx[4] = { 0, 1, 0xff, 0xff };
-       hw_regs_t hw[2];
 
        if (!request_region(0x108, 2, "umc8672")) {
                printk(KERN_ERR "umc8672: ports 0x108-0x109 already in use.\n");
                return 1;
        }
        local_irq_save(flags);
-       outb_p(0x5A,0x108); /* enable umc */
+       outb_p(0x5A, 0x108); /* enable umc */
        if (in_umc (0xd5) != 0xa0) {
                local_irq_restore(flags);
                printk(KERN_ERR "umc8672: not found\n");
                release_region(0x108, 2);
-               return 1;  
+               return 1;
        }
-       outb_p(0xa5,0x108); /* disable umc */
+       outb_p(0xa5, 0x108); /* disable umc */
 
-       umc_set_speeds (current_speeds);
+       umc_set_speeds(current_speeds);
        local_irq_restore(flags);
 
-       memset(&hw, 0, sizeof(hw));
-
-       ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
-       hw[0].irq = 14;
-
-       ide_std_init_ports(&hw[1], 0x170, 0x376);
-       hw[1].irq = 15;
-
-       ide_init_port_hw(&ide_hwifs[0], &hw[0]);
-       ide_init_port_hw(&ide_hwifs[1], &hw[1]);
-
-       ide_hwifs[0].set_pio_mode = &umc_set_pio_mode;
-       ide_hwifs[1].set_pio_mode = &umc_set_pio_mode;
-
-       ide_device_add(idx, &umc8672_port_info);
-
-       return 0;
+       return ide_legacy_device_add(&umc8672_port_info, 0);
 }
 
-int probe_umc8672 = 0;
+static int probe_umc8672;
 
 module_param_named(probe, probe_umc8672, bool, 0);
 MODULE_PARM_DESC(probe, "probe for UMC8672 chipset");
index 9b628248f2f4a8c174c32b027671a21303317c21..296b9c674baec645b51bbe68900f729ed64c0024 100644 (file)
@@ -47,7 +47,6 @@
 #define IDE_AU1XXX_BURSTMODE   1
 
 static _auide_hwif auide_hwif;
-static int dbdma_init_done;
 
 static int auide_ddma_init(_auide_hwif *auide);
 
@@ -61,7 +60,7 @@ void auide_insw(unsigned long port, void *addr, u32 count)
 
        if(!put_dest_flags(ahwif->rx_chan, (void*)addr, count << 1, 
                           DDMA_FLAGS_NOIE)) {
-               printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__);
+               printk(KERN_ERR "%s failed %d\n", __func__, __LINE__);
                return;
        }
        ctp = *((chan_tab_t **)ahwif->rx_chan);
@@ -79,7 +78,7 @@ void auide_outsw(unsigned long port, void *addr, u32 count)
 
        if(!put_source_flags(ahwif->tx_chan, (void*)addr,
                             count << 1, DDMA_FLAGS_NOIE)) {
-               printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__);
+               printk(KERN_ERR "%s failed %d\n", __func__, __LINE__);
                return;
        }
        ctp = *((chan_tab_t **)ahwif->tx_chan);
@@ -250,7 +249,7 @@ static int auide_build_dmatable(ide_drive_t *drive)
                                                     (void*) sg_virt(sg),
                                                     tc, flags)) { 
                                        printk(KERN_ERR "%s failed %d\n", 
-                                              __FUNCTION__, __LINE__);
+                                              __func__, __LINE__);
                                }
                        } else 
                        {
@@ -258,7 +257,7 @@ static int auide_build_dmatable(ide_drive_t *drive)
                                                   (void*) sg_virt(sg),
                                                   tc, flags)) { 
                                        printk(KERN_ERR "%s failed %d\n", 
-                                              __FUNCTION__, __LINE__);
+                                              __func__, __LINE__);
                                }
                        }
 
@@ -315,35 +314,6 @@ static int auide_dma_setup(ide_drive_t *drive)
        return 0;
 }
 
-static u8 auide_mdma_filter(ide_drive_t *drive)
-{
-       /*
-        * FIXME: ->white_list and ->black_list are based on completely bogus
-        * ->ide_dma_check implementation which didn't set neither the host
-        * controller timings nor the device for the desired transfer mode.
-        *
-        * They should be either removed or 0x00 MWDMA mask should be
-        * returned for devices on the ->black_list.
-        */
-
-       if (dbdma_init_done == 0) {
-               auide_hwif.white_list = ide_in_drive_list(drive->id,
-                                                         dma_white_list);
-               auide_hwif.black_list = ide_in_drive_list(drive->id,
-                                                         dma_black_list);
-               auide_hwif.drive = drive;
-               auide_ddma_init(&auide_hwif);
-               dbdma_init_done = 1;
-       }
-
-       /* Is the drive in our DMA black list? */
-       if (auide_hwif.black_list)
-               printk(KERN_WARNING "%s: Disabling DMA for %s (blacklisted)\n",
-                                   drive->name, drive->id->model);
-
-       return drive->hwif->mwdma_mask;
-}
-
 static int auide_dma_test_irq(ide_drive_t *drive)
 {      
        if (drive->waiting_for_dma == 0)
@@ -396,41 +366,41 @@ static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 de
        dev->dev_devwidth    = devwidth;
        dev->dev_flags       = flags;
 }
-  
-#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
 
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
 static void auide_dma_timeout(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = HWIF(drive);
 
        printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
 
-       if (hwif->ide_dma_test_irq(drive))
+       if (auide_dma_test_irq(drive))
                return;
 
-       hwif->ide_dma_end(drive);
+       auide_dma_end(drive);
 }
-                                       
 
-static int auide_ddma_init(_auide_hwif *auide) {
-       
+static const struct ide_dma_ops au1xxx_dma_ops = {
+       .dma_host_set           = auide_dma_host_set,
+       .dma_setup              = auide_dma_setup,
+       .dma_exec_cmd           = auide_dma_exec_cmd,
+       .dma_start              = auide_dma_start,
+       .dma_end                = auide_dma_end,
+       .dma_test_irq           = auide_dma_test_irq,
+       .dma_lost_irq           = auide_dma_lost_irq,
+       .dma_timeout            = auide_dma_timeout,
+};
+
+static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
+{
+       _auide_hwif *auide = (_auide_hwif *)hwif->hwif_data;
        dbdev_tab_t source_dev_tab, target_dev_tab;
        u32 dev_id, tsize, devwidth, flags;
-       ide_hwif_t *hwif = auide->hwif;
 
        dev_id   = AU1XXX_ATA_DDMA_REQ;
 
-       if (auide->white_list || auide->black_list) {
-               tsize    = 8;
-               devwidth = 32;
-       }
-       else { 
-               tsize    = 1;
-               devwidth = 16;
-               
-               printk(KERN_ERR "au1xxx-ide: %s is not on ide driver whitelist.\n",auide_hwif.drive->id->model);
-               printk(KERN_ERR "            please read 'Documentation/mips/AU1xxx_IDE.README'");
-       }
+       tsize    =  8; /*  1 */
+       devwidth = 32; /* 16 */
 
 #ifdef IDE_AU1XXX_BURSTMODE 
        flags = DEV_FLAGS_SYNC | DEV_FLAGS_BURSTABLE;
@@ -482,9 +452,9 @@ static int auide_ddma_init(_auide_hwif *auide) {
        return 0;
 } 
 #else
-static int auide_ddma_init( _auide_hwif *auide )
+static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
 {
+       _auide_hwif *auide = (_auide_hwif *)hwif->hwif_data;
        dbdev_tab_t source_dev_tab;
        int flags;
 
@@ -532,20 +502,28 @@ static int auide_ddma_init( _auide_hwif *auide )
 static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif)
 {
        int i;
-       unsigned long *ata_regs = hw->io_ports;
+       unsigned long *ata_regs = hw->io_ports_array;
 
        /* FIXME? */
-       for (i = 0; i < IDE_CONTROL_OFFSET; i++) {
+       for (i = 0; i < 8; i++)
                *ata_regs++ = ahwif->regbase + (i << AU1XXX_ATA_REG_OFFSET);
-       }
 
        /* set the Alternative Status register */
        *ata_regs = ahwif->regbase + (14 << AU1XXX_ATA_REG_OFFSET);
 }
 
+static const struct ide_port_ops au1xxx_port_ops = {
+       .set_pio_mode           = au1xxx_set_pio_mode,
+       .set_dma_mode           = auide_set_dma_mode,
+};
+
 static const struct ide_port_info au1xxx_port_info = {
+       .init_dma               = auide_ddma_init,
+       .port_ops               = &au1xxx_port_ops,
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+       .dma_ops                = &au1xxx_dma_ops,
+#endif
        .host_flags             = IDE_HFLAG_POST_SET_MODE |
-                                 IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
                                  IDE_HFLAG_NO_IO_32BIT |
                                  IDE_HFLAG_UNMASK_IRQS,
        .pio_mask               = ATA_PIO4,
@@ -599,9 +577,11 @@ static int au_ide_probe(struct device *dev)
                goto out;
        }
 
-       /* FIXME:  This might possibly break PCMCIA IDE devices */
-
-       hwif                            = &ide_hwifs[pdev->id];
+       hwif = ide_find_port();
+       if (hwif == NULL) {
+               ret = -ENOENT;
+               goto out;
+       }
 
        memset(&hw, 0, sizeof(hw));
        auide_setup_ports(&hw, ahwif);
@@ -613,8 +593,6 @@ static int au_ide_probe(struct device *dev)
 
        hwif->dev = dev;
 
-       hwif->mmio  = 1;
-
        /* If the user has selected DDMA assisted copies,
           then set up a few local I/O function entry points 
        */
@@ -623,34 +601,12 @@ static int au_ide_probe(struct device *dev)
        hwif->INSW                      = auide_insw;
        hwif->OUTSW                     = auide_outsw;
 #endif
-
-       hwif->set_pio_mode              = &au1xxx_set_pio_mode;
-       hwif->set_dma_mode              = &auide_set_dma_mode;
-
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-       hwif->dma_timeout               = &auide_dma_timeout;
-
-       hwif->mdma_filter               = &auide_mdma_filter;
-
-       hwif->dma_host_set              = &auide_dma_host_set;
-       hwif->dma_exec_cmd              = &auide_dma_exec_cmd;
-       hwif->dma_start                 = &auide_dma_start;
-       hwif->ide_dma_end               = &auide_dma_end;
-       hwif->dma_setup                 = &auide_dma_setup;
-       hwif->ide_dma_test_irq          = &auide_dma_test_irq;
-       hwif->dma_lost_irq              = &auide_dma_lost_irq;
-#endif
        hwif->select_data               = 0;    /* no chipset-specific code */
        hwif->config_data               = 0;    /* no chipset-specific code */
 
        auide_hwif.hwif                 = hwif;
        hwif->hwif_data                 = &auide_hwif;
 
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA           
-       auide_ddma_init(&auide_hwif);
-       dbdma_init_done = 1;
-#endif
-
        idx[0] = hwif->index;
 
        ide_device_add(idx, &au1xxx_port_info);
@@ -670,7 +626,7 @@ static int au_ide_remove(struct device *dev)
        ide_hwif_t *hwif = dev_get_drvdata(dev);
        _auide_hwif *ahwif = &auide_hwif;
 
-       ide_unregister(hwif->index);
+       ide_unregister(hwif);
 
        iounmap((void *)ahwif->regbase);
 
index 956259fc09ba079ced2db086cdf6fbf6a63fcab5..68947626e4aaa40bde14c333c9ca7dcaef21713e 100644 (file)
@@ -76,17 +76,12 @@ static int __devinit swarm_ide_probe(struct device *dev)
        if (!SIBYTE_HAVE_IDE)
                return -ENODEV;
 
-       /* Find an empty slot.  */
-       for (i = 0; i < MAX_HWIFS; i++)
-               if (!ide_hwifs[i].io_ports[IDE_DATA_OFFSET])
-                       break;
-       if (i >= MAX_HWIFS) {
+       hwif = ide_find_port();
+       if (hwif == NULL) {
                printk(KERN_ERR DRV_NAME ": no free slot for interface\n");
                return -ENOMEM;
        }
 
-       hwif = ide_hwifs + i;
-
        base = ioremap(A_IO_EXT_BASE, 0x800);
        offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS));
        size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS));
@@ -115,15 +110,13 @@ static int __devinit swarm_ide_probe(struct device *dev)
 
        /* Setup MMIO ops.  */
        default_hwif_mmiops(hwif);
-       /* Prevent resource map manipulation.  */
-       hwif->mmio = 1;
+
        hwif->chipset = ide_generic;
-       hwif->noprobe = 0;
 
-       for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
-               hwif->io_ports[i] =
+       for (i = 0; i <= 7; i++)
+               hwif->io_ports_array[i] =
                                (unsigned long)(base + ((0x1f0 + i) << 5));
-       hwif->io_ports[IDE_CONTROL_OFFSET] =
+       hwif->io_ports.ctl_addr =
                                (unsigned long)(base + (0x3f6 << 5));
        hwif->irq = K_INT_GB_IDE;
 
index cfb3265bc1a8764befa33b60ca8b5ed23057260b..7f46c224b7c40f0f2091eea99a0be2f193d44921 100644 (file)
@@ -135,12 +135,12 @@ static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
 
 static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-       drive->hwif->set_dma_mode(drive, pio + XFER_PIO_0);
+       drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0);
 }
 
 static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const char *name)
 {
-       int bus_speed = system_bus_clock();
+       int bus_speed = ide_pci_clk ? ide_pci_clk : system_bus_clock();
 
        if (bus_speed <= 33)
                pci_set_drvdata(dev, (void *) aec6xxx_33_base);
@@ -175,27 +175,23 @@ static u8 __devinit atp86x_cable_detect(ide_hwif_t *hwif)
        return (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 }
 
-static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-       hwif->set_pio_mode = &aec_set_pio_mode;
-
-       if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
-               hwif->set_dma_mode = &aec6210_set_mode;
-       else {
-               hwif->set_dma_mode = &aec6260_set_mode;
+static const struct ide_port_ops atp850_port_ops = {
+       .set_pio_mode           = aec_set_pio_mode,
+       .set_dma_mode           = aec6210_set_mode,
+};
 
-               hwif->cable_detect = atp86x_cable_detect;
-       }
-}
+static const struct ide_port_ops atp86x_port_ops = {
+       .set_pio_mode           = aec_set_pio_mode,
+       .set_dma_mode           = aec6260_set_mode,
+       .cable_detect           = atp86x_cable_detect,
+};
 
 static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
        {       /* 0 */
                .name           = "AEC6210",
                .init_chipset   = init_chipset_aec62xx,
-               .init_hwif      = init_hwif_aec62xx,
                .enablebits     = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+               .port_ops       = &atp850_port_ops,
                .host_flags     = IDE_HFLAG_SERIALIZE |
                                  IDE_HFLAG_NO_ATAPI_DMA |
                                  IDE_HFLAG_NO_DSC |
@@ -207,7 +203,7 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
        },{     /* 1 */
                .name           = "AEC6260",
                .init_chipset   = init_chipset_aec62xx,
-               .init_hwif      = init_hwif_aec62xx,
+               .port_ops       = &atp86x_port_ops,
                .host_flags     = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_AUTODMA |
                                  IDE_HFLAG_ABUSE_SET_DMA_MODE |
                                  IDE_HFLAG_OFF_BOARD,
@@ -217,17 +213,18 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
        },{     /* 2 */
                .name           = "AEC6260R",
                .init_chipset   = init_chipset_aec62xx,
-               .init_hwif      = init_hwif_aec62xx,
                .enablebits     = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+               .port_ops       = &atp86x_port_ops,
                .host_flags     = IDE_HFLAG_NO_ATAPI_DMA |
-                                 IDE_HFLAG_ABUSE_SET_DMA_MODE,
+                                 IDE_HFLAG_ABUSE_SET_DMA_MODE |
+                                 IDE_HFLAG_NON_BOOTABLE,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA4,
        },{     /* 3 */
                .name           = "AEC6280",
                .init_chipset   = init_chipset_aec62xx,
-               .init_hwif      = init_hwif_aec62xx,
+               .port_ops       = &atp86x_port_ops,
                .host_flags     = IDE_HFLAG_NO_ATAPI_DMA |
                                  IDE_HFLAG_ABUSE_SET_DMA_MODE |
                                  IDE_HFLAG_OFF_BOARD,
@@ -237,8 +234,8 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
        },{     /* 4 */
                .name           = "AEC6280R",
                .init_chipset   = init_chipset_aec62xx,
-               .init_hwif      = init_hwif_aec62xx,
                .enablebits     = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+               .port_ops       = &atp86x_port_ops,
                .host_flags     = IDE_HFLAG_NO_ATAPI_DMA |
                                  IDE_HFLAG_ABUSE_SET_DMA_MODE |
                                  IDE_HFLAG_OFF_BOARD,
index b3b6f514ce2d8ac4d5775ebddb353f4907ca4460..b36a22b8c213807a1966595eafc68adf463a75ba 100644 (file)
@@ -38,8 +38,6 @@
 
 #include <asm/io.h>
 
-#define DISPLAY_ALI_TIMINGS
-
 /*
  *     ALi devices are not plug in. Otherwise these static values would
  *     need to go. They ought to go away anyway
@@ -49,236 +47,6 @@ static u8 m5229_revision;
 static u8 chip_is_1543c_e;
 static struct pci_dev *isa_dev;
 
-#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 ali_proc = 0;
-
-static struct pci_dev *bmide_dev;
-
-static char *fifo[4] = {
-       "FIFO Off",
-       "FIFO On ",
-       "DMA mode",
-       "PIO mode" };
-
-static char *udmaT[8] = {
-       "1.5T",
-       "  2T",
-       "2.5T",
-       "  3T",
-       "3.5T",
-       "  4T",
-       "  6T",
-       "  8T"
-};
-
-static char *channel_status[8] = {
-       "OK            ",
-       "busy          ",
-       "DRQ           ",
-       "DRQ busy      ",
-       "error         ",
-       "error busy    ",
-       "error DRQ     ",
-       "error DRQ busy"
-};
-
-/**
- *     ali_get_info            -       generate proc file for ALi IDE
- *     @buffer: buffer to fill
- *     @addr: address of user start in buffer
- *     @offset: offset into 'file'
- *     @count: buffer count
- *
- *     Walks the Ali devices and outputs summary data on the tuning and
- *     anything else that will help with debugging
- */
-static int ali_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-       unsigned long bibma;
-       u8 reg53h, reg5xh, reg5yh, reg5xh1, reg5yh1, c0, c1, rev, tmp;
-       char *q, *p = buffer;
-
-       /* fetch rev. */
-       pci_read_config_byte(bmide_dev, 0x08, &rev);
-       if (rev >= 0xc1)        /* M1543C or newer */
-               udmaT[7] = " ???";
-       else
-               fifo[3]  = "   ???  ";
-
-       /* first fetch bibma: */
-       
-       bibma = pci_resource_start(bmide_dev, 4);
-
-       /*
-        * at that point bibma+0x2 et bibma+0xa are byte
-        * registers to investigate:
-        */
-       c0 = inb(bibma + 0x02);
-       c1 = inb(bibma + 0x0a);
-
-       p += sprintf(p,
-               "\n                                Ali M15x3 Chipset.\n");
-       p += sprintf(p,
-               "                                ------------------\n");
-       pci_read_config_byte(bmide_dev, 0x78, &reg53h);
-       p += sprintf(p, "PCI Clock: %d.\n", reg53h);
-
-       pci_read_config_byte(bmide_dev, 0x53, &reg53h);
-       p += sprintf(p,
-               "CD_ROM FIFO:%s, CD_ROM DMA:%s\n",
-               (reg53h & 0x02) ? "Yes" : "No ",
-               (reg53h & 0x01) ? "Yes" : "No " );
-       pci_read_config_byte(bmide_dev, 0x74, &reg53h);
-       p += sprintf(p,
-               "FIFO Status: contains %d Words, runs%s%s\n\n",
-               (reg53h & 0x3f),
-               (reg53h & 0x40) ? " OVERWR" : "",
-               (reg53h & 0x80) ? " OVERRD." : "." );
-
-       p += sprintf(p,
-               "-------------------primary channel"
-               "-------------------secondary channel"
-               "---------\n\n");
-
-       pci_read_config_byte(bmide_dev, 0x09, &reg53h);
-       p += sprintf(p,
-               "channel status:       %s"
-               "                               %s\n",
-               (reg53h & 0x20) ? "On " : "Off",
-               (reg53h & 0x10) ? "On " : "Off" );
-
-       p += sprintf(p,
-               "both channels togth:  %s"
-               "                               %s\n",
-               (c0&0x80) ? "No " : "Yes",
-               (c1&0x80) ? "No " : "Yes" );
-
-       pci_read_config_byte(bmide_dev, 0x76, &reg53h);
-       p += sprintf(p,
-               "Channel state:        %s                    %s\n",
-               channel_status[reg53h & 0x07],
-               channel_status[(reg53h & 0x70) >> 4] );
-
-       pci_read_config_byte(bmide_dev, 0x58, &reg5xh);
-       pci_read_config_byte(bmide_dev, 0x5c, &reg5yh);
-       p += sprintf(p,
-               "Add. Setup Timing:    %dT"
-               "                                %dT\n",
-               (reg5xh & 0x07) ? (reg5xh & 0x07) : 8,
-               (reg5yh & 0x07) ? (reg5yh & 0x07) : 8 );
-
-       pci_read_config_byte(bmide_dev, 0x59, &reg5xh);
-       pci_read_config_byte(bmide_dev, 0x5d, &reg5yh);
-       p += sprintf(p,
-               "Command Act. Count:   %dT"
-               "                                %dT\n"
-               "Command Rec. Count:   %dT"
-               "                               %dT\n\n",
-               (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8,
-               (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, 
-               (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16,
-               (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16 );
-
-       p += sprintf(p,
-               "----------------drive0-----------drive1"
-               "------------drive0-----------drive1------\n\n");
-       p += sprintf(p,
-               "DMA enabled:      %s              %s"
-               "               %s              %s\n",
-               (c0&0x20) ? "Yes" : "No ",
-               (c0&0x40) ? "Yes" : "No ",
-               (c1&0x20) ? "Yes" : "No ",
-               (c1&0x40) ? "Yes" : "No " );
-
-       pci_read_config_byte(bmide_dev, 0x54, &reg5xh);
-       pci_read_config_byte(bmide_dev, 0x55, &reg5yh);
-       q = "FIFO threshold:   %2d Words         %2d Words"
-               "          %2d Words         %2d Words\n";
-       if (rev < 0xc1) {
-               if ((rev == 0x20) &&
-                   (pci_read_config_byte(bmide_dev, 0x4f, &tmp), (tmp &= 0x20))) {
-                       p += sprintf(p, q, 8, 8, 8, 8);
-               } else {
-                       p += sprintf(p, q,
-                               (reg5xh & 0x03) + 12,
-                               ((reg5xh & 0x30)>>4) + 12,
-                               (reg5yh & 0x03) + 12,
-                               ((reg5yh & 0x30)>>4) + 12 );
-               }
-       } else {
-               int t1 = (tmp = (reg5xh & 0x03)) ? (tmp << 3) : 4;
-               int t2 = (tmp = ((reg5xh & 0x30)>>4)) ? (tmp << 3) : 4;
-               int t3 = (tmp = (reg5yh & 0x03)) ? (tmp << 3) : 4;
-               int t4 = (tmp = ((reg5yh & 0x30)>>4)) ? (tmp << 3) : 4;
-               p += sprintf(p, q, t1, t2, t3, t4);
-       }
-
-#if 0
-       p += sprintf(p, 
-               "FIFO threshold:   %2d Words         %2d Words"
-               "          %2d Words         %2d Words\n",
-               (reg5xh & 0x03) + 12,
-               ((reg5xh & 0x30)>>4) + 12,
-               (reg5yh & 0x03) + 12,
-               ((reg5yh & 0x30)>>4) + 12 );
-#endif
-
-       p += sprintf(p,
-               "FIFO mode:        %s         %s          %s         %s\n",
-               fifo[((reg5xh & 0x0c) >> 2)],
-               fifo[((reg5xh & 0xc0) >> 6)],
-               fifo[((reg5yh & 0x0c) >> 2)],
-               fifo[((reg5yh & 0xc0) >> 6)] );
-
-       pci_read_config_byte(bmide_dev, 0x5a, &reg5xh);
-       pci_read_config_byte(bmide_dev, 0x5b, &reg5xh1);
-       pci_read_config_byte(bmide_dev, 0x5e, &reg5yh);
-       pci_read_config_byte(bmide_dev, 0x5f, &reg5yh1);
-
-       p += sprintf(p,/*
-               "------------------drive0-----------drive1"
-               "------------drive0-----------drive1------\n")*/
-               "Dt RW act. Cnt    %2dT              %2dT"
-               "               %2dT              %2dT\n"
-               "Dt RW rec. Cnt    %2dT              %2dT"
-               "               %2dT              %2dT\n\n",
-               (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8,
-               (reg5xh1 & 0x70) ? ((reg5xh1 & 0x70) >> 4) : 8,
-               (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8,
-               (reg5yh1 & 0x70) ? ((reg5yh1 & 0x70) >> 4) : 8,
-               (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16,
-               (reg5xh1 & 0x0f) ? (reg5xh1 & 0x0f) : 16,
-               (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16,
-               (reg5yh1 & 0x0f) ? (reg5yh1 & 0x0f) : 16 );
-
-       p += sprintf(p,
-               "-----------------------------------UDMA Timings"
-               "--------------------------------\n\n");
-
-       pci_read_config_byte(bmide_dev, 0x56, &reg5xh);
-       pci_read_config_byte(bmide_dev, 0x57, &reg5yh);
-       p += sprintf(p,
-               "UDMA:             %s               %s"
-               "                %s               %s\n"
-               "UDMA timings:     %s             %s"
-               "              %s             %s\n\n",
-               (reg5xh & 0x08) ? "OK" : "No",
-               (reg5xh & 0x80) ? "OK" : "No",
-               (reg5yh & 0x08) ? "OK" : "No",
-               (reg5yh & 0x80) ? "OK" : "No",
-               udmaT[(reg5xh & 0x07)],
-               udmaT[(reg5xh & 0x70) >> 4],
-               udmaT[reg5yh & 0x07],
-               udmaT[(reg5yh & 0x70) >> 4] );
-
-       return p-buffer; /* => must be less than 4k! */
-}
-#endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */
-
 /**
  *     ali_set_pio_mode        -       set host controller for PIO mode
  *     @drive: drive
@@ -294,7 +62,7 @@ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
        int s_time, a_time, c_time;
        u8 s_clc, a_clc, r_clc;
        unsigned long flags;
-       int bus_speed = system_bus_clock();
+       int bus_speed = ide_pci_clk ? ide_pci_clk : system_bus_clock();
        int port = hwif->channel ? 0x5c : 0x58;
        int portFIFO = hwif->channel ? 0x55 : 0x54;
        u8 cd_dma_fifo = 0;
@@ -465,14 +233,6 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c
 
        isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
 
-#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
-       if (!ali_proc) {
-               ali_proc = 1;
-               bmide_dev = dev;
-               ide_pci_create_host_proc("ali", ali_get_info);
-       }
-#endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */
-
        local_irq_save(flags);
 
        if (m5229_revision < 0xC2) {
@@ -610,7 +370,7 @@ static int ali_cable_override(struct pci_dev *pdev)
 }
 
 /**
- *     ata66_ali15x3   -       check for UDMA 66 support
+ *     ali_cable_detect        -       cable detection
  *     @hwif: IDE interface
  *
  *     This checks if the controller and the cable are capable
@@ -620,7 +380,7 @@ static int ali_cable_override(struct pci_dev *pdev)
  *     FIXME: frobs bits that are not defined on newer ALi devicea
  */
 
-static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif)
+static u8 __devinit ali_cable_detect(ide_hwif_t *hwif)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
        unsigned long flags;
@@ -652,27 +412,7 @@ static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif)
        return cbl;
 }
 
-/**
- *     init_hwif_common_ali15x3        -       Set up ALI IDE hardware
- *     @hwif: IDE interface
- *
- *     Initialize the IDE structure side of the ALi 15x3 driver.
- */
-static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif)
-{
-       hwif->set_pio_mode = &ali_set_pio_mode;
-       hwif->set_dma_mode = &ali_set_dma_mode;
-       hwif->udma_filter = &ali_udma_filter;
-
-       hwif->cable_detect = ata66_ali15x3;
-
-       if (hwif->dma_base == 0)
-               return;
-
-       hwif->dma_setup = &ali15x3_dma_setup;
-}
-
+#ifndef CONFIG_SPARC64
 /**
  *     init_hwif_ali15x3       -       Initialize the ALI IDE x86 stuff
  *     @hwif: interface to configure
@@ -722,35 +462,66 @@ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
                if(irq >= 0)
                        hwif->irq = irq;
        }
-
-       init_hwif_common_ali15x3(hwif);
 }
+#endif
 
 /**
  *     init_dma_ali15x3        -       set up DMA on ALi15x3
  *     @hwif: IDE interface
- *     @dmabase: DMA interface base PCI address
+ *     @d: IDE port info
  *
- *     Set up the DMA functionality on the ALi 15x3. For the ALi
- *     controllers this is generic so we can let the generic code do
- *     the actual work.
+ *     Set up the DMA functionality on the ALi 15x3.
  */
 
-static void __devinit init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase)
+static int __devinit init_dma_ali15x3(ide_hwif_t *hwif,
+                                     const struct ide_port_info *d)
 {
-       if (m5229_revision < 0x20)
-               return;
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       unsigned long base = ide_pci_dma_base(hwif, d);
+
+       if (base == 0 || ide_pci_set_master(dev, d->name) < 0)
+               return -1;
+
        if (!hwif->channel)
-               outb(inb(dmabase + 2) & 0x60, dmabase + 2);
-       ide_setup_dma(hwif, dmabase);
+               outb(inb(base + 2) & 0x60, base + 2);
+
+       printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx\n",
+                        hwif->name, base, base + 7);
+
+       if (ide_allocate_dma_engine(hwif))
+               return -1;
+
+       ide_setup_dma(hwif, base);
+
+       return 0;
 }
 
+static const struct ide_port_ops ali_port_ops = {
+       .set_pio_mode           = ali_set_pio_mode,
+       .set_dma_mode           = ali_set_dma_mode,
+       .udma_filter            = ali_udma_filter,
+       .cable_detect           = ali_cable_detect,
+};
+
+static const struct ide_dma_ops ali_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ali15x3_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = ide_dma_start,
+       .dma_end                = __ide_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
 static const struct ide_port_info ali15x3_chipset __devinitdata = {
        .name           = "ALI15X3",
        .init_chipset   = init_chipset_ali15x3,
+#ifndef CONFIG_SPARC64
        .init_hwif      = init_hwif_ali15x3,
+#endif
        .init_dma       = init_dma_ali15x3,
-       .host_flags     = IDE_HFLAG_BOOTABLE,
+       .port_ops       = &ali_port_ops,
        .pio_mask       = ATA_PIO5,
        .swdma_mask     = ATA_SWDMA2,
        .mwdma_mask     = ATA_MWDMA2,
@@ -793,14 +564,17 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev
                        d.udma_mask = ATA_UDMA5;
                else
                        d.udma_mask = ATA_UDMA6;
+
+               d.dma_ops = &ali_dma_ops;
+       } else {
+               d.host_flags |= IDE_HFLAG_NO_DMA;
+
+               d.mwdma_mask = d.swdma_mask = 0;
        }
 
        if (idx == 0)
                d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
 
-#if defined(CONFIG_SPARC64)
-       d.init_hwif = init_hwif_common_ali15x3;
-#endif /* CONFIG_SPARC64 */
        return ide_setup_pci_device(dev, &d);
 }
 
index 2ef890ce80976fa83e6667f80ade5689df0899dc..efcf54338be7b9c63543f496f3548d71d8825be2 100644 (file)
@@ -179,7 +179,7 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev,
  * Determine the system bus clock.
  */
 
-       amd_clock = system_bus_clock() * 1000;
+       amd_clock = (ide_pci_clk ? ide_pci_clk : system_bus_clock()) * 1000;
 
        switch (amd_clock) {
                case 33000: amd_clock = 33333; break;
@@ -210,21 +210,20 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
 
        if (hwif->irq == 0) /* 0 is bogus but will do for now */
                hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel);
-
-       hwif->set_pio_mode = &amd_set_pio_mode;
-       hwif->set_dma_mode = &amd_set_drive;
-
-       hwif->cable_detect = amd_cable_detect;
 }
 
+static const struct ide_port_ops amd_port_ops = {
+       .set_pio_mode           = amd_set_pio_mode,
+       .set_dma_mode           = amd_set_drive,
+       .cable_detect           = amd_cable_detect,
+};
+
 #define IDE_HFLAGS_AMD \
        (IDE_HFLAG_PIO_NO_BLACKLIST | \
-        IDE_HFLAG_PIO_NO_DOWNGRADE | \
         IDE_HFLAG_ABUSE_SET_DMA_MODE | \
         IDE_HFLAG_POST_SET_MODE | \
         IDE_HFLAG_IO_32BIT | \
-        IDE_HFLAG_UNMASK_IRQS | \
-        IDE_HFLAG_BOOTABLE)
+        IDE_HFLAG_UNMASK_IRQS)
 
 #define DECLARE_AMD_DEV(name_str, swdma, udma)                         \
        {                                                               \
@@ -232,6 +231,7 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
                .init_chipset   = init_chipset_amd74xx,                 \
                .init_hwif      = init_hwif_amd74xx,                    \
                .enablebits     = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, \
+               .port_ops       = &amd_port_ops,                        \
                .host_flags     = IDE_HFLAGS_AMD,                       \
                .pio_mask       = ATA_PIO5,                             \
                .swdma_mask     = swdma,                                \
@@ -245,6 +245,7 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
                .init_chipset   = init_chipset_amd74xx,                 \
                .init_hwif      = init_hwif_amd74xx,                    \
                .enablebits     = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, \
+               .port_ops       = &amd_port_ops,                        \
                .host_flags     = IDE_HFLAGS_AMD,                       \
                .pio_mask       = ATA_PIO5,                             \
                .swdma_mask     = ATA_SWDMA2,                           \
index 7e037c880cb0a62279f22dfc4654ef05ab446982..8b637181681ad2d6d4cfcbf30c39d6e6044b9bc6 100644 (file)
@@ -130,37 +130,26 @@ static u8 __devinit atiixp_cable_detect(ide_hwif_t *hwif)
                return ATA_CBL_PATA40;
 }
 
-/**
- *     init_hwif_atiixp                -       fill in the hwif for the ATIIXP
- *     @hwif: IDE interface
- *
- *     Set up the ide_hwif_t for the ATIIXP interface according to the
- *     capabilities of the hardware.
- */
-
-static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
-{
-       hwif->set_pio_mode = &atiixp_set_pio_mode;
-       hwif->set_dma_mode = &atiixp_set_dma_mode;
-
-       hwif->cable_detect = atiixp_cable_detect;
-}
+static const struct ide_port_ops atiixp_port_ops = {
+       .set_pio_mode           = atiixp_set_pio_mode,
+       .set_dma_mode           = atiixp_set_dma_mode,
+       .cable_detect           = atiixp_cable_detect,
+};
 
 static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
        {       /* 0 */
                .name           = "ATIIXP",
-               .init_hwif      = init_hwif_atiixp,
                .enablebits     = {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
-               .host_flags     = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
+               .port_ops       = &atiixp_port_ops,
+               .host_flags     = IDE_HFLAG_LEGACY_IRQS,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA5,
        },{     /* 1 */
                .name           = "SB600_PATA",
-               .init_hwif      = init_hwif_atiixp,
                .enablebits     = {{0x48,0x01,0x00}, {0x00,0x00,0x00}},
-               .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS |
-                                 IDE_HFLAG_BOOTABLE,
+               .port_ops       = &atiixp_port_ops,
+               .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA5,
index a1cfe033a55f5ac5b42150c32118123ea7320229..aaf38109eaecef95de0bdfd363bc92f514b62b9a 100644 (file)
@@ -4,7 +4,7 @@
 
 /*
  *  Original authors:  abramov@cecmow.enet.dec.com (Igor Abramov)
- *                     mlord@pobox.com (Mark Lord)
+ *                     mlord@pobox.com (Mark Lord)
  *
  *  See linux/MAINTAINERS for address of current maintainer.
  *
@@ -98,7 +98,7 @@
 
 #define CMD640_PREFETCH_MASKS 1
 
-//#define CMD640_DUMP_REGS
+/*#define CMD640_DUMP_REGS */
 
 #include <linux/types.h>
 #include <linux/kernel.h>
 
 #include <asm/io.h>
 
-/*
- * This flag is set in ide.c by the parameter:  ide0=cmd640_vlb
- */
-int cmd640_vlb = 0;
+#define DRV_NAME "cmd640"
+
+static int cmd640_vlb;
 
 /*
  * CMD640 specific registers definition.
@@ -185,7 +184,6 @@ static DEFINE_SPINLOCK(cmd640_lock);
  * These are initialized to point at the devices we control
  */
 static ide_hwif_t  *cmd_hwif0, *cmd_hwif1;
-static ide_drive_t *cmd_drives[4];
 
 /*
  * Interface to access cmd640x registers
@@ -207,13 +205,13 @@ static unsigned int cmd640_chip_version;
 
 /* PCI method 1 access */
 
-static void put_cmd640_reg_pci1 (u16 reg, u8 val)
+static void put_cmd640_reg_pci1(u16 reg, u8 val)
 {
        outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
        outb_p(val, (reg & 3) | 0xcfc);
 }
 
-static u8 get_cmd640_reg_pci1 (u16 reg)
+static u8 get_cmd640_reg_pci1(u16 reg)
 {
        outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
        return inb_p((reg & 3) | 0xcfc);
@@ -221,14 +219,14 @@ static u8 get_cmd640_reg_pci1 (u16 reg)
 
 /* PCI method 2 access (from CMD datasheet) */
 
-static void put_cmd640_reg_pci2 (u16 reg, u8 val)
+static void put_cmd640_reg_pci2(u16 reg, u8 val)
 {
        outb_p(0x10, 0xcf8);
        outb_p(val, cmd640_key + reg);
        outb_p(0, 0xcf8);
 }
 
-static u8 get_cmd640_reg_pci2 (u16 reg)
+static u8 get_cmd640_reg_pci2(u16 reg)
 {
        u8 b;
 
@@ -240,13 +238,13 @@ static u8 get_cmd640_reg_pci2 (u16 reg)
 
 /* VLB access */
 
-static void put_cmd640_reg_vlb (u16 reg, u8 val)
+static void put_cmd640_reg_vlb(u16 reg, u8 val)
 {
        outb_p(reg, cmd640_key);
        outb_p(val, cmd640_key + 4);
 }
 
-static u8 get_cmd640_reg_vlb (u16 reg)
+static u8 get_cmd640_reg_vlb(u16 reg)
 {
        outb_p(reg, cmd640_key);
        return inb_p(cmd640_key + 4);
@@ -268,11 +266,11 @@ static void put_cmd640_reg(u16 reg, u8 val)
        unsigned long flags;
 
        spin_lock_irqsave(&cmd640_lock, flags);
-       __put_cmd640_reg(reg,val);
+       __put_cmd640_reg(reg, val);
        spin_unlock_irqrestore(&cmd640_lock, flags);
 }
 
-static int __init match_pci_cmd640_device (void)
+static int __init match_pci_cmd640_device(void)
 {
        const u8 ven_dev[4] = {0x95, 0x10, 0x40, 0x06};
        unsigned int i;
@@ -292,7 +290,7 @@ static int __init match_pci_cmd640_device (void)
 /*
  * Probe for CMD640x -- pci method 1
  */
-static int __init probe_for_cmd640_pci1 (void)
+static int __init probe_for_cmd640_pci1(void)
 {
        __get_cmd640_reg = get_cmd640_reg_pci1;
        __put_cmd640_reg = put_cmd640_reg_pci1;
@@ -308,7 +306,7 @@ static int __init probe_for_cmd640_pci1 (void)
 /*
  * Probe for CMD640x -- pci method 2
  */
-static int __init probe_for_cmd640_pci2 (void)
+static int __init probe_for_cmd640_pci2(void)
 {
        __get_cmd640_reg = get_cmd640_reg_pci2;
        __put_cmd640_reg = put_cmd640_reg_pci2;
@@ -322,7 +320,7 @@ static int __init probe_for_cmd640_pci2 (void)
 /*
  * Probe for CMD640x -- vlb
  */
-static int __init probe_for_cmd640_vlb (void)
+static int __init probe_for_cmd640_vlb(void)
 {
        u8 b;
 
@@ -343,18 +341,18 @@ static int __init probe_for_cmd640_vlb (void)
  *  Returns 1 if an IDE interface/drive exists at 0x170,
  *  Returns 0 otherwise.
  */
-static int __init secondary_port_responding (void)
+static int __init secondary_port_responding(void)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&cmd640_lock, flags);
 
-       outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET);        /* select drive0 */
+       outb_p(0x0a, 0x176);    /* select drive0 */
        udelay(100);
-       if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x0a) {
-               outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */
+       if ((inb_p(0x176) & 0x1f) != 0x0a) {
+               outb_p(0x1a, 0x176); /* select drive1 */
                udelay(100);
-               if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) {
+               if ((inb_p(0x176) & 0x1f) != 0x1a) {
                        spin_unlock_irqrestore(&cmd640_lock, flags);
                        return 0; /* nothing responded */
                }
@@ -367,7 +365,7 @@ static int __init secondary_port_responding (void)
 /*
  * Dump out all cmd640 registers.  May be called from ide.c
  */
-static void cmd640_dump_regs (void)
+static void cmd640_dump_regs(void)
 {
        unsigned int reg = cmd640_vlb ? 0x50 : 0x00;
 
@@ -382,13 +380,13 @@ static void cmd640_dump_regs (void)
 }
 #endif
 
+#ifndef CONFIG_BLK_DEV_CMD640_ENHANCED
 /*
  * Check whether prefetch is on for a drive,
  * and initialize the unmask flags for safe operation.
  */
-static void __init check_prefetch (unsigned int index)
+static void __init check_prefetch(ide_drive_t *drive, unsigned int index)
 {
-       ide_drive_t *drive = cmd_drives[index];
        u8 b = get_cmd640_reg(prefetch_regs[index]);
 
        if (b & prefetch_masks[index]) {        /* is prefetch off? */
@@ -403,29 +401,12 @@ static void __init check_prefetch (unsigned int index)
                drive->no_io_32bit = 0;
        }
 }
-
-/*
- * Figure out which devices we control
- */
-static void __init setup_device_ptrs (void)
-{
-       cmd_hwif0 = &ide_hwifs[0];
-       cmd_hwif1 = &ide_hwifs[1];
-
-       cmd_drives[0] = &cmd_hwif0->drives[0];
-       cmd_drives[1] = &cmd_hwif0->drives[1];
-       cmd_drives[2] = &cmd_hwif1->drives[0];
-       cmd_drives[3] = &cmd_hwif1->drives[1];
-}
-
-#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
-
+#else
 /*
  * Sets prefetch mode for a drive.
  */
-static void set_prefetch_mode (unsigned int index, int mode)
+static void set_prefetch_mode(ide_drive_t *drive, unsigned int index, int mode)
 {
-       ide_drive_t *drive = cmd_drives[index];
        unsigned long flags;
        int reg = prefetch_regs[index];
        u8 b;
@@ -452,7 +433,7 @@ static void set_prefetch_mode (unsigned int index, int mode)
 /*
  * Dump out current drive clocks settings
  */
-static void display_clocks (unsigned int index)
+static void display_clocks(unsigned int index)
 {
        u8 active_count, recovery_count;
 
@@ -471,44 +452,16 @@ static void display_clocks (unsigned int index)
  * Pack active and recovery counts into single byte representation
  * used by controller
  */
-static inline u8 pack_nibbles (u8 upper, u8 lower)
+static inline u8 pack_nibbles(u8 upper, u8 lower)
 {
        return ((upper & 0x0f) << 4) | (lower & 0x0f);
 }
 
-/*
- * This routine retrieves the initial drive timings from the chipset.
- */
-static void __init retrieve_drive_counts (unsigned int index)
-{
-       u8 b;
-
-       /*
-        * Get the internal setup timing, and convert to clock count
-        */
-       b = get_cmd640_reg(arttim_regs[index]) & ~0x3f;
-       switch (b) {
-               case 0x00: b = 4; break;
-               case 0x80: b = 3; break;
-               case 0x40: b = 2; break;
-               default:   b = 5; break;
-       }
-       setup_counts[index] = b;
-
-       /*
-        * Get the active/recovery counts
-        */
-       b = get_cmd640_reg(drwtim_regs[index]);
-       active_counts[index]   = (b >> 4)   ? (b >> 4)   : 0x10;
-       recovery_counts[index] = (b & 0x0f) ? (b & 0x0f) : 0x10;
-}
-
-
 /*
  * This routine writes the prepared setup/active/recovery counts
  * for a drive into the cmd640 chipset registers to active them.
  */
-static void program_drive_counts (unsigned int index)
+static void program_drive_counts(ide_drive_t *drive, unsigned int index)
 {
        unsigned long flags;
        u8 setup_count    = setup_counts[index];
@@ -522,8 +475,11 @@ static void program_drive_counts (unsigned int index)
         * so we merge the timings, using the slowest value for each timing.
         */
        if (index > 1) {
-               unsigned int mate;
-               if (cmd_drives[mate = index ^ 1]->present) {
+               ide_hwif_t *hwif = drive->hwif;
+               ide_drive_t *peer = &hwif->drives[!drive->select.b.unit];
+               unsigned int mate = index ^ 1;
+
+               if (peer->present) {
                        if (setup_count < setup_counts[mate])
                                setup_count = setup_counts[mate];
                        if (active_count < active_counts[mate])
@@ -537,11 +493,11 @@ static void program_drive_counts (unsigned int index)
         * Convert setup_count to internal chipset representation
         */
        switch (setup_count) {
-               case 4:  setup_count = 0x00; break;
-               case 3:  setup_count = 0x80; break;
-               case 1:
-               case 2:  setup_count = 0x40; break;
-               default: setup_count = 0xc0; /* case 5 */
+       case 4:  setup_count = 0x00; break;
+       case 3:  setup_count = 0x80; break;
+       case 1:
+       case 2:  setup_count = 0x40; break;
+       default: setup_count = 0xc0; /* case 5 */
        }
 
        /*
@@ -562,11 +518,19 @@ static void program_drive_counts (unsigned int index)
 /*
  * Set a specific pio_mode for a drive
  */
-static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle_time)
+static void cmd640_set_mode(ide_drive_t *drive, unsigned int index,
+                           u8 pio_mode, unsigned int cycle_time)
 {
        int setup_time, active_time, recovery_time, clock_time;
        u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count;
-       int bus_speed = system_bus_clock();
+       int bus_speed;
+
+       if (cmd640_vlb && ide_vlb_clk)
+               bus_speed = ide_vlb_clk;
+       else if (!cmd640_vlb && ide_pci_clk)
+               bus_speed = ide_pci_clk;
+       else
+               bus_speed = system_bus_clock();
 
        if (pio_mode > 5)
                pio_mode = 5;
@@ -574,15 +538,15 @@ static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle
        active_time = ide_pio_timings[pio_mode].active_time;
        recovery_time = cycle_time - (setup_time + active_time);
        clock_time = 1000 / bus_speed;
-       cycle_count = (cycle_time + clock_time - 1) / clock_time;
+       cycle_count = DIV_ROUND_UP(cycle_time, clock_time);
 
-       setup_count = (setup_time + clock_time - 1) / clock_time;
+       setup_count = DIV_ROUND_UP(setup_time, clock_time);
 
-       active_count = (active_time + clock_time - 1) / clock_time;
+       active_count = DIV_ROUND_UP(active_time, clock_time);
        if (active_count < 2)
                active_count = 2; /* minimum allowed by cmd640 */
 
-       recovery_count = (recovery_time + clock_time - 1) / clock_time;
+       recovery_count = DIV_ROUND_UP(recovery_time, clock_time);
        recovery_count2 = cycle_count - (setup_count + active_count);
        if (recovery_count2 > recovery_count)
                recovery_count = recovery_count2;
@@ -611,7 +575,7 @@ static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle
         *      1) this is the wrong place to do it (proper is do_special() in ide.c)
         *      2) in practice this is rarely, if ever, necessary
         */
-       program_drive_counts (index);
+       program_drive_counts(drive, index);
 }
 
 static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
@@ -619,32 +583,26 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
        unsigned int index = 0, cycle_time;
        u8 b;
 
-       while (drive != cmd_drives[index]) {
-               if (++index > 3) {
-                       printk(KERN_ERR "%s: bad news in %s\n",
-                                       drive->name, __FUNCTION__);
-                       return;
-               }
-       }
        switch (pio) {
-               case 6: /* set fast-devsel off */
-               case 7: /* set fast-devsel on */
-                       b = get_cmd640_reg(CNTRL) & ~0x27;
-                       if (pio & 1)
-                               b |= 0x27;
-                       put_cmd640_reg(CNTRL, b);
-                       printk("%s: %sabled cmd640 fast host timing (devsel)\n", drive->name, (pio & 1) ? "en" : "dis");
-                       return;
-
-               case 8: /* set prefetch off */
-               case 9: /* set prefetch on */
-                       set_prefetch_mode(index, pio & 1);
-                       printk("%s: %sabled cmd640 prefetch\n", drive->name, (pio & 1) ? "en" : "dis");
-                       return;
+       case 6: /* set fast-devsel off */
+       case 7: /* set fast-devsel on */
+               b = get_cmd640_reg(CNTRL) & ~0x27;
+               if (pio & 1)
+                       b |= 0x27;
+               put_cmd640_reg(CNTRL, b);
+               printk("%s: %sabled cmd640 fast host timing (devsel)\n",
+                       drive->name, (pio & 1) ? "en" : "dis");
+               return;
+       case 8: /* set prefetch off */
+       case 9: /* set prefetch on */
+               set_prefetch_mode(drive, index, pio & 1);
+               printk("%s: %sabled cmd640 prefetch\n",
+                       drive->name, (pio & 1) ? "en" : "dis");
+               return;
        }
 
        cycle_time = ide_pio_cycle_time(drive, pio);
-       cmd640_set_mode(index, pio, cycle_time);
+       cmd640_set_mode(drive, index, pio, cycle_time);
 
        printk("%s: selected cmd640 PIO mode%d (%dns)",
                drive->name, pio, cycle_time);
@@ -652,6 +610,9 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
        display_clocks(index);
 }
 
+static const struct ide_port_ops cmd640_port_ops = {
+       .set_pio_mode           = cmd640_set_pio_mode,
+};
 #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
 
 static int pci_conf1(void)
@@ -693,14 +654,32 @@ static const struct ide_port_info cmd640_port_info __initdata = {
        .chipset                = ide_cmd640,
        .host_flags             = IDE_HFLAG_SERIALIZE |
                                  IDE_HFLAG_NO_DMA |
-                                 IDE_HFLAG_NO_AUTOTUNE |
                                  IDE_HFLAG_ABUSE_PREFETCH |
                                  IDE_HFLAG_ABUSE_FAST_DEVSEL,
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+       .port_ops               = &cmd640_port_ops,
        .pio_mask               = ATA_PIO5,
 #endif
 };
 
+static int cmd640x_init_one(unsigned long base, unsigned long ctl)
+{
+       if (!request_region(base, 8, DRV_NAME)) {
+               printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
+                               DRV_NAME, base, base + 7);
+               return -EBUSY;
+       }
+
+       if (!request_region(ctl, 1, DRV_NAME)) {
+               printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
+                               DRV_NAME, ctl);
+               release_region(base, 8);
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
 /*
  * Probe for a cmd640 chipset, and initialize it if found.
  */
@@ -709,7 +688,7 @@ static int __init cmd640x_init(void)
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
        int second_port_toggled = 0;
 #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
-       int second_port_cmd640 = 0;
+       int second_port_cmd640 = 0, rc;
        const char *bus_type, *port2;
        unsigned int index;
        u8 b, cfr;
@@ -749,10 +728,21 @@ static int __init cmd640x_init(void)
        cfr = get_cmd640_reg(CFR);
        cmd640_chip_version = cfr & CFR_DEVREV;
        if (cmd640_chip_version == 0) {
-               printk ("ide: bad cmd640 revision: %d\n", cmd640_chip_version);
+               printk("ide: bad cmd640 revision: %d\n", cmd640_chip_version);
                return 0;
        }
 
+       rc = cmd640x_init_one(0x1f0, 0x3f6);
+       if (rc)
+               return rc;
+
+       rc = cmd640x_init_one(0x170, 0x376);
+       if (rc) {
+               release_region(0x3f6, 1);
+               release_region(0x1f0, 8);
+               return rc;
+       }
+
        memset(&hw, 0, sizeof(hw));
 
        ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
@@ -764,17 +754,15 @@ static int __init cmd640x_init(void)
        printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x"
                         "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr);
 
+       cmd_hwif0 = ide_find_port();
+
        /*
         * Initialize data for primary port
         */
-       setup_device_ptrs ();
-
-       ide_init_port_hw(cmd_hwif0, &hw[0]);
-#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
-       cmd_hwif0->set_pio_mode = &cmd640_set_pio_mode;
-#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
-
-       idx[0] = cmd_hwif0->index;
+       if (cmd_hwif0) {
+               ide_init_port_hw(cmd_hwif0, &hw[0]);
+               idx[0] = cmd_hwif0->index;
+       }
 
        /*
         * Ensure compatibility by always using the slowest timings
@@ -786,10 +774,13 @@ static int __init cmd640x_init(void)
        put_cmd640_reg(CMDTIM, 0);
        put_cmd640_reg(BRST, 0x40);
 
+       cmd_hwif1 = ide_find_port();
+
        /*
         * Try to enable the secondary interface, if not already enabled
         */
-       if (cmd_hwif1->drives[0].noprobe && cmd_hwif1->drives[1].noprobe) {
+       if (cmd_hwif1 &&
+           cmd_hwif1->drives[0].noprobe && cmd_hwif1->drives[1].noprobe) {
                port2 = "not probed";
        } else {
                b = get_cmd640_reg(CNTRL);
@@ -820,15 +811,11 @@ static int __init cmd640x_init(void)
        /*
         * Initialize data for secondary cmd640 port, if enabled
         */
-       if (second_port_cmd640) {
+       if (second_port_cmd640 && cmd_hwif1) {
                ide_init_port_hw(cmd_hwif1, &hw[1]);
-#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
-               cmd_hwif1->set_pio_mode = &cmd640_set_pio_mode;
-#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
-
                idx[1] = cmd_hwif1->index;
        }
-       printk(KERN_INFO "%s: %sserialized, secondary interface %s\n", cmd_hwif1->name,
+       printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n",
                         second_port_cmd640 ? "" : "not ", port2);
 
        /*
@@ -836,35 +823,34 @@ static int __init cmd640x_init(void)
         * Do not unnecessarily disturb any prior BIOS setup of these.
         */
        for (index = 0; index < (2 + (second_port_cmd640 << 1)); index++) {
-               ide_drive_t *drive = cmd_drives[index];
-#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
-               if (drive->autotune || ((index > 1) && second_port_toggled)) {
-                       /*
-                        * Reset timing to the slowest speed and turn off prefetch.
-                        * This way, the drive identify code has a better chance.
-                        */
-                       setup_counts    [index] = 4;    /* max possible */
-                       active_counts   [index] = 16;   /* max possible */
-                       recovery_counts [index] = 16;   /* max possible */
-                       program_drive_counts (index);
-                       set_prefetch_mode (index, 0);
-                       printk("cmd640: drive%d timings/prefetch cleared\n", index);
-               } else {
-                       /*
-                        * Record timings/prefetch without changing them.
-                        * This preserves any prior BIOS setup.
-                        */
-                       retrieve_drive_counts (index);
-                       check_prefetch (index);
-                       printk("cmd640: drive%d timings/prefetch(%s) preserved",
-                               index, drive->no_io_32bit ? "off" : "on");
-                       display_clocks(index);
+               ide_drive_t *drive;
+
+               if (index > 1) {
+                       if (cmd_hwif1 == NULL)
+                               continue;
+                       drive = &cmd_hwif1->drives[index & 1];
+               } else  {
+                       if (cmd_hwif0 == NULL)
+                               continue;
+                       drive = &cmd_hwif0->drives[index & 1];
                }
+
+#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+               /*
+                * Reset timing to the slowest speed and turn off prefetch.
+                * This way, the drive identify code has a better chance.
+                */
+               setup_counts    [index] = 4;    /* max possible */
+               active_counts   [index] = 16;   /* max possible */
+               recovery_counts [index] = 16;   /* max possible */
+               program_drive_counts(drive, index);
+               set_prefetch_mode(drive, index, 0);
+               printk("cmd640: drive%d timings/prefetch cleared\n", index);
 #else
                /*
                 * Set the drive unmask flags to match the prefetch setting
                 */
-               check_prefetch (index);
+               check_prefetch(drive, index);
                printk("cmd640: drive%d timings/prefetch(%s) preserved\n",
                        index, drive->no_io_32bit ? "off" : "on");
 #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
index edabe6299efdf58ca2b6806600c7191b45fed0fa..08674711d0895c6fae3476cba5d02a2d1f351541 100644 (file)
@@ -68,8 +68,8 @@ static u8 quantize_timing(int timing, int quant)
  */
 static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time)
 {
-       struct pci_dev *dev     = to_pci_dev(drive->hwif->dev);
-       int clock_time          = 1000 / system_bus_clock();
+       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+       int clock_time = 1000 / (ide_pci_clk ? ide_pci_clk : system_bus_clock());
        u8  cycle_count, active_count, recovery_count, drwtim;
        static const u8 recovery_values[] =
                {15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0};
@@ -128,7 +128,7 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
                            ide_pio_timings[pio].active_time);
 
        setup_count = quantize_timing(ide_pio_timings[pio].setup_time,
-                                     1000 / system_bus_clock());
+                       1000 / (ide_pci_clk ? ide_pci_clk : system_bus_clock()));
 
        /*
         * The primary channel has individual address setup timing registers
@@ -223,7 +223,7 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
                (void) pci_write_config_byte(dev, pciU, regU);
 }
 
-static int cmd648_ide_dma_end (ide_drive_t *drive)
+static int cmd648_dma_end(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        unsigned long base      = hwif->dma_base - (hwif->channel * 8);
@@ -239,7 +239,7 @@ static int cmd648_ide_dma_end (ide_drive_t *drive)
        return err;
 }
 
-static int cmd64x_ide_dma_end (ide_drive_t *drive)
+static int cmd64x_dma_end(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
@@ -256,7 +256,7 @@ static int cmd64x_ide_dma_end (ide_drive_t *drive)
        return err;
 }
 
-static int cmd648_ide_dma_test_irq (ide_drive_t *drive)
+static int cmd648_dma_test_irq(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        unsigned long base      = hwif->dma_base - (hwif->channel * 8);
@@ -279,7 +279,7 @@ static int cmd648_ide_dma_test_irq (ide_drive_t *drive)
        return 0;
 }
 
-static int cmd64x_ide_dma_test_irq (ide_drive_t *drive)
+static int cmd64x_dma_test_irq(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
@@ -310,7 +310,7 @@ static int cmd64x_ide_dma_test_irq (ide_drive_t *drive)
  * event order for DMA transfers.
  */
 
-static int cmd646_1_ide_dma_end (ide_drive_t *drive)
+static int cmd646_1_dma_end(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = HWIF(drive);
        u8 dma_stat = 0, dma_cmd = 0;
@@ -370,7 +370,7 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha
        return 0;
 }
 
-static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif)
+static u8 __devinit cmd64x_cable_detect(ide_hwif_t *hwif)
 {
        struct pci_dev  *dev    = to_pci_dev(hwif->dev);
        u8 bmidecsr = 0, mask   = hwif->channel ? 0x02 : 0x01;
@@ -385,91 +385,85 @@ static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif)
        }
 }
 
-static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-       hwif->set_pio_mode = &cmd64x_set_pio_mode;
-       hwif->set_dma_mode = &cmd64x_set_dma_mode;
-
-       hwif->cable_detect = ata66_cmd64x;
+static const struct ide_port_ops cmd64x_port_ops = {
+       .set_pio_mode           = cmd64x_set_pio_mode,
+       .set_dma_mode           = cmd64x_set_dma_mode,
+       .cable_detect           = cmd64x_cable_detect,
+};
 
-       if (!hwif->dma_base)
-               return;
+static const struct ide_dma_ops cmd64x_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = ide_dma_start,
+       .dma_end                = cmd64x_dma_end,
+       .dma_test_irq           = cmd64x_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
 
-       /*
-        * UltraDMA only supported on PCI646U and PCI646U2, which
-        * correspond to revisions 0x03, 0x05 and 0x07 respectively.
-        * Actually, although the CMD tech support people won't
-        * tell me the details, the 0x03 revision cannot support
-        * UDMA correctly without hardware modifications, and even
-        * then it only works with Quantum disks due to some
-        * hold time assumptions in the 646U part which are fixed
-        * in the 646U2.
-        *
-        * So we only do UltraDMA on revision 0x05 and 0x07 chipsets.
-        */
-       if (dev->device == PCI_DEVICE_ID_CMD_646 && dev->revision < 5)
-               hwif->ultra_mask = 0x00;
+static const struct ide_dma_ops cmd646_rev1_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = ide_dma_start,
+       .dma_end                = cmd646_1_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
 
-       switch (dev->device) {
-       case PCI_DEVICE_ID_CMD_648:
-       case PCI_DEVICE_ID_CMD_649:
-       alt_irq_bits:
-               hwif->ide_dma_end       = &cmd648_ide_dma_end;
-               hwif->ide_dma_test_irq  = &cmd648_ide_dma_test_irq;
-               break;
-       case PCI_DEVICE_ID_CMD_646:
-               if (dev->revision == 0x01) {
-                       hwif->ide_dma_end = &cmd646_1_ide_dma_end;
-                       break;
-               } else if (dev->revision >= 0x03)
-                       goto alt_irq_bits;
-               /* fall thru */
-       default:
-               hwif->ide_dma_end       = &cmd64x_ide_dma_end;
-               hwif->ide_dma_test_irq  = &cmd64x_ide_dma_test_irq;
-               break;
-       }
-}
+static const struct ide_dma_ops cmd648_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = ide_dma_start,
+       .dma_end                = cmd648_dma_end,
+       .dma_test_irq           = cmd648_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
 
 static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
        {       /* 0 */
                .name           = "CMD643",
                .init_chipset   = init_chipset_cmd64x,
-               .init_hwif      = init_hwif_cmd64x,
                .enablebits     = {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
+               .port_ops       = &cmd64x_port_ops,
+               .dma_ops        = &cmd64x_dma_ops,
                .host_flags     = IDE_HFLAG_CLEAR_SIMPLEX |
-                                 IDE_HFLAG_ABUSE_PREFETCH |
-                                 IDE_HFLAG_BOOTABLE,
+                                 IDE_HFLAG_ABUSE_PREFETCH,
                .pio_mask       = ATA_PIO5,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = 0x00, /* no udma */
        },{     /* 1 */
                .name           = "CMD646",
                .init_chipset   = init_chipset_cmd64x,
-               .init_hwif      = init_hwif_cmd64x,
                .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
                .chipset        = ide_cmd646,
-               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
+               .port_ops       = &cmd64x_port_ops,
+               .dma_ops        = &cmd648_dma_ops,
+               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH,
                .pio_mask       = ATA_PIO5,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA2,
        },{     /* 2 */
                .name           = "CMD648",
                .init_chipset   = init_chipset_cmd64x,
-               .init_hwif      = init_hwif_cmd64x,
                .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
-               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
+               .port_ops       = &cmd64x_port_ops,
+               .dma_ops        = &cmd648_dma_ops,
+               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH,
                .pio_mask       = ATA_PIO5,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA4,
        },{     /* 3 */
                .name           = "CMD649",
                .init_chipset   = init_chipset_cmd64x,
-               .init_hwif      = init_hwif_cmd64x,
                .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
-               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
+               .port_ops       = &cmd64x_port_ops,
+               .dma_ops        = &cmd648_dma_ops,
+               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH,
                .pio_mask       = ATA_PIO5,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA5,
@@ -483,12 +477,35 @@ static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_devic
 
        d = cmd64x_chipsets[idx];
 
-       /*
-        * The original PCI0646 didn't have the primary channel enable bit,
-        * it appeared starting with PCI0646U (i.e. revision ID 3).
-        */
-       if (idx == 1 && dev->revision < 3)
-               d.enablebits[0].reg = 0;
+       if (idx == 1) {
+               /*
+                * UltraDMA only supported on PCI646U and PCI646U2, which
+                * correspond to revisions 0x03, 0x05 and 0x07 respectively.
+                * Actually, although the CMD tech support people won't
+                * tell me the details, the 0x03 revision cannot support
+                * UDMA correctly without hardware modifications, and even
+                * then it only works with Quantum disks due to some
+                * hold time assumptions in the 646U part which are fixed
+                * in the 646U2.
+                *
+                * So we only do UltraDMA on revision 0x05 and 0x07 chipsets.
+                */
+               if (dev->revision < 5) {
+                       d.udma_mask = 0x00;
+                       /*
+                        * The original PCI0646 didn't have the primary
+                        * channel enable bit, it appeared starting with
+                        * PCI0646U (i.e. revision ID 3).
+                        */
+                       if (dev->revision < 3) {
+                               d.enablebits[0].reg = 0;
+                               if (dev->revision == 1)
+                                       d.dma_ops = &cmd646_rev1_dma_ops;
+                               else
+                                       d.dma_ops = &cmd64x_dma_ops;
+                       }
+               }
+       }
 
        return ide_setup_pci_device(dev, &d);
 }
index 1c163e4ef03f1d7b5972d13b65a343ebd8ddba2d..17669a434438bccbd596e23b4fdc51fdfb2f679e 100644 (file)
@@ -103,27 +103,32 @@ static void cs5520_dma_host_set(ide_drive_t *drive, int on)
        ide_dma_host_set(drive, on);
 }
 
-static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
-{
-       hwif->set_pio_mode = &cs5520_set_pio_mode;
-       hwif->set_dma_mode = &cs5520_set_dma_mode;
-
-       if (hwif->dma_base == 0)
-               return;
+static const struct ide_port_ops cs5520_port_ops = {
+       .set_pio_mode           = cs5520_set_pio_mode,
+       .set_dma_mode           = cs5520_set_dma_mode,
+};
 
-       hwif->dma_host_set = &cs5520_dma_host_set;
-}
+static const struct ide_dma_ops cs5520_dma_ops = {
+       .dma_host_set           = cs5520_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = ide_dma_start,
+       .dma_end                = __ide_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
 
 #define DECLARE_CS_DEV(name_str)                               \
        {                                                       \
                .name           = name_str,                     \
-               .init_hwif      = init_hwif_cs5520,             \
+               .port_ops       = &cs5520_port_ops,             \
+               .dma_ops        = &cs5520_dma_ops,              \
                .host_flags     = IDE_HFLAG_ISA_PORTS |         \
                                  IDE_HFLAG_CS5520 |            \
                                  IDE_HFLAG_VDMA |              \
                                  IDE_HFLAG_NO_ATAPI_DMA |      \
-                                 IDE_HFLAG_ABUSE_SET_DMA_MODE |\
-                                 IDE_HFLAG_BOOTABLE,           \
+                                 IDE_HFLAG_ABUSE_SET_DMA_MODE, \
                .pio_mask       = ATA_PIO4,                     \
        }
 
index 941a1344820b95ae8d2f238714124f9d3e4c6470..f5534c1ff349841b10ace33856a5b587b2e19860 100644 (file)
@@ -228,29 +228,27 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
        unsigned long basereg;
        u32 d0_timings;
 
-       hwif->set_pio_mode = &cs5530_set_pio_mode;
-       hwif->set_dma_mode = &cs5530_set_dma_mode;
-
        basereg = CS5530_BASEREG(hwif);
        d0_timings = inl(basereg + 0);
        if (CS5530_BAD_PIO(d0_timings))
                outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 0);
        if (CS5530_BAD_PIO(inl(basereg + 8)))
                outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 8);
-
-       if (hwif->dma_base == 0)
-               return;
-
-       hwif->udma_filter = cs5530_udma_filter;
 }
 
+static const struct ide_port_ops cs5530_port_ops = {
+       .set_pio_mode           = cs5530_set_pio_mode,
+       .set_dma_mode           = cs5530_set_dma_mode,
+       .udma_filter            = cs5530_udma_filter,
+};
+
 static const struct ide_port_info cs5530_chipset __devinitdata = {
        .name           = "CS5530",
        .init_chipset   = init_chipset_cs5530,
        .init_hwif      = init_hwif_cs5530,
+       .port_ops       = &cs5530_port_ops,
        .host_flags     = IDE_HFLAG_SERIALIZE |
-                         IDE_HFLAG_POST_SET_MODE |
-                         IDE_HFLAG_BOOTABLE,
+                         IDE_HFLAG_POST_SET_MODE,
        .pio_mask       = ATA_PIO4,
        .mwdma_mask     = ATA_MWDMA2,
        .udma_mask      = ATA_UDMA2,
index d7b5ea992e94a25ee10b46eac7bb4237a9848764..99fe91a191b8f556abb865876c2e3fcaf0e8a97a 100644 (file)
@@ -166,27 +166,17 @@ static u8 __devinit cs5535_cable_detect(ide_hwif_t *hwif)
        return (bit & 1) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
 }
 
-/****
- *     init_hwif_cs5535        -       Initialize one ide cannel
- *     @hwif: Channel descriptor
- *
- *     This gets invoked by the IDE driver once for each channel. It
- *     performs channel-specific pre-initialization before drive probing.
- *
- */
-static void __devinit init_hwif_cs5535(ide_hwif_t *hwif)
-{
-       hwif->set_pio_mode = &cs5535_set_pio_mode;
-       hwif->set_dma_mode = &cs5535_set_dma_mode;
-
-       hwif->cable_detect = cs5535_cable_detect;
-}
+static const struct ide_port_ops cs5535_port_ops = {
+       .set_pio_mode           = cs5535_set_pio_mode,
+       .set_dma_mode           = cs5535_set_dma_mode,
+       .cable_detect           = cs5535_cable_detect,
+};
 
 static const struct ide_port_info cs5535_chipset __devinitdata = {
        .name           = "CS5535",
-       .init_hwif      = init_hwif_cs5535,
+       .port_ops       = &cs5535_port_ops,
        .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE |
-                         IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_BOOTABLE,
+                         IDE_HFLAG_ABUSE_SET_DMA_MODE,
        .pio_mask       = ATA_PIO4,
        .mwdma_mask     = ATA_MWDMA2,
        .udma_mask      = ATA_UDMA4,
index 724cbacf4e5b04d9a82e19e5ea05a0d6e0cf5292..77cc22c2ad457b61092e67056d31cab28d3fcbb1 100644 (file)
@@ -6,7 +6,7 @@
  *
  * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards.
  * Writing the driver was quite simple, since most of the job is
- * done by the generic pci-ide support. 
+ * done by the generic pci-ide support.
  * The hard part was finding the CY82C693's datasheet on Cypress's
  * web page :-(. But Altavista solved this problem :-).
  *
  * - I recently got a 16.8G IBM DTTA, so I was able to test it with
  *   a large and fast disk - the results look great, so I'd say the
  *   driver is working fine :-)
- *   hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA 
- * - this is my first linux driver, so there's probably a lot  of room 
+ *   hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA
+ * - this is my first linux driver, so there's probably a lot  of room
  *   for optimizations and bug fixing, so feel free to do it.
- * - use idebus=xx parameter to set PCI bus speed - needed to calc
- *   timings for PIO modes (default will be 40)
- * - if using PIO mode it's a good idea to set the PIO mode and 
+ * - if using PIO mode it's a good idea to set the PIO mode and
  *   32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda
  * - I had some problems with my IBM DHEA with PIO modes < 2
  *   (lost interrupts) ?????
@@ -110,11 +108,11 @@ typedef struct pio_clocks_s {
  * calc clocks using bus_speed
  * returns (rounded up) time in bus clocks for time in ns
  */
-static int calc_clk (int time, int bus_speed)
+static int calc_clk(int time, int bus_speed)
 {
        int clocks;
 
-       clocks = (time*bus_speed+999)/1000 -1;
+       clocks = (time*bus_speed+999)/1000 - 1;
 
        if (clocks < 0)
                clocks = 0;
@@ -132,11 +130,11 @@ static int calc_clk (int time, int bus_speed)
  * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used
  *       for mode 3 and 4 drives 8 and 16-bit timings are the same
  *
- */ 
-static void compute_clocks (u8 pio, pio_clocks_t *p_pclk)
+ */
+static void compute_clocks(u8 pio, pio_clocks_t *p_pclk)
 {
        int clk1, clk2;
-       int bus_speed = system_bus_clock();     /* get speed of PCI bus */
+       int bus_speed = ide_pci_clk ? ide_pci_clk : system_bus_clock();
 
        /* we don't check against CY82C693's min and max speed,
         * so you can play with the idebus=xx parameter
@@ -158,7 +156,7 @@ static void compute_clocks (u8 pio, pio_clocks_t *p_pclk)
        clk1 = (clk1<<4)|clk2;  /* combine active and recovery clocks */
 
        /* note: we use the same values for 16bit IOR and IOW
-         *     those are all the same, since I don't have other
+             those are all the same, since I don't have other
         *      timings than those from ide-lib.c
         */
 
@@ -186,7 +184,7 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
        outb(index, CY82_INDEX_PORT);
        data = inb(CY82_DATA_PORT);
 
-       printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n",
+       printk(KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n",
                drive->name, HWIF(drive)->channel, drive->select.b.unit,
                (data&0x3), ((data>>2)&1));
 #endif /* CY82C693_DEBUG_LOGS */
@@ -202,7 +200,7 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
                mode & 3, single);
 #endif /* CY82C693_DEBUG_INFO */
 
-       /* 
+       /*
         * note: below we set the value for Bus Master IDE TimeOut Register
         * I'm not absolutly sure what this does, but it solved my problem
         * with IDE DMA and sound, so I now can play sound and work with
@@ -216,8 +214,8 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
        outb(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT);
        outb(data, CY82_DATA_PORT);
 
-#if CY82C693_DEBUG_INFO        
-       printk (KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n",
+#if CY82C693_DEBUG_INFO
+       printk(KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n",
                drive->name, data);
 #endif /* CY82C693_DEBUG_INFO */
 }
@@ -242,14 +240,14 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
 
 #if CY82C693_DEBUG_LOGS
        /* for debug let's show the register values */
-       
-               if (drive->select.b.unit == 0) {
+
+       if (drive->select.b.unit == 0) {
                /*
-                * get master drive registers                   
+                * get master drive registers
                 * address setup control register
                 * is 32 bit !!!
-                */ 
-               pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);                
+                */
+               pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
                addrCtrl &= 0x0F;
 
                /* now let's get the remaining registers */
@@ -261,7 +259,7 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
                 * set slave drive registers
                 * address setup control register
                 * is 32 bit !!!
-                */ 
+                */
                pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
 
                addrCtrl &= 0xF0;
@@ -288,9 +286,9 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
                 * set master drive
                 * address setup control register
                 * is 32 bit !!!
-                */ 
+                */
                pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
-               
+
                addrCtrl &= (~0xF);
                addrCtrl |= (unsigned int)pclk.address_time;
                pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
@@ -299,14 +297,14 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
                pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, pclk.time_16r);
                pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w);
                pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8);
-               
+
                addrCtrl &= 0xF;
        } else {
                /*
                 * set slave drive
                 * address setup control register
                 * is 32 bit !!!
-                */ 
+                */
                pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
 
                addrCtrl &= (~0xF0);
@@ -320,7 +318,7 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
 
                addrCtrl >>= 4;
                addrCtrl &= 0xF;
-       }       
+       }
 
 #if CY82C693_DEBUG_INFO
        printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to "
@@ -340,41 +338,41 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c
 
 #ifdef CY82C693_SETDMA_CLOCK
        u8 data = 0;
-#endif /* CY82C693_SETDMA_CLOCK */ 
+#endif /* CY82C693_SETDMA_CLOCK */
 
        /* write info about this verion of the driver */
        printk(KERN_INFO CY82_VERSION "\n");
 
 #ifdef CY82C693_SETDMA_CLOCK
        /* okay let's set the DMA clock speed */
-        
-        outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
-        data = inb(CY82_DATA_PORT);
+
+       outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
+       data = inb(CY82_DATA_PORT);
 
 #if CY82C693_DEBUG_INFO
        printk(KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n",
                name, data);
 #endif /* CY82C693_DEBUG_INFO */
 
-        /*
+       /*
         * for some reason sometimes the DMA controller
         * speed is set to ATCLK/2 ???? - we fix this here
-        * 
+        *
         * note: i don't know what causes this strange behaviour,
         *       but even changing the dma speed doesn't solve it :-(
-        *       the ide performance is still only half the normal speed 
-        * 
+        *       the ide performance is still only half the normal speed
+        *
         *       if anybody knows what goes wrong with my machine, please
         *       let me know - ASK
-         */
+        */
 
        data |= 0x03;
 
-        outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
-        outb(data, CY82_DATA_PORT);
+       outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
+       outb(data, CY82_DATA_PORT);
 
 #if CY82C693_DEBUG_INFO
-       printk (KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n",
+       printk(KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n",
                name, data);
 #endif /* CY82C693_DEBUG_INFO */
 
@@ -382,15 +380,6 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c
        return 0;
 }
 
-/*
- * the init function - called for each ide channel once
- */
-static void __devinit init_hwif_cy82c693(ide_hwif_t *hwif)
-{
-       hwif->set_pio_mode = &cy82c693_set_pio_mode;
-       hwif->set_dma_mode = &cy82c693_set_dma_mode;
-}
-
 static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
 {
        static ide_hwif_t *primary;
@@ -404,14 +393,18 @@ static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
        }
 }
 
+static const struct ide_port_ops cy82c693_port_ops = {
+       .set_pio_mode           = cy82c693_set_pio_mode,
+       .set_dma_mode           = cy82c693_set_dma_mode,
+};
+
 static const struct ide_port_info cy82c693_chipset __devinitdata = {
        .name           = "CY82C693",
        .init_chipset   = init_chipset_cy82c693,
        .init_iops      = init_iops_cy82c693,
-       .init_hwif      = init_hwif_cy82c693,
+       .port_ops       = &cy82c693_port_ops,
        .chipset        = ide_cy82c693,
-       .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_CY82C693 |
-                         IDE_HFLAG_BOOTABLE,
+       .host_flags     = IDE_HFLAG_SINGLE,
        .pio_mask       = ATA_PIO4,
        .swdma_mask     = ATA_SWDMA2,
        .mwdma_mask     = ATA_MWDMA2,
@@ -424,7 +417,7 @@ static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_dev
 
        /* CY82C693 is more than only a IDE controller.
           Function 1 is primary IDE channel, function 2 - secondary. */
-        if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
+       if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
            PCI_FUNC(dev->devfn) == 1) {
                dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
                ret = ide_setup_pci_devices(dev, dev2, &cy82c693_chipset);
index 961698d655eb6f2a9df206c726ce2ec0f14f055a..b9e457996d0e2f36034f209772f0c58afa8f9a89 100644 (file)
@@ -43,6 +43,10 @@ static const u8 setup[] = {
        0x00, 0x00, 0x00, 0x00, 0xa4, 0x83, 0x02, 0x13,
 };
 
+static const struct ide_port_ops delkin_cb_port_ops = {
+       .quirkproc              = ide_undecoded_slave,
+};
+
 static int __devinit
 delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
 {
@@ -71,26 +75,21 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
                if (setup[i])
                        outb(setup[i], base + i);
        }
-       pci_release_regions(dev);       /* IDE layer handles regions itself */
 
        memset(&hw, 0, sizeof(hw));
        ide_std_init_ports(&hw, base + 0x10, base + 0x1e);
        hw.irq = dev->irq;
        hw.chipset = ide_pci;           /* this enables IRQ sharing */
 
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif == NULL)
                goto out_disable;
 
        i = hwif->index;
 
-       if (hwif->present)
-               ide_unregister(i);
-       else
-               ide_init_port_data(hwif, i);
-
+       ide_init_port_data(hwif, i);
        ide_init_port_hw(hwif, &hw);
-       hwif->quirkproc = &ide_undecoded_slave;
+       hwif->port_ops = &delkin_cb_port_ops;
 
        idx[0] = i;
 
@@ -110,6 +109,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
 
 out_disable:
        printk(KERN_ERR "delkin_cb: no IDE devices found\n");
+       pci_release_regions(dev);
        pci_disable_device(dev);
        return -ENODEV;
 }
@@ -119,9 +119,9 @@ delkin_cb_remove (struct pci_dev *dev)
 {
        ide_hwif_t *hwif = pci_get_drvdata(dev);
 
-       if (hwif)
-               ide_unregister(hwif->index);
+       ide_unregister(hwif);
 
+       pci_release_regions(dev);
        pci_disable_device(dev);
 }
 
index 7fd83a9d4dee16fb8612850bce50732e0e60930a..041720e22762840aefbad8a151d5c0ed7e5159f1 100644 (file)
@@ -38,8 +38,7 @@ MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE st
        { \
                .name           = name_str, \
                .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA | \
-                                 extra_flags | \
-                                 IDE_HFLAG_BOOTABLE, \
+                                 extra_flags, \
                .swdma_mask     = ATA_SWDMA2, \
                .mwdma_mask     = ATA_MWDMA2, \
                .udma_mask      = ATA_UDMA6, \
@@ -50,9 +49,8 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
 
        {       /* 1 */
                .name           = "NS87410",
-               .enablebits     = {{0x43,0x08,0x08}, {0x47,0x08,0x08}},
-               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
-                                 IDE_HFLAG_BOOTABLE,
+               .enablebits     = { {0x43, 0x08, 0x08}, {0x47, 0x08, 0x08} },
+               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA,
                .swdma_mask     = ATA_SWDMA2,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA6,
@@ -99,7 +97,7 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
  *     Called when the PCI registration layer (or the IDE initialization)
  *     finds a device matching our IDE device tables.
  */
+
 static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        const struct ide_port_info *d = &generic_chipsets[id->driver_data];
index 9f01da46b01648d6ead8c8b516fbe7a7a9d4cc1e..84c36c117194cb731e24e2ea60ee7b67e2df5681 100644 (file)
@@ -115,11 +115,10 @@ static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev, const cha
        return dev->irq;
 }
 
-static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif)
-{
-       hwif->set_pio_mode = &hpt34x_set_pio_mode;
-       hwif->set_dma_mode = &hpt34x_set_mode;
-}
+static const struct ide_port_ops hpt34x_port_ops = {
+       .set_pio_mode           = hpt34x_set_pio_mode,
+       .set_dma_mode           = hpt34x_set_mode,
+};
 
 #define IDE_HFLAGS_HPT34X \
        (IDE_HFLAG_NO_ATAPI_DMA | \
@@ -131,16 +130,14 @@ static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
        { /* 0 */
                .name           = "HPT343",
                .init_chipset   = init_chipset_hpt34x,
-               .init_hwif      = init_hwif_hpt34x,
-               .extra          = 16,
-               .host_flags     = IDE_HFLAGS_HPT34X,
+               .port_ops       = &hpt34x_port_ops,
+               .host_flags     = IDE_HFLAGS_HPT34X | IDE_HFLAG_NON_BOOTABLE,
                .pio_mask       = ATA_PIO5,
        },
        { /* 1 */
                .name           = "HPT345",
                .init_chipset   = init_chipset_hpt34x,
-               .init_hwif      = init_hwif_hpt34x,
-               .extra          = 16,
+               .port_ops       = &hpt34x_port_ops,
                .host_flags     = IDE_HFLAGS_HPT34X | IDE_HFLAG_OFF_BOARD,
                .pio_mask       = ATA_PIO5,
 #ifdef CONFIG_HPT34X_AUTODMA
index 82d0e318a1fe6200dc762405861078cbde410d91..c929dadaaaffb02836cf6e66067f6862cd8c0dae 100644 (file)
@@ -760,7 +760,7 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
                }
        } else
                outb(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
-                    hwif->io_ports[IDE_CONTROL_OFFSET]);
+                    hwif->io_ports.ctl_addr);
 }
 
 /*
@@ -776,7 +776,7 @@ static void hpt366_dma_lost_irq(ide_drive_t *drive)
        pci_read_config_byte(dev, 0x52, &mcr3);
        pci_read_config_byte(dev, 0x5a, &scr1);
        printk("%s: (%s)  mcr1=0x%02x, mcr3=0x%02x, scr1=0x%02x\n",
-               drive->name, __FUNCTION__, mcr1, mcr3, scr1);
+               drive->name, __func__, mcr1, mcr3, scr1);
        if (scr1 & 0x10)
                pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
        ide_dma_lost_irq(drive);
@@ -808,7 +808,7 @@ static void hpt370_irq_timeout(ide_drive_t *drive)
        hpt370_clear_engine(drive);
 }
 
-static void hpt370_ide_dma_start(ide_drive_t *drive)
+static void hpt370_dma_start(ide_drive_t *drive)
 {
 #ifdef HPT_RESET_STATE_ENGINE
        hpt370_clear_engine(drive);
@@ -816,7 +816,7 @@ static void hpt370_ide_dma_start(ide_drive_t *drive)
        ide_dma_start(drive);
 }
 
-static int hpt370_ide_dma_end(ide_drive_t *drive)
+static int hpt370_dma_end(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        u8  dma_stat            = inb(hwif->dma_status);
@@ -838,7 +838,7 @@ static void hpt370_dma_timeout(ide_drive_t *drive)
 }
 
 /* returns 1 if DMA IRQ issued, 0 otherwise */
-static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
+static int hpt374_dma_test_irq(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
@@ -858,11 +858,11 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
 
        if (!drive->waiting_for_dma)
                printk(KERN_WARNING "%s: (%s) called while not waiting\n",
-                               drive->name, __FUNCTION__);
+                               drive->name, __func__);
        return 0;
 }
 
-static int hpt374_ide_dma_end(ide_drive_t *drive)
+static int hpt374_dma_end(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
@@ -1271,17 +1271,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
        /* Cache the channel's MISC. control registers' offset */
        hwif->select_data       = hwif->channel ? 0x54 : 0x50;
 
-       hwif->set_pio_mode      = &hpt3xx_set_pio_mode;
-       hwif->set_dma_mode      = &hpt3xx_set_mode;
-
-       hwif->quirkproc         = &hpt3xx_quirkproc;
-       hwif->maskproc          = &hpt3xx_maskproc;
-
-       hwif->udma_filter       = &hpt3xx_udma_filter;
-       hwif->mdma_filter       = &hpt3xx_mdma_filter;
-
-       hwif->cable_detect      = hpt3xx_cable_detect;
-
        /*
         * HPT3xxN chips have some complications:
         *
@@ -1323,29 +1312,19 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
 
        if (new_mcr != old_mcr)
                pci_write_config_byte(dev, hwif->select_data + 1, new_mcr);
-
-       if (hwif->dma_base == 0)
-               return;
-
-       if (chip_type >= HPT374) {
-               hwif->ide_dma_test_irq  = &hpt374_ide_dma_test_irq;
-               hwif->ide_dma_end       = &hpt374_ide_dma_end;
-       } else if (chip_type >= HPT370) {
-               hwif->dma_start         = &hpt370_ide_dma_start;
-               hwif->ide_dma_end       = &hpt370_ide_dma_end;
-               hwif->dma_timeout       = &hpt370_dma_timeout;
-       } else
-               hwif->dma_lost_irq      = &hpt366_dma_lost_irq;
 }
 
-static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
+static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
+                                    const struct ide_port_info *d)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
-       u8 masterdma    = 0, slavedma   = 0;
-       u8 dma_new      = 0, dma_old    = 0;
-       unsigned long flags;
+       unsigned long flags, base = ide_pci_dma_base(hwif, d);
+       u8 dma_old, dma_new, masterdma = 0, slavedma = 0;
 
-       dma_old = inb(dmabase + 2);
+       if (base == 0 || ide_pci_set_master(dev, d->name) < 0)
+               return -1;
+
+       dma_old = inb(base + 2);
 
        local_irq_save(flags);
 
@@ -1356,11 +1335,21 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
        if (masterdma & 0x30)   dma_new |= 0x20;
        if ( slavedma & 0x30)   dma_new |= 0x40;
        if (dma_new != dma_old)
-               outb(dma_new, dmabase + 2);
+               outb(dma_new, base + 2);
 
        local_irq_restore(flags);
 
-       ide_setup_dma(hwif, dmabase);
+       printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx\n",
+                        hwif->name, base, base + 7);
+
+       hwif->extra_base = base + (hwif->channel ? 8 : 16);
+
+       if (ide_allocate_dma_engine(hwif))
+               return -1;
+
+       ide_setup_dma(hwif, base);
+
+       return 0;
 }
 
 static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2)
@@ -1416,6 +1405,49 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
         IDE_HFLAG_ABUSE_SET_DMA_MODE | \
         IDE_HFLAG_OFF_BOARD)
 
+static const struct ide_port_ops hpt3xx_port_ops = {
+       .set_pio_mode           = hpt3xx_set_pio_mode,
+       .set_dma_mode           = hpt3xx_set_mode,
+       .quirkproc              = hpt3xx_quirkproc,
+       .maskproc               = hpt3xx_maskproc,
+       .mdma_filter            = hpt3xx_mdma_filter,
+       .udma_filter            = hpt3xx_udma_filter,
+       .cable_detect           = hpt3xx_cable_detect,
+};
+
+static const struct ide_dma_ops hpt37x_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = ide_dma_start,
+       .dma_end                = hpt374_dma_end,
+       .dma_test_irq           = hpt374_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
+static const struct ide_dma_ops hpt370_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = hpt370_dma_start,
+       .dma_end                = hpt370_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = hpt370_dma_timeout,
+};
+
+static const struct ide_dma_ops hpt36x_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = ide_dma_start,
+       .dma_end                = __ide_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_lost_irq           = hpt366_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
 static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
        {       /* 0 */
                .name           = "HPT36x",
@@ -1429,7 +1461,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
                 * Bit 4 is for the primary channel, bit 5 for the secondary.
                 */
                .enablebits     = {{0x50,0x10,0x10}, {0x54,0x04,0x04}},
-               .extra          = 240,
+               .port_ops       = &hpt3xx_port_ops,
+               .dma_ops        = &hpt36x_dma_ops,
                .host_flags     = IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
@@ -1439,7 +1472,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
                .init_hwif      = init_hwif_hpt366,
                .init_dma       = init_dma_hpt366,
                .enablebits     = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
-               .extra          = 240,
+               .port_ops       = &hpt3xx_port_ops,
+               .dma_ops        = &hpt37x_dma_ops,
                .host_flags     = IDE_HFLAGS_HPT3XX,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
@@ -1449,7 +1483,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
                .init_hwif      = init_hwif_hpt366,
                .init_dma       = init_dma_hpt366,
                .enablebits     = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
-               .extra          = 240,
+               .port_ops       = &hpt3xx_port_ops,
+               .dma_ops        = &hpt37x_dma_ops,
                .host_flags     = IDE_HFLAGS_HPT3XX,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
@@ -1459,7 +1494,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
                .init_hwif      = init_hwif_hpt366,
                .init_dma       = init_dma_hpt366,
                .enablebits     = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
-               .extra          = 240,
+               .port_ops       = &hpt3xx_port_ops,
+               .dma_ops        = &hpt37x_dma_ops,
                .host_flags     = IDE_HFLAGS_HPT3XX,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
@@ -1470,7 +1506,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
                .init_dma       = init_dma_hpt366,
                .enablebits     = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
                .udma_mask      = ATA_UDMA5,
-               .extra          = 240,
+               .port_ops       = &hpt3xx_port_ops,
+               .dma_ops        = &hpt37x_dma_ops,
                .host_flags     = IDE_HFLAGS_HPT3XX,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
@@ -1480,7 +1517,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
                .init_hwif      = init_hwif_hpt366,
                .init_dma       = init_dma_hpt366,
                .enablebits     = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
-               .extra          = 240,
+               .port_ops       = &hpt3xx_port_ops,
+               .dma_ops        = &hpt37x_dma_ops,
                .host_flags     = IDE_HFLAGS_HPT3XX,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
@@ -1543,6 +1581,10 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic
        d.name = info->chip_name;
        d.udma_mask = info->udma_mask;
 
+       /* fixup ->dma_ops for HPT370/HPT370A */
+       if (info == &hpt370 || info == &hpt370a)
+               d.dma_ops = &hpt370_dma_ops;
+
        pci_set_drvdata(dev, (void *)info);
 
        if (info == &hpt36x || info == &hpt374)
@@ -1557,7 +1599,7 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic
                        hpt374_init(dev, dev2);
                else {
                        if (hpt36x_init(dev, dev2))
-                               d.host_flags |= IDE_HFLAG_BOOTABLE;
+                               d.host_flags &= ~IDE_HFLAG_NON_BOOTABLE;
                }
 
                ret = ide_setup_pci_devices(dev, dev2, &d);
index e3427eaab430b9de5ef463c4e8c558e6bace1fec..9053c8771e6ec792304c49b9e509fd450d994437 100644 (file)
@@ -35,7 +35,7 @@ static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
        static DEFINE_SPINLOCK(tune_lock);
        int control = 0;
 
-       static const u8 timings[][2]= {
+       static const u8 timings[][2] = {
                                        { 0, 0 },
                                        { 0, 0 },
                                        { 1, 0 },
@@ -105,11 +105,10 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
 
                if (!(reg48 & u_flag))
                        pci_write_config_byte(dev, 0x48, reg48 | u_flag);
-               if (speed >= XFER_UDMA_5) {
+               if (speed >= XFER_UDMA_5)
                        pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
-               } else {
+               else
                        pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
-               }
 
                if ((reg4a & a_speed) != u_speed)
                        pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
@@ -150,29 +149,18 @@ static u8 __devinit it8213_cable_detect(ide_hwif_t *hwif)
        return (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 }
 
-/**
- *     init_hwif_it8213        -       set up hwif structs
- *     @hwif: interface to set up
- *
- *     We do the basic set up of the interface structure.
- */
-
-static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
-{
-       hwif->set_dma_mode = &it8213_set_dma_mode;
-       hwif->set_pio_mode = &it8213_set_pio_mode;
-
-       hwif->cable_detect = it8213_cable_detect;
-}
-
+static const struct ide_port_ops it8213_port_ops = {
+       .set_pio_mode           = it8213_set_pio_mode,
+       .set_dma_mode           = it8213_set_dma_mode,
+       .cable_detect           = it8213_cable_detect,
+};
 
 #define DECLARE_ITE_DEV(name_str)                      \
        {                                               \
                .name           = name_str,             \
-               .init_hwif      = init_hwif_it8213,     \
-               .enablebits     = {{0x41,0x80,0x80}}, \
-               .host_flags     = IDE_HFLAG_SINGLE |    \
-                                 IDE_HFLAG_BOOTABLE,   \
+               .enablebits     = { {0x41, 0x80, 0x80} }, \
+               .port_ops       = &it8213_port_ops,     \
+               .host_flags     = IDE_HFLAG_SINGLE,     \
                .pio_mask       = ATA_PIO4,             \
                .swdma_mask     = ATA_SWDMA2_ONLY,      \
                .mwdma_mask     = ATA_MWDMA12_ONLY,     \
index d8a167451fd6fde390a6eea620a34a0e1be12025..6ab04115286be677e3b550caf201fdf7f12bd3a1 100644 (file)
@@ -418,7 +418,7 @@ static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed)
 }
 
 /**
- *     ata66_it821x    -       check for 80 pin cable
+ *     it821x_cable_detect     -       cable detection
  *     @hwif: interface to check
  *
  *     Check for the presence of an ATA66 capable cable on the
@@ -426,7 +426,7 @@ static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed)
  *     the needed logic onboard.
  */
 
-static u8 __devinit ata66_it821x(ide_hwif_t *hwif)
+static u8 __devinit it821x_cable_detect(ide_hwif_t *hwif)
 {
        /* The reference driver also only does disk side */
        return ATA_CBL_PATA80;
@@ -511,6 +511,11 @@ static void __devinit it821x_quirkproc(ide_drive_t *drive)
 
 }
 
+static struct ide_dma_ops it821x_pass_through_dma_ops = {
+       .dma_start              = it821x_dma_start,
+       .dma_end                = it821x_dma_end,
+};
+
 /**
  *     init_hwif_it821x        -       set up hwif structs
  *     @hwif: interface to set up
@@ -523,16 +528,10 @@ static void __devinit it821x_quirkproc(ide_drive_t *drive)
 static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct it821x_dev *idev = kzalloc(sizeof(struct it821x_dev), GFP_KERNEL);
+       struct it821x_dev **itdevs = (struct it821x_dev **)pci_get_drvdata(dev);
+       struct it821x_dev *idev = itdevs[hwif->channel];
        u8 conf;
 
-       hwif->quirkproc = &it821x_quirkproc;
-
-       if (idev == NULL) {
-               printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n");
-               return;
-       }
-
        ide_set_hwifdata(hwif, idev);
 
        pci_read_config_byte(dev, 0x50, &conf);
@@ -567,17 +566,11 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
        }
 
        if (idev->smart == 0) {
-               hwif->set_pio_mode = &it821x_set_pio_mode;
-               hwif->set_dma_mode = &it821x_set_dma_mode;
-
                /* MWDMA/PIO clock switching for pass through mode */
-               hwif->dma_start = &it821x_dma_start;
-               hwif->ide_dma_end = &it821x_dma_end;
+               hwif->dma_ops = &it821x_pass_through_dma_ops;
        } else
                hwif->host_flags |= IDE_HFLAG_NO_SET_MODE;
 
-       hwif->cable_detect = ata66_it821x;
-
        if (hwif->dma_base == 0)
                return;
 
@@ -617,13 +610,20 @@ static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const cha
        return 0;
 }
 
+static const struct ide_port_ops it821x_port_ops = {
+       /* it821x_set_{pio,dma}_mode() are only used in pass-through mode */
+       .set_pio_mode           = it821x_set_pio_mode,
+       .set_dma_mode           = it821x_set_dma_mode,
+       .quirkproc              = it821x_quirkproc,
+       .cable_detect           = it821x_cable_detect,
+};
 
 #define DECLARE_ITE_DEV(name_str)                      \
        {                                               \
                .name           = name_str,             \
                .init_chipset   = init_chipset_it821x,  \
                .init_hwif      = init_hwif_it821x,     \
-               .host_flags     = IDE_HFLAG_BOOTABLE,   \
+               .port_ops       = &it821x_port_ops,     \
                .pio_mask       = ATA_PIO4,             \
        }
 
@@ -642,6 +642,22 @@ static const struct ide_port_info it821x_chipsets[] __devinitdata = {
 
 static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
+       struct it821x_dev *itdevs[2] = { NULL, NULL} , *itdev;
+       unsigned int i;
+
+       for (i = 0; i < 2; i++) {
+               itdev = kzalloc(sizeof(*itdev), GFP_KERNEL);
+               if (itdev == NULL) {
+                       kfree(itdevs[0]);
+                       printk(KERN_ERR "it821x: out of memory\n");
+                       return -ENOMEM;
+               }
+
+               itdevs[i] = itdev;
+       }
+
+       pci_set_drvdata(dev, itdevs);
+
        return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
 }
 
index a56bcb4f22f4f9d402616d5314c50a4ed8794ec5..96ef7394f28395b5646bee8f3ae9e319be3dcc90 100644 (file)
@@ -19,13 +19,13 @@ typedef enum {
 } port_type;
 
 /**
- *     ata66_jmicron           -       Cable check
+ *     jmicron_cable_detect    -       cable detection
  *     @hwif: IDE port
  *
  *     Returns the cable type.
  */
 
-static u8 __devinit ata66_jmicron(ide_hwif_t *hwif)
+static u8 __devinit jmicron_cable_detect(ide_hwif_t *hwif)
 {
        struct pci_dev *pdev = to_pci_dev(hwif->dev);
 
@@ -63,8 +63,7 @@ static u8 __devinit ata66_jmicron(ide_hwif_t *hwif)
         *      actually do our cable checking etc. Thankfully we don't need
         *      to do the plumbing for other cases.
         */
-       switch (port_map[port])
-       {
+       switch (port_map[port]) {
        case PORT_PATA0:
                if (control & (1 << 3)) /* 40/80 pin primary */
                        return ATA_CBL_PATA40;
@@ -96,26 +95,16 @@ static void jmicron_set_dma_mode(ide_drive_t *drive, const u8 mode)
 {
 }
 
-/**
- *     init_hwif_jmicron       -       set up hwif structs
- *     @hwif: interface to set up
- *
- *     Minimal set up is required for the Jmicron hardware.
- */
-
-static void __devinit init_hwif_jmicron(ide_hwif_t *hwif)
-{
-       hwif->set_pio_mode = &jmicron_set_pio_mode;
-       hwif->set_dma_mode = &jmicron_set_dma_mode;
-
-       hwif->cable_detect = ata66_jmicron;
-}
+static const struct ide_port_ops jmicron_port_ops = {
+       .set_pio_mode           = jmicron_set_pio_mode,
+       .set_dma_mode           = jmicron_set_dma_mode,
+       .cable_detect           = jmicron_cable_detect,
+};
 
 static const struct ide_port_info jmicron_chipset __devinitdata = {
        .name           = "JMB",
-       .init_hwif      = init_hwif_jmicron,
-       .host_flags     = IDE_HFLAG_BOOTABLE,
        .enablebits     = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } },
+       .port_ops       = &jmicron_port_ops,
        .pio_mask       = ATA_PIO5,
        .mwdma_mask     = ATA_MWDMA2,
        .udma_mask      = ATA_UDMA6,
index 75513320aad9277fc3dc14cc3b5d2bbf7c96e0c2..c13e299077ec37cfb3497fdc4fd85ee7c5948fc8 100644 (file)
@@ -72,8 +72,8 @@ static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
        base = pci_resource_start(pdev, port * 2) & ~3;
        dmabase = pci_resource_start(pdev, 4) & ~3;
 
-       superio_ide_status[port] = base + IDE_STATUS_OFFSET;
-       superio_ide_select[port] = base + IDE_SELECT_OFFSET;
+       superio_ide_status[port] = base + 7;
+       superio_ide_select[port] = base + 6;
        superio_ide_dma_status[port] = dmabase + (!port ? 2 : 0xa);
 
        /* Clear error/interrupt, enable dma */
@@ -150,7 +150,7 @@ static void ns87415_selectproc (ide_drive_t *drive)
        ns87415_prepare_drive (drive, drive->using_dma);
 }
 
-static int ns87415_ide_dma_end (ide_drive_t *drive)
+static int ns87415_dma_end(ide_drive_t *drive)
 {
        ide_hwif_t      *hwif = HWIF(drive);
        u8 dma_stat = 0, dma_cmd = 0;
@@ -170,7 +170,7 @@ static int ns87415_ide_dma_end (ide_drive_t *drive)
        return (dma_stat & 7) != 4;
 }
 
-static int ns87415_ide_dma_setup(ide_drive_t *drive)
+static int ns87415_dma_setup(ide_drive_t *drive)
 {
        /* select DMA xfer */
        ns87415_prepare_drive(drive, 1);
@@ -195,8 +195,6 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
        u8 stat;
 #endif
 
-       hwif->selectproc = &ns87415_selectproc;
-
        /*
         * We cannot probe for IRQ: both ports share common IRQ on INTA.
         * Also, leave IRQ masked during drive probing, to prevent infinite
@@ -233,12 +231,12 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
                 *      SELECT_DRIVE() properly during first ide_probe_port().
                 */
                timeout = 10000;
-               outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
+               outb(12, hwif->io_ports.ctl_addr);
                udelay(10);
-               outb(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
+               outb(8, hwif->io_ports.ctl_addr);
                do {
                        udelay(50);
-                       stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+                       stat = hwif->INB(hwif->io_ports.status_addr);
                        if (stat == 0xff)
                                break;
                } while ((stat & BUSY_STAT) && --timeout);
@@ -246,7 +244,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
        }
 
        if (!using_inta)
-               hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]);
+               hwif->irq = ide_default_irq(hwif->io_ports.data_addr);
        else if (!hwif->irq && hwif->mate && hwif->mate->irq)
                hwif->irq = hwif->mate->irq;    /* share IRQ with mate */
 
@@ -254,19 +252,33 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
                return;
 
        outb(0x60, hwif->dma_status);
-       hwif->dma_setup = &ns87415_ide_dma_setup;
-       hwif->ide_dma_end = &ns87415_ide_dma_end;
 }
 
+static const struct ide_port_ops ns87415_port_ops = {
+       .selectproc             = ns87415_selectproc,
+};
+
+static const struct ide_dma_ops ns87415_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ns87415_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = ide_dma_start,
+       .dma_end                = ns87415_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
 static const struct ide_port_info ns87415_chipset __devinitdata = {
        .name           = "NS87415",
 #ifdef CONFIG_SUPERIO
        .init_iops      = init_iops_ns87415,
 #endif
        .init_hwif      = init_hwif_ns87415,
+       .port_ops       = &ns87415_port_ops,
+       .dma_ops        = &ns87415_dma_ops,
        .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
-                         IDE_HFLAG_NO_ATAPI_DMA |
-                         IDE_HFLAG_BOOTABLE,
+                         IDE_HFLAG_NO_ATAPI_DMA,
 };
 
 static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
index 46e8748f507e57cdb985007b32f18e80619f93a6..6e99080497bfea0633d504d0c4c99ce557c35b5a 100644 (file)
  * If you then set the second drive to another PIO, the old value
  * (automatically selected) will be overrided by yours.
  * There is a 25/33MHz switch in configuration
- * register, but driver is written for use at any frequency which get
- * (use idebus=xx to select PCI bus speed).
+ * register, but driver is written for use at any frequency.
  *
  * Version 0.1, Nov 8, 1996
- * by Jaromir Koutek, for 2.1.8. 
+ * by Jaromir Koutek, for 2.1.8.
  * Initial version of driver.
- * 
+ *
  * Version 0.2
  * Number 0.2 skipped.
  *
@@ -75,7 +74,7 @@
  * by Jaromir Koutek
  * Updates for use with (again) new IDE block driver.
  * Update of documentation.
- * 
+ *
  * Version 0.6, Jan 2, 1999
  * by Jaromir Koutek
  * Reversed to version 0.3 of the driver, because
@@ -208,29 +207,34 @@ typedef struct pio_clocks_s {
 
 static void compute_clocks(int pio, pio_clocks_t *clks)
 {
-        if (pio != PIO_NOT_EXIST) {
-               int adr_setup, data_pls;
-               int bus_speed = system_bus_clock();
-
-               adr_setup = ide_pio_timings[pio].setup_time;
-               data_pls = ide_pio_timings[pio].active_time;
-               clks->address_time = cmpt_clk(adr_setup, bus_speed);
-               clks->data_time = cmpt_clk(data_pls, bus_speed);
-               clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time
-                       - adr_setup-data_pls, bus_speed);
-               if (clks->address_time<1) clks->address_time = 1;
-               if (clks->address_time>4) clks->address_time = 4;
-               if (clks->data_time<1) clks->data_time = 1;
-               if (clks->data_time>16) clks->data_time = 16;
-               if (clks->recovery_time<2) clks->recovery_time = 2;
-               if (clks->recovery_time>17) clks->recovery_time = 17;
+       if (pio != PIO_NOT_EXIST) {
+               int adr_setup, data_pls;
+               int bus_speed = ide_pci_clk ? ide_pci_clk : system_bus_clock();
+
+               adr_setup = ide_pio_timings[pio].setup_time;
+               data_pls = ide_pio_timings[pio].active_time;
+               clks->address_time = cmpt_clk(adr_setup, bus_speed);
+               clks->data_time = cmpt_clk(data_pls, bus_speed);
+               clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time
+                       - adr_setup-data_pls, bus_speed);
+               if (clks->address_time < 1)
+                       clks->address_time = 1;
+               if (clks->address_time > 4)
+                       clks->address_time = 4;
+               if (clks->data_time < 1)
+                       clks->data_time = 1;
+               if (clks->data_time > 16)
+                       clks->data_time = 16;
+               if (clks->recovery_time < 2)
+                       clks->recovery_time = 2;
+               if (clks->recovery_time > 17)
+                       clks->recovery_time = 17;
        } else {
                clks->address_time = 1;
                clks->data_time = 1;
                clks->recovery_time = 2;
                /* minimal values */
        }
 }
 
 static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
@@ -247,8 +251,8 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
 
        /* sets drive->drive_data for both drives */
        compute_pios(drive, pio);
-       pio1 = hwif->drives[0].drive_data;
-       pio2 = hwif->drives[1].drive_data;
+       pio1 = hwif->drives[0].drive_data;
+       pio2 = hwif->drives[1].drive_data;
 
        compute_clocks(pio1, &first);
        compute_clocks(pio2, &second);
@@ -275,7 +279,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
 
        spin_lock_irqsave(&opti621_lock, flags);
 
-       reg_base = hwif->io_ports[IDE_DATA_OFFSET];
+       reg_base = hwif->io_ports.data_addr;
 
        /* allow Register-B */
        outb(0xc0, reg_base + CNTRL_REG);
@@ -321,31 +325,25 @@ static void __devinit opti621_port_init_devs(ide_hwif_t *hwif)
        hwif->drives[1].drive_data = PIO_DONT_KNOW;
 }
 
-/*
- * init_hwif_opti621() is called once for each hwif found at boot.
- */
-static void __devinit init_hwif_opti621 (ide_hwif_t *hwif)
-{
-       hwif->port_init_devs = opti621_port_init_devs;
-       hwif->set_pio_mode = &opti621_set_pio_mode;
-}
+static const struct ide_port_ops opti621_port_ops = {
+       .port_init_devs         = opti621_port_init_devs,
+       .set_pio_mode           = opti621_set_pio_mode,
+};
 
 static const struct ide_port_info opti621_chipsets[] __devinitdata = {
        {       /* 0 */
                .name           = "OPTI621",
-               .init_hwif      = init_hwif_opti621,
-               .enablebits     = {{0x45,0x80,0x00}, {0x40,0x08,0x00}},
-               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
-                                 IDE_HFLAG_BOOTABLE,
+               .enablebits     = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} },
+               .port_ops       = &opti621_port_ops,
+               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA,
                .pio_mask       = ATA_PIO3,
                .swdma_mask     = ATA_SWDMA2,
                .mwdma_mask     = ATA_MWDMA2,
-       },    /* 1 */
+       }, {    /* 1 */
                .name           = "OPTI621X",
-               .init_hwif      = init_hwif_opti621,
-               .enablebits     = {{0x45,0x80,0x00}, {0x40,0x08,0x00}},
-               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
-                                 IDE_HFLAG_BOOTABLE,
+               .enablebits     = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} },
+               .port_ops       = &opti621_port_ops,
+               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA,
                .pio_mask       = ATA_PIO3,
                .swdma_mask     = ATA_SWDMA2,
                .mwdma_mask     = ATA_MWDMA2,
index 1c8cb7797a4aea2a6800c22da7ab251fe9cb8163..ec9bd7b352fc031d1308d493e8da7ca9ad705b06 100644 (file)
@@ -34,7 +34,7 @@
 #undef DEBUG
 
 #ifdef DEBUG
-#define DBG(fmt, args...) printk("%s: " fmt, __FUNCTION__, ## args)
+#define DBG(fmt, args...) printk("%s: " fmt, __func__, ## args)
 #else
 #define DBG(fmt, args...)
 #endif
@@ -442,17 +442,6 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
        return dev->irq;
 }
 
-static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
-{
-       hwif->set_pio_mode = &pdcnew_set_pio_mode;
-       hwif->set_dma_mode = &pdcnew_set_dma_mode;
-
-       hwif->quirkproc = &pdcnew_quirkproc;
-       hwif->resetproc = &pdcnew_reset;
-
-       hwif->cable_detect = pdcnew_cable_detect;
-}
-
 static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
 {
        struct pci_dev *dev2;
@@ -476,11 +465,19 @@ static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
        return NULL;
 }
 
+static const struct ide_port_ops pdcnew_port_ops = {
+       .set_pio_mode           = pdcnew_set_pio_mode,
+       .set_dma_mode           = pdcnew_set_dma_mode,
+       .quirkproc              = pdcnew_quirkproc,
+       .resetproc              = pdcnew_reset,
+       .cable_detect           = pdcnew_cable_detect,
+};
+
 #define DECLARE_PDCNEW_DEV(name_str, udma) \
        { \
                .name           = name_str, \
                .init_chipset   = init_chipset_pdcnew, \
-               .init_hwif      = init_hwif_pdc202new, \
+               .port_ops       = &pdcnew_port_ops, \
                .host_flags     = IDE_HFLAG_POST_SET_MODE | \
                                  IDE_HFLAG_ERROR_STOPS_FIFO | \
                                  IDE_HFLAG_OFF_BOARD, \
index 150422ec3cfabc6685d8f6a8bf5b82804cf969b4..fca89eda5c022cf8538eeaa0e89dd9344223d6ec 100644 (file)
@@ -115,7 +115,7 @@ static void pdc202xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
        pdc202xx_set_mode(drive, XFER_PIO_0 + pio);
 }
 
-static u8 __devinit pdc2026x_old_cable_detect(ide_hwif_t *hwif)
+static u8 __devinit pdc2026x_cable_detect(ide_hwif_t *hwif)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
        u16 CIS, mask = hwif->channel ? (1 << 11) : (1 << 10);
@@ -163,7 +163,7 @@ static void pdc202xx_quirkproc(ide_drive_t *drive)
        drive->quirk_list = 0;
 }
 
-static void pdc202xx_old_ide_dma_start(ide_drive_t *drive)
+static void pdc202xx_dma_start(ide_drive_t *drive)
 {
        if (drive->current_speed > XFER_UDMA_2)
                pdc_old_enable_66MHz_clock(drive->hwif);
@@ -185,7 +185,7 @@ static void pdc202xx_old_ide_dma_start(ide_drive_t *drive)
        ide_dma_start(drive);
 }
 
-static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
+static int pdc202xx_dma_end(ide_drive_t *drive)
 {
        if (drive->media != ide_disk || drive->addressing == 1) {
                ide_hwif_t *hwif        = HWIF(drive);
@@ -202,7 +202,7 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
        return __ide_dma_end(drive);
 }
 
-static int pdc202xx_old_ide_dma_test_irq(ide_drive_t *drive)
+static int pdc202xx_dma_test_irq(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        unsigned long high_16   = hwif->extra_base - 16;
@@ -226,26 +226,6 @@ somebody_else:
        return (dma_stat & 4) == 4;     /* return 1 if INTR asserted */
 }
 
-static void pdc202xx_dma_lost_irq(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-
-       if (hwif->resetproc != NULL)
-               hwif->resetproc(drive);
-
-       ide_dma_lost_irq(drive);
-}
-
-static void pdc202xx_dma_timeout(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-
-       if (hwif->resetproc != NULL)
-               hwif->resetproc(drive);
-
-       ide_dma_timeout(drive);
-}
-
 static void pdc202xx_reset_host (ide_hwif_t *hwif)
 {
        unsigned long high_16   = hwif->extra_base - 16;
@@ -271,68 +251,46 @@ static void pdc202xx_reset (ide_drive_t *drive)
        ide_set_max_pio(drive);
 }
 
-static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev,
-                                                       const char *name)
+static void pdc202xx_dma_lost_irq(ide_drive_t *drive)
 {
-       return dev->irq;
+       pdc202xx_reset(drive);
+       ide_dma_lost_irq(drive);
 }
 
-static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif)
+static void pdc202xx_dma_timeout(ide_drive_t *drive)
 {
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-       hwif->set_pio_mode = &pdc202xx_set_pio_mode;
-       hwif->set_dma_mode = &pdc202xx_set_mode;
-
-       hwif->quirkproc = &pdc202xx_quirkproc;
-
-       if (dev->device != PCI_DEVICE_ID_PROMISE_20246) {
-               hwif->resetproc = &pdc202xx_reset;
-
-               hwif->cable_detect = pdc2026x_old_cable_detect;
-       }
-
-       if (hwif->dma_base == 0)
-               return;
-
-       hwif->dma_lost_irq = &pdc202xx_dma_lost_irq;
-       hwif->dma_timeout = &pdc202xx_dma_timeout;
-
-       if (dev->device != PCI_DEVICE_ID_PROMISE_20246) {
-               hwif->dma_start = &pdc202xx_old_ide_dma_start;
-               hwif->ide_dma_end = &pdc202xx_old_ide_dma_end;
-       } 
-       hwif->ide_dma_test_irq = &pdc202xx_old_ide_dma_test_irq;
+       pdc202xx_reset(drive);
+       ide_dma_timeout(drive);
 }
 
-static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase)
+static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev,
+                                                   const char *name)
 {
+       unsigned long dmabase = pci_resource_start(dev, 4);
        u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0;
 
-       if (hwif->channel) {
-               ide_setup_dma(hwif, dmabase);
-               return;
-       }
+       if (dmabase == 0)
+               goto out;
 
        udma_speed_flag = inb(dmabase | 0x1f);
        primary_mode    = inb(dmabase | 0x1a);
        secondary_mode  = inb(dmabase | 0x1b);
        printk(KERN_INFO "%s: (U)DMA Burst Bit %sABLED " \
                "Primary %s Mode " \
-               "Secondary %s Mode.\n", hwif->cds->name,
+               "Secondary %s Mode.\n", pci_name(dev),
                (udma_speed_flag & 1) ? "EN" : "DIS",
                (primary_mode & 1) ? "MASTER" : "PCI",
                (secondary_mode & 1) ? "MASTER" : "PCI" );
 
        if (!(udma_speed_flag & 1)) {
                printk(KERN_INFO "%s: FORCING BURST BIT 0x%02x->0x%02x ",
-                       hwif->cds->name, udma_speed_flag,
+                       pci_name(dev), udma_speed_flag,
                        (udma_speed_flag|1));
                outb(udma_speed_flag | 1, dmabase | 0x1f);
                printk("%sACTIVE\n", (inb(dmabase | 0x1f) & 1) ? "" : "IN");
        }
-
-       ide_setup_dma(hwif, dmabase);
+out:
+       return dev->irq;
 }
 
 static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
@@ -357,13 +315,48 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
         IDE_HFLAG_ABUSE_SET_DMA_MODE | \
         IDE_HFLAG_OFF_BOARD)
 
+static const struct ide_port_ops pdc20246_port_ops = {
+       .set_pio_mode           = pdc202xx_set_pio_mode,
+       .set_dma_mode           = pdc202xx_set_mode,
+       .quirkproc              = pdc202xx_quirkproc,
+};
+
+static const struct ide_port_ops pdc2026x_port_ops = {
+       .set_pio_mode           = pdc202xx_set_pio_mode,
+       .set_dma_mode           = pdc202xx_set_mode,
+       .quirkproc              = pdc202xx_quirkproc,
+       .resetproc              = pdc202xx_reset,
+       .cable_detect           = pdc2026x_cable_detect,
+};
+
+static const struct ide_dma_ops pdc20246_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = ide_dma_start,
+       .dma_end                = __ide_dma_end,
+       .dma_test_irq           = pdc202xx_dma_test_irq,
+       .dma_lost_irq           = pdc202xx_dma_lost_irq,
+       .dma_timeout            = pdc202xx_dma_timeout,
+};
+
+static const struct ide_dma_ops pdc2026x_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = pdc202xx_dma_start,
+       .dma_end                = pdc202xx_dma_end,
+       .dma_test_irq           = pdc202xx_dma_test_irq,
+       .dma_lost_irq           = pdc202xx_dma_lost_irq,
+       .dma_timeout            = pdc202xx_dma_timeout,
+};
+
 #define DECLARE_PDC2026X_DEV(name_str, udma, extra_flags) \
        { \
                .name           = name_str, \
                .init_chipset   = init_chipset_pdc202xx, \
-               .init_hwif      = init_hwif_pdc202xx, \
-               .init_dma       = init_dma_pdc202xx, \
-               .extra          = 48, \
+               .port_ops       = &pdc2026x_port_ops, \
+               .dma_ops        = &pdc2026x_dma_ops, \
                .host_flags     = IDE_HFLAGS_PDC202XX | extra_flags, \
                .pio_mask       = ATA_PIO4, \
                .mwdma_mask     = ATA_MWDMA2, \
@@ -374,9 +367,8 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
        {       /* 0 */
                .name           = "PDC20246",
                .init_chipset   = init_chipset_pdc202xx,
-               .init_hwif      = init_hwif_pdc202xx,
-               .init_dma       = init_dma_pdc202xx,
-               .extra          = 16,
+               .port_ops       = &pdc20246_port_ops,
+               .dma_ops        = &pdc20246_dma_ops,
                .host_flags     = IDE_HFLAGS_PDC202XX,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
index decef0f476748ab0858360f3bc9fbfa647f96f06..21c5dd23f928561d28157573e2b6d4cbfa7678ad 100644 (file)
@@ -285,11 +285,6 @@ static u8 __devinit piix_cable_detect(ide_hwif_t *hwif)
 
 static void __devinit init_hwif_piix(ide_hwif_t *hwif)
 {
-       hwif->set_pio_mode = &piix_set_pio_mode;
-       hwif->set_dma_mode = &piix_set_dma_mode;
-
-       hwif->cable_detect = piix_cable_detect;
-
        if (!hwif->dma_base)
                return;
 
@@ -306,10 +301,16 @@ static void __devinit init_hwif_ich(ide_hwif_t *hwif)
                hwif->ide_dma_clear_irq = &piix_dma_clear_irq;
 }
 
+static const struct ide_port_ops piix_port_ops = {
+       .set_pio_mode           = piix_set_pio_mode,
+       .set_dma_mode           = piix_set_dma_mode,
+       .cable_detect           = piix_cable_detect,
+};
+
 #ifndef CONFIG_IA64
- #define IDE_HFLAGS_PIIX (IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE)
+ #define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS
 #else
- #define IDE_HFLAGS_PIIX IDE_HFLAG_BOOTABLE
+ #define IDE_HFLAGS_PIIX 0
 #endif
 
 #define DECLARE_PIIX_DEV(name_str, udma) \
@@ -317,6 +318,7 @@ static void __devinit init_hwif_ich(ide_hwif_t *hwif)
                .name           = name_str,             \
                .init_hwif      = init_hwif_piix,       \
                .enablebits     = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
+               .port_ops       = &piix_port_ops,       \
                .host_flags     = IDE_HFLAGS_PIIX,      \
                .pio_mask       = ATA_PIO4,             \
                .swdma_mask     = ATA_SWDMA2_ONLY,      \
@@ -330,6 +332,7 @@ static void __devinit init_hwif_ich(ide_hwif_t *hwif)
                .init_chipset   = init_chipset_ich, \
                .init_hwif      = init_hwif_ich, \
                .enablebits     = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
+               .port_ops       = &piix_port_ops, \
                .host_flags     = IDE_HFLAGS_PIIX, \
                .pio_mask       = ATA_PIO4, \
                .swdma_mask     = ATA_SWDMA2_ONLY, \
index 51676612f78f0d603e49e8456a8012ca54f58f06..532154adba2945738d27cb30066c292f2a09c05f 100644 (file)
@@ -43,7 +43,7 @@ static const struct ide_port_info rz1000_chipset __devinitdata = {
        .name           = "RZ100x",
        .init_hwif      = init_hwif_rz1000,
        .chipset        = ide_rz1000,
-       .host_flags     = IDE_HFLAG_NO_DMA | IDE_HFLAG_BOOTABLE,
+       .host_flags     = IDE_HFLAG_NO_DMA,
 };
 
 static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id)
index 561aa47c7720fafa38c615a4fa36d0dd62dba76d..14c787b5d95f89c8fd6406d22cd82ef72d4322bb 100644 (file)
@@ -165,7 +165,7 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
  *
  *  returns 1 on error, 0 otherwise
  */
-static int sc1200_ide_dma_end (ide_drive_t *drive)
+static int sc1200_dma_end(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = HWIF(drive);
        unsigned long dma_base = hwif->dma_base;
@@ -214,7 +214,7 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio)
                printk("SC1200: %s: changing (U)DMA mode\n", drive->name);
                ide_dma_off_quietly(drive);
                if (ide_set_dma_mode(drive, mode) == 0 && drive->using_dma)
-                       hwif->dma_host_set(drive, 1);
+                       hwif->dma_ops->dma_host_set(drive, 1);
                return;
        }
 
@@ -286,29 +286,30 @@ static int sc1200_resume (struct pci_dev *dev)
 }
 #endif
 
-/*
- * This gets invoked by the IDE driver once for each channel,
- * and performs channel-specific pre-initialization before drive probing.
- */
-static void __devinit init_hwif_sc1200 (ide_hwif_t *hwif)
-{
-       hwif->set_pio_mode = &sc1200_set_pio_mode;
-       hwif->set_dma_mode = &sc1200_set_dma_mode;
-
-       if (hwif->dma_base == 0)
-               return;
+static const struct ide_port_ops sc1200_port_ops = {
+       .set_pio_mode           = sc1200_set_pio_mode,
+       .set_dma_mode           = sc1200_set_dma_mode,
+       .udma_filter            = sc1200_udma_filter,
+};
 
-       hwif->udma_filter = sc1200_udma_filter;
-       hwif->ide_dma_end   = &sc1200_ide_dma_end;
-}
+static const struct ide_dma_ops sc1200_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = ide_dma_start,
+       .dma_end                = sc1200_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
 
 static const struct ide_port_info sc1200_chipset __devinitdata = {
        .name           = "SC1200",
-       .init_hwif      = init_hwif_sc1200,
+       .port_ops       = &sc1200_port_ops,
+       .dma_ops        = &sc1200_dma_ops,
        .host_flags     = IDE_HFLAG_SERIALIZE |
                          IDE_HFLAG_POST_SET_MODE |
-                         IDE_HFLAG_ABUSE_DMA_MODES |
-                         IDE_HFLAG_BOOTABLE,
+                         IDE_HFLAG_ABUSE_DMA_MODES,
        .pio_mask       = ATA_PIO4,
        .mwdma_mask     = ATA_MWDMA2,
        .udma_mask      = ATA_UDMA2,
index ef07c7a8b97ae5a3868f8613a3ed8abaf9e06dc6..ad7cdf9060ca3e1367951fe7221981590ebce041 100644 (file)
@@ -65,7 +65,7 @@
 
 static struct scc_ports {
        unsigned long ctl, dma;
-       unsigned char hwif_id;  /* for removing hwif from system */
+       ide_hwif_t *hwif;  /* for removing port from system */
 } scc_ports[MAX_HWIFS];
 
 /* PIO transfer mode  table */
@@ -317,14 +317,14 @@ static int scc_dma_setup(ide_drive_t *drive)
 
 
 /**
- *     scc_ide_dma_end -       Stop DMA
+ *     scc_dma_end     -       Stop DMA
  *     @drive: IDE drive
  *
  *     Check and clear INT Status register.
  *      Then call __ide_dma_end().
  */
 
-static int scc_ide_dma_end(ide_drive_t * drive)
+static int scc_dma_end(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = HWIF(drive);
        unsigned long intsts_port = hwif->dma_base + 0x014;
@@ -334,7 +334,7 @@ static int scc_ide_dma_end(ide_drive_t * drive)
 
        /* errata A308 workaround: Step5 (check data loss) */
        /* We don't check non ide_disk because it is limited to UDMA4 */
-       if (!(in_be32((void __iomem *)hwif->io_ports[IDE_ALTSTATUS_OFFSET])
+       if (!(in_be32((void __iomem *)hwif->io_ports.ctl_addr)
              & ERR_STAT) &&
            drive->media == ide_disk && drive->current_speed > XFER_UDMA_4) {
                reg = in_be32((void __iomem *)intsts_port);
@@ -438,7 +438,7 @@ static int scc_dma_test_irq(ide_drive_t *drive)
        u32 int_stat = in_be32((void __iomem *)hwif->dma_base + 0x014);
 
        /* SCC errata A252,A308 workaround: Step4 */
-       if ((in_be32((void __iomem *)hwif->io_ports[IDE_ALTSTATUS_OFFSET])
+       if ((in_be32((void __iomem *)hwif->io_ports.ctl_addr)
             & ERR_STAT) &&
            (int_stat & INTSTS_INTRQ))
                return 1;
@@ -449,7 +449,7 @@ static int scc_dma_test_irq(ide_drive_t *drive)
 
        if (!drive->waiting_for_dma)
                printk(KERN_WARNING "%s: (%s) called while not waiting\n",
-                       drive->name, __FUNCTION__);
+                       drive->name, __func__);
        return 0;
 }
 
@@ -483,7 +483,7 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name)
        unsigned long dma_size = pci_resource_len(dev, 1);
        void __iomem *ctl_addr;
        void __iomem *dma_addr;
-       int i;
+       int i, ret;
 
        for (i = 0; i < MAX_HWIFS; i++) {
                if (scc_ports[i].ctl == 0)
@@ -492,21 +492,17 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name)
        if (i >= MAX_HWIFS)
                return -ENOMEM;
 
-       if (!request_mem_region(ctl_base, ctl_size, name)) {
-               printk(KERN_WARNING "%s: IDE controller MMIO ports not available.\n", SCC_PATA_NAME);
-               goto fail_0;
-       }
-
-       if (!request_mem_region(dma_base, dma_size, name)) {
-               printk(KERN_WARNING "%s: IDE controller MMIO ports not available.\n", SCC_PATA_NAME);
-               goto fail_1;
+       ret = pci_request_selected_regions(dev, (1 << 2) - 1, name);
+       if (ret < 0) {
+               printk(KERN_ERR "%s: can't reserve resources\n", name);
+               return ret;
        }
 
        if ((ctl_addr = ioremap(ctl_base, ctl_size)) == NULL)
-               goto fail_2;
+               goto fail_0;
 
        if ((dma_addr = ioremap(dma_base, dma_size)) == NULL)
-               goto fail_3;
+               goto fail_1;
 
        pci_set_master(dev);
        scc_ports[i].ctl = (unsigned long)ctl_addr;
@@ -515,12 +511,8 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name)
 
        return 1;
 
- fail_3:
-       iounmap(ctl_addr);
- fail_2:
-       release_mem_region(dma_base, dma_size);
  fail_1:
-       release_mem_region(ctl_base, ctl_size);
+       iounmap(ctl_addr);
  fail_0:
        return -ENOMEM;
 }
@@ -534,26 +526,21 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev,
        u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
        int i;
 
-       for (i = 0; i < MAX_HWIFS; i++) {
-               hwif = &ide_hwifs[i];
-               if (hwif->chipset == ide_unknown)
-                       break; /* pick an unused entry */
-       }
-       if (i == MAX_HWIFS) {
+       hwif = ide_find_port();
+       if (hwif == NULL) {
                printk(KERN_ERR "%s: too many IDE interfaces, "
                                "no room in table\n", SCC_PATA_NAME);
                return -ENOMEM;
        }
 
        memset(&hw, 0, sizeof(hw));
-       for (i = IDE_DATA_OFFSET; i <= IDE_CONTROL_OFFSET; i++)
-               hw.io_ports[i] = ports->dma + 0x20 + i * 4;
+       for (i = 0; i <= 8; i++)
+               hw.io_ports_array[i] = ports->dma + 0x20 + i * 4;
        hw.irq = dev->irq;
        hw.dev = &dev->dev;
        hw.chipset = ide_pci;
        ide_init_port_hw(hwif, &hw);
        hwif->dev = &dev->dev;
-       hwif->cds = d;
 
        idx[0] = hwif->index;
 
@@ -696,7 +683,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
 {
        struct scc_ports *ports = ide_get_hwifdata(hwif);
 
-       ports->hwif_id = hwif->index;
+       ports->hwif = hwif;
 
        hwif->dma_command = hwif->dma_base;
        hwif->dma_status = hwif->dma_base + 0x04;
@@ -705,28 +692,38 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
        /* PTERADD */
        out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma);
 
-       hwif->dma_setup = scc_dma_setup;
-       hwif->ide_dma_end = scc_ide_dma_end;
-       hwif->set_pio_mode = scc_set_pio_mode;
-       hwif->set_dma_mode = scc_set_dma_mode;
-       hwif->ide_dma_test_irq = scc_dma_test_irq;
-       hwif->udma_filter = scc_udma_filter;
-
        if (in_be32((void __iomem *)(hwif->config_data + 0xff0)) & CCKCTRL_ATACLKOEN)
                hwif->ultra_mask = ATA_UDMA6; /* 133MHz */
        else
                hwif->ultra_mask = ATA_UDMA5; /* 100MHz */
-
-       hwif->cable_detect = scc_cable_detect;
 }
 
+static const struct ide_port_ops scc_port_ops = {
+       .set_pio_mode           = scc_set_pio_mode,
+       .set_dma_mode           = scc_set_dma_mode,
+       .udma_filter            = scc_udma_filter,
+       .cable_detect           = scc_cable_detect,
+};
+
+static const struct ide_dma_ops scc_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = scc_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = ide_dma_start,
+       .dma_end                = scc_dma_end,
+       .dma_test_irq           = scc_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
 #define DECLARE_SCC_DEV(name_str)                      \
   {                                                    \
       .name            = name_str,                     \
       .init_iops       = init_iops_scc,                \
       .init_hwif       = init_hwif_scc,                \
-      .host_flags      = IDE_HFLAG_SINGLE |            \
-                         IDE_HFLAG_BOOTABLE,           \
+      .port_ops                = &scc_port_ops,                \
+      .dma_ops         = &scc_dma_ops,                 \
+      .host_flags      = IDE_HFLAG_SINGLE,             \
       .pio_mask                = ATA_PIO4,                     \
   }
 
@@ -758,11 +755,7 @@ static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_i
 static void __devexit scc_remove(struct pci_dev *dev)
 {
        struct scc_ports *ports = pci_get_drvdata(dev);
-       ide_hwif_t *hwif = &ide_hwifs[ports->hwif_id];
-       unsigned long ctl_base = pci_resource_start(dev, 0);
-       unsigned long dma_base = pci_resource_start(dev, 1);
-       unsigned long ctl_size = pci_resource_len(dev, 0);
-       unsigned long dma_size = pci_resource_len(dev, 1);
+       ide_hwif_t *hwif = ports->hwif;
 
        if (hwif->dmatable_cpu) {
                pci_free_consistent(dev, PRD_ENTRIES * PRD_BYTES,
@@ -770,13 +763,11 @@ static void __devexit scc_remove(struct pci_dev *dev)
                hwif->dmatable_cpu = NULL;
        }
 
-       ide_unregister(hwif->index);
+       ide_unregister(hwif);
 
-       hwif->chipset = ide_unknown;
        iounmap((void*)ports->dma);
        iounmap((void*)ports->ctl);
-       release_mem_region(dma_base, dma_size);
-       release_mem_region(ctl_base, ctl_size);
+       pci_release_selected_regions(dev, (1 << 2) - 1);
        memset(ports, 0, sizeof(*ports));
 }
 
index c11880b0709f711c4ee49ef2edc376f8e57e1df6..a1fb20826a5b817244d500db92c921a054c9ddee 100644 (file)
@@ -312,7 +312,7 @@ static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif)
        return ATA_CBL_PATA40;
 }
 
-static u8 __devinit ata66_svwks(ide_hwif_t *hwif)
+static u8 __devinit svwks_cable_detect(ide_hwif_t *hwif)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
 
@@ -336,28 +336,28 @@ static u8 __devinit ata66_svwks(ide_hwif_t *hwif)
        return ATA_CBL_PATA40;
 }
 
-static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-       hwif->set_pio_mode = &svwks_set_pio_mode;
-       hwif->set_dma_mode = &svwks_set_dma_mode;
-       hwif->udma_filter = &svwks_udma_filter;
+static const struct ide_port_ops osb4_port_ops = {
+       .set_pio_mode           = svwks_set_pio_mode,
+       .set_dma_mode           = svwks_set_dma_mode,
+       .udma_filter            = svwks_udma_filter,
+};
 
-       if (dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE)
-               hwif->cable_detect = ata66_svwks;
-}
+static const struct ide_port_ops svwks_port_ops = {
+       .set_pio_mode           = svwks_set_pio_mode,
+       .set_dma_mode           = svwks_set_dma_mode,
+       .udma_filter            = svwks_udma_filter,
+       .cable_detect           = svwks_cable_detect,
+};
 
 #define IDE_HFLAGS_SVWKS \
        (IDE_HFLAG_LEGACY_IRQS | \
-        IDE_HFLAG_ABUSE_SET_DMA_MODE | \
-        IDE_HFLAG_BOOTABLE)
+        IDE_HFLAG_ABUSE_SET_DMA_MODE)
 
 static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
        {       /* 0 */
                .name           = "SvrWks OSB4",
                .init_chipset   = init_chipset_svwks,
-               .init_hwif      = init_hwif_svwks,
+               .port_ops       = &osb4_port_ops,
                .host_flags     = IDE_HFLAGS_SVWKS,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
@@ -365,7 +365,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
        },{     /* 1 */
                .name           = "SvrWks CSB5",
                .init_chipset   = init_chipset_svwks,
-               .init_hwif      = init_hwif_svwks,
+               .port_ops       = &svwks_port_ops,
                .host_flags     = IDE_HFLAGS_SVWKS,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
@@ -373,7 +373,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
        },{     /* 2 */
                .name           = "SvrWks CSB6",
                .init_chipset   = init_chipset_svwks,
-               .init_hwif      = init_hwif_svwks,
+               .port_ops       = &svwks_port_ops,
                .host_flags     = IDE_HFLAGS_SVWKS,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
@@ -381,7 +381,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
        },{     /* 3 */
                .name           = "SvrWks CSB6",
                .init_chipset   = init_chipset_svwks,
-               .init_hwif      = init_hwif_svwks,
+               .port_ops       = &svwks_port_ops,
                .host_flags     = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
@@ -389,7 +389,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
        },{     /* 4 */
                .name           = "SvrWks HT1000",
                .init_chipset   = init_chipset_svwks,
-               .init_hwif      = init_hwif_svwks,
+               .port_ops       = &svwks_port_ops,
                .host_flags     = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
@@ -418,7 +418,7 @@ static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device
        else if (idx == 2 || idx == 3) {
                if ((PCI_FUNC(dev->devfn) & 1) == 0) {
                        if (pci_resource_start(dev, 0) != 0x01f1)
-                               d.host_flags &= ~IDE_HFLAG_BOOTABLE;
+                               d.host_flags |= IDE_HFLAG_NON_BOOTABLE;
                        d.host_flags |= IDE_HFLAG_SINGLE;
                } else
                        d.host_flags &= ~IDE_HFLAG_SINGLE;
index 9d1a3038af9b717de7985803c28fdb365777dd55..63e28f4e6d3b3304221b1e991dcc9b7e622cb577 100644 (file)
@@ -98,28 +98,28 @@ sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
        int i;
 
        /* Registers are word (32 bit) aligned */
-       for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
-               hw->io_ports[i] = reg + i * 4;
+       for (i = 0; i <= 7; i++)
+               hw->io_ports_array[i] = reg + i * 4;
 
        if (ctrl_port)
-               hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+               hw->io_ports.ctl_addr = ctrl_port;
 
        if (irq_port)
-               hw->io_ports[IDE_IRQ_OFFSET] = irq_port;
+               hw->io_ports.irq_addr = irq_port;
 }
 
 static void
 sgiioc4_maskproc(ide_drive_t * drive, int mask)
 {
        writeb(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
-              (void __iomem *)drive->hwif->io_ports[IDE_CONTROL_OFFSET]);
+              (void __iomem *)drive->hwif->io_ports.ctl_addr);
 }
 
 static int
 sgiioc4_checkirq(ide_hwif_t * hwif)
 {
        unsigned long intr_addr =
-               hwif->io_ports[IDE_IRQ_OFFSET] + IOC4_INTR_REG * 4;
+               hwif->io_ports.irq_addr + IOC4_INTR_REG * 4;
 
        if ((u8)readl((void __iomem *)intr_addr) & 0x03)
                return 1;
@@ -134,8 +134,8 @@ sgiioc4_clearirq(ide_drive_t * drive)
 {
        u32 intr_reg;
        ide_hwif_t *hwif = HWIF(drive);
-       unsigned long other_ir =
-           hwif->io_ports[IDE_IRQ_OFFSET] + (IOC4_INTR_REG << 2);
+       struct ide_io_ports *io_ports = &hwif->io_ports;
+       unsigned long other_ir = io_ports->irq_addr + (IOC4_INTR_REG << 2);
 
        /* Code to check for PCI error conditions */
        intr_reg = readl((void __iomem *)other_ir);
@@ -147,12 +147,12 @@ sgiioc4_clearirq(ide_drive_t * drive)
                 * a "clear" status if it got cleared.  If not, then spin
                 * for a bit trying to clear it.
                 */
-               u8 stat = sgiioc4_INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+               u8 stat = sgiioc4_INB(io_ports->status_addr);
                int count = 0;
-               stat = sgiioc4_INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+               stat = sgiioc4_INB(io_ports->status_addr);
                while ((stat & 0x80) && (count++ < 100)) {
                        udelay(1);
-                       stat = sgiioc4_INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+                       stat = sgiioc4_INB(io_ports->status_addr);
                }
 
                if (intr_reg & 0x02) {
@@ -162,18 +162,18 @@ sgiioc4_clearirq(ide_drive_t * drive)
                            pci_stat_cmd_reg;
 
                        pci_err_addr_low =
-                               readl((void __iomem *)hwif->io_ports[IDE_IRQ_OFFSET]);
+                               readl((void __iomem *)io_ports->irq_addr);
                        pci_err_addr_high =
-                               readl((void __iomem *)(hwif->io_ports[IDE_IRQ_OFFSET] + 4));
+                               readl((void __iomem *)(io_ports->irq_addr + 4));
                        pci_read_config_dword(dev, PCI_COMMAND,
                                              &pci_stat_cmd_reg);
                        printk(KERN_ERR
                               "%s(%s) : PCI Bus Error when doing DMA:"
                                   " status-cmd reg is 0x%x\n",
-                              __FUNCTION__, drive->name, pci_stat_cmd_reg);
+                              __func__, drive->name, pci_stat_cmd_reg);
                        printk(KERN_ERR
                               "%s(%s) : PCI Error Address is 0x%x%x\n",
-                              __FUNCTION__, drive->name,
+                              __func__, drive->name,
                               pci_err_addr_high, pci_err_addr_low);
                        /* Clear the PCI Error indicator */
                        pci_write_config_dword(dev, PCI_COMMAND, 0x00000146);
@@ -188,7 +188,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
        return intr_reg & 3;
 }
 
-static void sgiioc4_ide_dma_start(ide_drive_t * drive)
+static void sgiioc4_dma_start(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = HWIF(drive);
        unsigned long ioc4_dma_addr = hwif->dma_base + IOC4_DMA_CTRL * 4;
@@ -215,8 +215,7 @@ sgiioc4_ide_dma_stop(ide_hwif_t *hwif, u64 dma_base)
 }
 
 /* Stops the IOC4 DMA Engine */
-static int
-sgiioc4_ide_dma_end(ide_drive_t * drive)
+static int sgiioc4_dma_end(ide_drive_t *drive)
 {
        u32 ioc4_dma, bc_dev, bc_mem, num, valid = 0, cnt = 0;
        ide_hwif_t *hwif = HWIF(drive);
@@ -232,7 +231,7 @@ sgiioc4_ide_dma_end(ide_drive_t * drive)
                printk(KERN_ERR
                       "%s(%s): IOC4 DMA STOP bit is still 1 :"
                       "ioc4_dma_reg 0x%x\n",
-                      __FUNCTION__, drive->name, ioc4_dma);
+                      __func__, drive->name, ioc4_dma);
                dma_stat = 1;
        }
 
@@ -251,7 +250,7 @@ sgiioc4_ide_dma_end(ide_drive_t * drive)
                udelay(1);
        }
        if (!valid) {
-               printk(KERN_ERR "%s(%s) : DMA incomplete\n", __FUNCTION__,
+               printk(KERN_ERR "%s(%s) : DMA incomplete\n", __func__,
                       drive->name);
                dma_stat = 1;
        }
@@ -264,7 +263,7 @@ sgiioc4_ide_dma_end(ide_drive_t * drive)
                        printk(KERN_ERR
                               "%s(%s): WARNING!! byte_count_dev %d "
                               "!= byte_count_mem %d\n",
-                              __FUNCTION__, drive->name, bc_dev, bc_mem);
+                              __func__, drive->name, bc_dev, bc_mem);
                }
        }
 
@@ -279,8 +278,7 @@ static void sgiioc4_set_dma_mode(ide_drive_t *drive, const u8 speed)
 }
 
 /* returns 1 if dma irq issued, 0 otherwise */
-static int
-sgiioc4_ide_dma_test_irq(ide_drive_t * drive)
+static int sgiioc4_dma_test_irq(ide_drive_t *drive)
 {
        return sgiioc4_checkirq(HWIF(drive));
 }
@@ -294,7 +292,7 @@ static void sgiioc4_dma_host_set(ide_drive_t *drive, int on)
 static void
 sgiioc4_resetproc(ide_drive_t * drive)
 {
-       sgiioc4_ide_dma_end(drive);
+       sgiioc4_dma_end(drive);
        sgiioc4_clearirq(drive);
 }
 
@@ -329,13 +327,17 @@ sgiioc4_INB(unsigned long port)
 
 /* Creates a dma map for the scatter-gather list entries */
 static int __devinit
-ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
+ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
+       unsigned long dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET;
        void __iomem *virt_dma_base;
        int num_ports = sizeof (ioc4_dma_regs_t);
        void *pad;
 
+       if (dma_base == 0)
+               return -1;
+
        printk(KERN_INFO "%s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name,
               dma_base, dma_base + num_ports - 1);
 
@@ -343,7 +345,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
                printk(KERN_ERR
                       "%s(%s) -- ERROR, Addresses 0x%p to 0x%p "
                       "ALREADY in use\n",
-                      __FUNCTION__, hwif->name, (void *) dma_base,
+                      __func__, hwif->name, (void *) dma_base,
                       (void *) dma_base + num_ports - 1);
                return -1;
        }
@@ -352,7 +354,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
        if (virt_dma_base == NULL) {
                printk(KERN_ERR
                       "%s(%s) -- ERROR, Unable to map addresses 0x%lx to 0x%lx\n",
-                      __FUNCTION__, hwif->name, dma_base, dma_base + num_ports - 1);
+                      __func__, hwif->name, dma_base, dma_base + num_ports - 1);
                goto dma_remap_failure;
        }
        hwif->dma_base = (unsigned long) virt_dma_base;
@@ -378,7 +380,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
                            hwif->dmatable_cpu, hwif->dmatable_dma);
        printk(KERN_INFO
               "%s() -- Error! Unable to allocate DMA Maps for drive %s\n",
-              __FUNCTION__, hwif->name);
+              __func__, hwif->name);
        printk(KERN_INFO
               "Changing from DMA to PIO mode for Drive %s\n", hwif->name);
 
@@ -406,14 +408,14 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
        if (ioc4_dma & IOC4_S_DMA_ACTIVE) {
                printk(KERN_WARNING
                        "%s(%s):Warning!! DMA from previous transfer was still active\n",
-                      __FUNCTION__, drive->name);
+                      __func__, drive->name);
                writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
                ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
 
                if (ioc4_dma & IOC4_S_DMA_STOP)
                        printk(KERN_ERR
                               "%s(%s) : IOC4 Dma STOP bit is still 1\n",
-                              __FUNCTION__, drive->name);
+                              __func__, drive->name);
        }
 
        ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
@@ -421,14 +423,14 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
                printk(KERN_WARNING
                       "%s(%s) : Warning!! - DMA Error during Previous"
                       " transfer | status 0x%x\n",
-                      __FUNCTION__, drive->name, ioc4_dma);
+                      __func__, drive->name, ioc4_dma);
                writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
                ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
 
                if (ioc4_dma & IOC4_S_DMA_STOP)
                        printk(KERN_ERR
                               "%s(%s) : IOC4 DMA STOP bit is still 1\n",
-                              __FUNCTION__, drive->name);
+                              __func__, drive->name);
        }
 
        /* Address of the Scatter Gather List */
@@ -519,7 +521,7 @@ use_pio_instead:
        return 0;               /* revert to PIO for this request */
 }
 
-static int sgiioc4_ide_dma_setup(ide_drive_t *drive)
+static int sgiioc4_dma_setup(ide_drive_t *drive)
 {
        struct request *rq = HWGROUP(drive)->rq;
        unsigned int count = 0;
@@ -548,62 +550,45 @@ static int sgiioc4_ide_dma_setup(ide_drive_t *drive)
        return 0;
 }
 
-static void __devinit
-ide_init_sgiioc4(ide_hwif_t * hwif)
-{
-       hwif->mmio = 1;
-       hwif->set_pio_mode = NULL; /* Sets timing for PIO mode */
-       hwif->set_dma_mode = &sgiioc4_set_dma_mode;
-       hwif->selectproc = NULL;/* Use the default routine to select drive */
-       hwif->reset_poll = NULL;/* No HBA specific reset_poll needed */
-       hwif->pre_reset = NULL; /* No HBA specific pre_set needed */
-       hwif->resetproc = &sgiioc4_resetproc;/* Reset DMA engine,
-                                               clear interrupts */
-       hwif->maskproc = &sgiioc4_maskproc;     /* Mask on/off NIEN register */
-       hwif->quirkproc = NULL;
-
-       hwif->INB = &sgiioc4_INB;
-
-       if (hwif->dma_base == 0)
-               return;
+static const struct ide_port_ops sgiioc4_port_ops = {
+       .set_dma_mode           = sgiioc4_set_dma_mode,
+       /* reset DMA engine, clear IRQs */
+       .resetproc              = sgiioc4_resetproc,
+       /* mask on/off NIEN register */
+       .maskproc               = sgiioc4_maskproc,
+};
 
-       hwif->dma_host_set = &sgiioc4_dma_host_set;
-       hwif->dma_setup = &sgiioc4_ide_dma_setup;
-       hwif->dma_start = &sgiioc4_ide_dma_start;
-       hwif->ide_dma_end = &sgiioc4_ide_dma_end;
-       hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
-       hwif->dma_lost_irq = &sgiioc4_dma_lost_irq;
-       hwif->dma_timeout = &ide_dma_timeout;
-}
+static const struct ide_dma_ops sgiioc4_dma_ops = {
+       .dma_host_set           = sgiioc4_dma_host_set,
+       .dma_setup              = sgiioc4_dma_setup,
+       .dma_start              = sgiioc4_dma_start,
+       .dma_end                = sgiioc4_dma_end,
+       .dma_test_irq           = sgiioc4_dma_test_irq,
+       .dma_lost_irq           = sgiioc4_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
 
 static const struct ide_port_info sgiioc4_port_info __devinitdata = {
        .chipset                = ide_pci,
-       .host_flags             = IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
-                                 IDE_HFLAG_NO_AUTOTUNE,
+       .init_dma               = ide_dma_sgiioc4,
+       .port_ops               = &sgiioc4_port_ops,
+       .dma_ops                = &sgiioc4_dma_ops,
        .mwdma_mask             = ATA_MWDMA2_ONLY,
 };
 
 static int __devinit
 sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
 {
-       unsigned long cmd_base, dma_base, irqport;
+       unsigned long cmd_base, irqport;
        unsigned long bar0, cmd_phys_base, ctl;
        void __iomem *virt_base;
        ide_hwif_t *hwif;
-       int h;
        u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
        hw_regs_t hw;
        struct ide_port_info d = sgiioc4_port_info;
 
-       /*
-        * Find an empty HWIF; if none available, return -ENOMEM.
-        */
-       for (h = 0; h < MAX_HWIFS; ++h) {
-               hwif = &ide_hwifs[h];
-               if (hwif->chipset == ide_unknown)
-                       break;
-       }
-       if (h == MAX_HWIFS) {
+       hwif = ide_find_port();
+       if (hwif == NULL) {
                printk(KERN_ERR "%s: too many IDE interfaces, no room in table\n",
                                DRV_NAME);
                return -ENOMEM;
@@ -620,7 +605,6 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
        cmd_base = (unsigned long) virt_base + IOC4_CMD_OFFSET;
        ctl = (unsigned long) virt_base + IOC4_CTRL_OFFSET;
        irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET;
-       dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET;
 
        cmd_phys_base = bar0 + IOC4_CMD_OFFSET;
        if (!request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
@@ -628,7 +612,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
                printk(KERN_ERR
                        "%s : %s -- ERROR, Addresses "
                        "0x%p to 0x%p ALREADY in use\n",
-                      __FUNCTION__, hwif->name, (void *) cmd_phys_base,
+                      __func__, hwif->name, (void *) cmd_phys_base,
                       (void *) cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
                return -ENOMEM;
        }
@@ -649,13 +633,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
        /* Initializing chipset IRQ Registers */
        writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
 
-       if (dma_base == 0 || ide_dma_sgiioc4(hwif, dma_base)) {
-               printk(KERN_INFO "%s: %s Bus-Master DMA disabled\n",
-                                hwif->name, DRV_NAME);
-               d.mwdma_mask = 0;
-       }
-
-       ide_init_sgiioc4(hwif);
+       hwif->INB = &sgiioc4_INB;
 
        idx[0] = hwif->index;
 
index b6be1b45f3294c27bc358a5d30574461cdf211ef..c2040a017f475e3abea81f27644ebc0b0dc49044 100644 (file)
@@ -301,7 +301,7 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
 }
 
 /* returns 1 if dma irq issued, 0 otherwise */
-static int siimage_io_ide_dma_test_irq (ide_drive_t *drive)
+static int siimage_io_dma_test_irq(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
@@ -320,14 +320,14 @@ static int siimage_io_ide_dma_test_irq (ide_drive_t *drive)
 }
 
 /**
- *     siimage_mmio_ide_dma_test_irq   -       check we caused an IRQ
+ *     siimage_mmio_dma_test_irq       -       check we caused an IRQ
  *     @drive: drive we are testing
  *
  *     Check if we caused an IDE DMA interrupt. We may also have caused
  *     SATA status interrupts, if so we clean them up and continue.
  */
-static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
+
+static int siimage_mmio_dma_test_irq(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        unsigned long addr      = siimage_selreg(hwif, 0x1);
@@ -347,7 +347,7 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
                        printk(KERN_WARNING "%s: sata_error = 0x%08x, "
                                "watchdog = %d, %s\n",
                                drive->name, sata_error, watchdog,
-                               __FUNCTION__);
+                               __func__);
 
                } else {
                        watchdog = (ext_stat & 0x8000) ? 1 : 0;
@@ -369,6 +369,14 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
        return 0;
 }
 
+static int siimage_dma_test_irq(ide_drive_t *drive)
+{
+       if (drive->hwif->mmio)
+               return siimage_mmio_dma_test_irq(drive);
+       else
+               return siimage_io_dma_test_irq(drive);
+}
+
 /**
  *     sil_sata_reset_poll     -       wait for SATA reset
  *     @drive: drive we are resetting
@@ -614,9 +622,10 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        void *addr              = pci_get_drvdata(dev);
        u8 ch                   = hwif->channel;
-       hw_regs_t               hw;
        unsigned long           base;
 
+       struct ide_io_ports *io_ports = &hwif->io_ports;
+
        /*
         *      Fill in the basic HWIF bits
         */
@@ -630,7 +639,7 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
         *      based I/O
         */
 
-       memset(&hw, 0, sizeof(hw_regs_t));
+       memset(io_ports, 0, sizeof(*io_ports));
 
        base = (unsigned long)addr;
        if (ch)
@@ -643,17 +652,15 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
         *      so we can't currently use it sanely since we want to
         *      use LBA48 mode.
         */     
-       hw.io_ports[IDE_DATA_OFFSET]    = base;
-       hw.io_ports[IDE_ERROR_OFFSET]   = base + 1;
-       hw.io_ports[IDE_NSECTOR_OFFSET] = base + 2;
-       hw.io_ports[IDE_SECTOR_OFFSET]  = base + 3;
-       hw.io_ports[IDE_LCYL_OFFSET]    = base + 4;
-       hw.io_ports[IDE_HCYL_OFFSET]    = base + 5;
-       hw.io_ports[IDE_SELECT_OFFSET]  = base + 6;
-       hw.io_ports[IDE_STATUS_OFFSET]  = base + 7;
-       hw.io_ports[IDE_CONTROL_OFFSET] = base + 10;
-
-       hw.io_ports[IDE_IRQ_OFFSET]     = 0;
+       io_ports->data_addr     = base;
+       io_ports->error_addr    = base + 1;
+       io_ports->nsect_addr    = base + 2;
+       io_ports->lbal_addr     = base + 3;
+       io_ports->lbam_addr     = base + 4;
+       io_ports->lbah_addr     = base + 5;
+       io_ports->device_addr   = base + 6;
+       io_ports->status_addr   = base + 7;
+       io_ports->ctl_addr      = base + 10;
 
        if (pdev_is_sata(dev)) {
                base = (unsigned long)addr;
@@ -664,8 +671,6 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
                hwif->sata_scr[SATA_CONTROL_OFFSET]     = base + 0x100;
        }
 
-       memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
-
        hwif->irq = dev->irq;
 
        hwif->dma_base = (unsigned long)addr + (ch ? 0x08 : 0x00);
@@ -735,14 +740,14 @@ static void __devinit init_iops_siimage(ide_hwif_t *hwif)
 }
 
 /**
- *     ata66_siimage   -       check for 80 pin cable
+ *     sil_cable_detect        -       cable detection
  *     @hwif: interface to check
  *
  *     Check for the presence of an ATA66 capable cable on the
  *     interface.
  */
 
-static u8 __devinit ata66_siimage(ide_hwif_t *hwif)
+static u8 __devinit sil_cable_detect(ide_hwif_t *hwif)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
        unsigned long addr = siimage_selreg(hwif, 0);
@@ -756,68 +761,44 @@ static u8 __devinit ata66_siimage(ide_hwif_t *hwif)
        return (ata66 & 0x01) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
 }
 
-/**
- *     init_hwif_siimage       -       set up hwif structs
- *     @hwif: interface to set up
- *
- *     We do the basic set up of the interface structure. The SIIMAGE
- *     requires several custom handlers so we override the default
- *     ide DMA handlers appropriately
- */
-
-static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
-{
-       u8 sata = is_sata(hwif);
-
-       hwif->set_pio_mode = &sil_set_pio_mode;
-       hwif->set_dma_mode = &sil_set_dma_mode;
-       hwif->quirkproc = &sil_quirkproc;
-
-       if (sata) {
-               static int first = 1;
-
-               hwif->reset_poll = &sil_sata_reset_poll;
-               hwif->pre_reset = &sil_sata_pre_reset;
-               hwif->udma_filter = &sil_sata_udma_filter;
-
-               if (first) {
-                       printk(KERN_INFO "siimage: For full SATA support you should use the libata sata_sil module.\n");
-                       first = 0;
-               }
-       } else
-               hwif->udma_filter = &sil_pata_udma_filter;
-
-       hwif->cable_detect = ata66_siimage;
-
-       if (hwif->dma_base == 0)
-               return;
+static const struct ide_port_ops sil_pata_port_ops = {
+       .set_pio_mode           = sil_set_pio_mode,
+       .set_dma_mode           = sil_set_dma_mode,
+       .quirkproc              = sil_quirkproc,
+       .udma_filter            = sil_pata_udma_filter,
+       .cable_detect           = sil_cable_detect,
+};
 
-       if (sata)
-               hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
+static const struct ide_port_ops sil_sata_port_ops = {
+       .set_pio_mode           = sil_set_pio_mode,
+       .set_dma_mode           = sil_set_dma_mode,
+       .reset_poll             = sil_sata_reset_poll,
+       .pre_reset              = sil_sata_pre_reset,
+       .quirkproc              = sil_quirkproc,
+       .udma_filter            = sil_sata_udma_filter,
+       .cable_detect           = sil_cable_detect,
+};
 
-       if (hwif->mmio) {
-               hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq;
-       } else {
-               hwif->ide_dma_test_irq = & siimage_io_ide_dma_test_irq;
-       }
-}
+static struct ide_dma_ops sil_dma_ops = {
+       .dma_test_irq           = siimage_dma_test_irq,
+};
 
-#define DECLARE_SII_DEV(name_str)                      \
+#define DECLARE_SII_DEV(name_str, p_ops)               \
        {                                               \
                .name           = name_str,             \
                .init_chipset   = init_chipset_siimage, \
                .init_iops      = init_iops_siimage,    \
-               .init_hwif      = init_hwif_siimage,    \
-               .host_flags     = IDE_HFLAG_BOOTABLE,   \
+               .port_ops       = p_ops,                \
+               .dma_ops        = &sil_dma_ops,         \
                .pio_mask       = ATA_PIO4,             \
                .mwdma_mask     = ATA_MWDMA2,           \
                .udma_mask      = ATA_UDMA6,            \
        }
 
 static const struct ide_port_info siimage_chipsets[] __devinitdata = {
-       /* 0 */ DECLARE_SII_DEV("SiI680"),
-       /* 1 */ DECLARE_SII_DEV("SiI3112 Serial ATA"),
-       /* 2 */ DECLARE_SII_DEV("Adaptec AAR-1210SA")
+       /* 0 */ DECLARE_SII_DEV("SiI680",               &sil_pata_port_ops),
+       /* 1 */ DECLARE_SII_DEV("SiI3112 Serial ATA",   &sil_sata_port_ops),
+       /* 2 */ DECLARE_SII_DEV("Adaptec AAR-1210SA",   &sil_sata_port_ops)
 };
 
 /**
@@ -831,7 +812,24 @@ static const struct ide_port_info siimage_chipsets[] __devinitdata = {
  
 static int __devinit siimage_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &siimage_chipsets[id->driver_data]);
+       struct ide_port_info d;
+       u8 idx = id->driver_data;
+
+       d = siimage_chipsets[idx];
+
+       if (idx) {
+               static int first = 1;
+
+               if (first) {
+                       printk(KERN_INFO "siimage: For full SATA support you "
+                               "should use the libata sata_sil module.\n");
+                       first = 0;
+               }
+
+               d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
+       }
+
+       return ide_setup_pci_device(dev, &d);
 }
 
 static const struct pci_device_id siimage_pci_tbl[] = {
index 512bb4c1fd5cdab9a2005fff535ea0838d3d2a90..4b0b85d8faf5ae2cba38878d7db4a3ded5504aa7 100644 (file)
 #define ATA_16         0x01
 #define ATA_33         0x02
 #define ATA_66         0x03
-#define ATA_100a       0x04 // SiS730/SiS550 is ATA100 with ATA66 layout
+#define ATA_100a       0x04 /* SiS730/SiS550 is ATA100 with ATA66 layout */
 #define ATA_100                0x05
-#define ATA_133a       0x06 // SiS961b with 133 support
-#define ATA_133                0x07 // SiS962/963
+#define ATA_133a       0x06 /* SiS961b with 133 support */
+#define ATA_133                0x07 /* SiS962/963 */
 
 static u8 chipset_family;
 
@@ -111,69 +111,70 @@ static const struct {
    Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */
 
 /* {0, ATA_16, ATA_33, ATA_66, ATA_100a, ATA_100, ATA_133} */
-static u8 cycle_time_offset[] = {0,0,5,4,4,0,0};
-static u8 cycle_time_range[] = {0,0,2,3,3,4,4};
+static u8 cycle_time_offset[] = { 0, 0, 5, 4, 4, 0, 0 };
+static u8 cycle_time_range[]  = { 0, 0, 2, 3, 3, 4, 4 };
 static u8 cycle_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
-       {0,0,0,0,0,0,0}, /* no udma */
-       {0,0,0,0,0,0,0}, /* no udma */
-       {3,2,1,0,0,0,0}, /* ATA_33 */
-       {7,5,3,2,1,0,0}, /* ATA_66 */
-       {7,5,3,2,1,0,0}, /* ATA_100a (730 specific), differences are on cycle_time range and offset */
-       {11,7,5,4,2,1,0}, /* ATA_100 */
-       {15,10,7,5,3,2,1}, /* ATA_133a (earliest 691 southbridges) */
-       {15,10,7,5,3,2,1}, /* ATA_133 */
+       {  0,  0, 0, 0, 0, 0, 0 }, /* no UDMA */
+       {  0,  0, 0, 0, 0, 0, 0 }, /* no UDMA */
+       {  3,  2, 1, 0, 0, 0, 0 }, /* ATA_33 */
+       {  7,  5, 3, 2, 1, 0, 0 }, /* ATA_66 */
+       {  7,  5, 3, 2, 1, 0, 0 }, /* ATA_100a (730 specific),
+                                     different cycle_time range and offset */
+       { 11,  7, 5, 4, 2, 1, 0 }, /* ATA_100 */
+       { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133a (earliest 691 southbridges) */
+       { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133 */
 };
 /* CRC Valid Setup Time vary across IDE clock setting 33/66/100/133
    See SiS962 data sheet for more detail */
 static u8 cvs_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
-       {0,0,0,0,0,0,0}, /* no udma */
-       {0,0,0,0,0,0,0}, /* no udma */
-       {2,1,1,0,0,0,0},
-       {4,3,2,1,0,0,0},
-       {4,3,2,1,0,0,0},
-       {6,4,3,1,1,1,0},
-       {9,6,4,2,2,2,2},
-       {9,6,4,2,2,2,2},
+       { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
+       { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
+       { 2, 1, 1, 0, 0, 0, 0 },
+       { 4, 3, 2, 1, 0, 0, 0 },
+       { 4, 3, 2, 1, 0, 0, 0 },
+       { 6, 4, 3, 1, 1, 1, 0 },
+       { 9, 6, 4, 2, 2, 2, 2 },
+       { 9, 6, 4, 2, 2, 2, 2 },
 };
 /* Initialize time, Active time, Recovery time vary across
    IDE clock settings. These 3 arrays hold the register value
    for PIO0/1/2/3/4 and DMA0/1/2 mode in order */
 static u8 ini_time_value[][8] = {
-       {0,0,0,0,0,0,0,0},
-       {0,0,0,0,0,0,0,0},
-       {2,1,0,0,0,1,0,0},
-       {4,3,1,1,1,3,1,1},
-       {4,3,1,1,1,3,1,1},
-       {6,4,2,2,2,4,2,2},
-       {9,6,3,3,3,6,3,3},
-       {9,6,3,3,3,6,3,3},
+       { 0, 0, 0, 0, 0, 0, 0, 0 },
+       { 0, 0, 0, 0, 0, 0, 0, 0 },
+       { 2, 1, 0, 0, 0, 1, 0, 0 },
+       { 4, 3, 1, 1, 1, 3, 1, 1 },
+       { 4, 3, 1, 1, 1, 3, 1, 1 },
+       { 6, 4, 2, 2, 2, 4, 2, 2 },
+       { 9, 6, 3, 3, 3, 6, 3, 3 },
+       { 9, 6, 3, 3, 3, 6, 3, 3 },
 };
 static u8 act_time_value[][8] = {
-       {0,0,0,0,0,0,0,0},
-       {0,0,0,0,0,0,0,0},
-       {9,9,9,2,2,7,2,2},
-       {19,19,19,5,4,14,5,4},
-       {19,19,19,5,4,14,5,4},
-       {28,28,28,7,6,21,7,6},
-       {38,38,38,10,9,28,10,9},
-       {38,38,38,10,9,28,10,9},
+       {  0,  0,  0,  0, 0,  0,  0, 0 },
+       {  0,  0,  0,  0, 0,  0,  0, 0 },
+       {  9,  9,  9,  2, 2,  7,  2, 2 },
+       { 19, 19, 19,  5, 4, 14,  5, 4 },
+       { 19, 19, 19,  5, 4, 14,  5, 4 },
+       { 28, 28, 28,  7, 6, 21,  7, 6 },
+       { 38, 38, 38, 10, 9, 28, 10, 9 },
+       { 38, 38, 38, 10, 9, 28, 10, 9 },
 };
 static u8 rco_time_value[][8] = {
-       {0,0,0,0,0,0,0,0},
-       {0,0,0,0,0,0,0,0},
-       {9,2,0,2,0,7,1,1},
-       {19,5,1,5,2,16,3,2},
-       {19,5,1,5,2,16,3,2},
-       {30,9,3,9,4,25,6,4},
-       {40,12,4,12,5,34,12,5},
-       {40,12,4,12,5,34,12,5},
+       {  0,  0, 0,  0, 0,  0,  0, 0 },
+       {  0,  0, 0,  0, 0,  0,  0, 0 },
+       {  9,  2, 0,  2, 0,  7,  1, 1 },
+       { 19,  5, 1,  5, 2, 16,  3, 2 },
+       { 19,  5, 1,  5, 2, 16,  3, 2 },
+       { 30,  9, 3,  9, 4, 25,  6, 4 },
+       { 40, 12, 4, 12, 5, 34, 12, 5 },
+       { 40, 12, 4, 12, 5, 34, 12, 5 },
 };
 
 /*
  * Printing configuration
  */
 /* Used for chipset type printing at boot time */
-static charchipset_capability[] = {
+static char *chipset_capability[] = {
        "ATA", "ATA 16",
        "ATA 33", "ATA 66",
        "ATA 100 (1st gen)", "ATA 100 (2nd gen)",
@@ -272,7 +273,7 @@ static void sis_program_timings(ide_drive_t *drive, const u8 mode)
                sis_ata133_program_timings(drive, mode);
 }
 
-static void config_drive_art_rwp (ide_drive_t *drive)
+static void config_drive_art_rwp(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
@@ -346,7 +347,7 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
                sis_program_timings(drive, speed);
 }
 
-static u8 sis5513_ata133_udma_filter(ide_drive_t *drive)
+static u8 sis_ata133_udma_filter(ide_drive_t *drive)
 {
        struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
        u32 regdw = 0;
@@ -358,8 +359,7 @@ static u8 sis5513_ata133_udma_filter(ide_drive_t *drive)
        return (regdw & 0x08) ? ATA_UDMA6 : ATA_UDMA5;
 }
 
-/* Chip detection and general config */
-static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const char *name)
+static int __devinit sis_find_family(struct pci_dev *dev)
 {
        struct pci_dev *host;
        int i = 0;
@@ -381,7 +381,7 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
                                chipset_family = ATA_100a;
                }
                pci_dev_put(host);
-       
+
                printk(KERN_INFO "SIS5513: %s %s controller\n",
                         SiSHostChipInfo[i].name, chipset_capability[chipset_family]);
        }
@@ -440,63 +440,60 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
                        }
        }
 
-       if (!chipset_family)
-               return -1;
+       return chipset_family;
+}
 
+static unsigned int __devinit init_chipset_sis5513(struct pci_dev *dev,
+                                                  const char *name)
+{
        /* Make general config ops here
           1/ tell IDE channels to operate in Compatibility mode only
           2/ tell old chips to allow per drive IDE timings */
 
-       {
-               u8 reg;
-               u16 regw;
-
-               switch(chipset_family) {
-                       case ATA_133:
-                               /* SiS962 operation mode */
-                               pci_read_config_word(dev, 0x50, &regw);
-                               if (regw & 0x08)
-                                       pci_write_config_word(dev, 0x50, regw&0xfff7);
-                               pci_read_config_word(dev, 0x52, &regw);
-                               if (regw & 0x08)
-                                       pci_write_config_word(dev, 0x52, regw&0xfff7);
-                               break;
-                       case ATA_133a:
-                       case ATA_100:
-                               /* Fixup latency */
-                               pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
-                               /* Set compatibility bit */
-                               pci_read_config_byte(dev, 0x49, &reg);
-                               if (!(reg & 0x01)) {
-                                       pci_write_config_byte(dev, 0x49, reg|0x01);
-                               }
-                               break;
-                       case ATA_100a:
-                       case ATA_66:
-                               /* Fixup latency */
-                               pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);
-
-                               /* On ATA_66 chips the bit was elsewhere */
-                               pci_read_config_byte(dev, 0x52, &reg);
-                               if (!(reg & 0x04)) {
-                                       pci_write_config_byte(dev, 0x52, reg|0x04);
-                               }
-                               break;
-                       case ATA_33:
-                               /* On ATA_33 we didn't have a single bit to set */
-                               pci_read_config_byte(dev, 0x09, &reg);
-                               if ((reg & 0x0f) != 0x00) {
-                                       pci_write_config_byte(dev, 0x09, reg&0xf0);
-                               }
-                       case ATA_16:
-                               /* force per drive recovery and active timings
-                                  needed on ATA_33 and below chips */
-                               pci_read_config_byte(dev, 0x52, &reg);
-                               if (!(reg & 0x08)) {
-                                       pci_write_config_byte(dev, 0x52, reg|0x08);
-                               }
-                               break;
-               }
+       u8 reg;
+       u16 regw;
+
+       switch (chipset_family) {
+       case ATA_133:
+               /* SiS962 operation mode */
+               pci_read_config_word(dev, 0x50, &regw);
+               if (regw & 0x08)
+                       pci_write_config_word(dev, 0x50, regw&0xfff7);
+               pci_read_config_word(dev, 0x52, &regw);
+               if (regw & 0x08)
+                       pci_write_config_word(dev, 0x52, regw&0xfff7);
+               break;
+       case ATA_133a:
+       case ATA_100:
+               /* Fixup latency */
+               pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
+               /* Set compatibility bit */
+               pci_read_config_byte(dev, 0x49, &reg);
+               if (!(reg & 0x01))
+                       pci_write_config_byte(dev, 0x49, reg|0x01);
+               break;
+       case ATA_100a:
+       case ATA_66:
+               /* Fixup latency */
+               pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);
+
+               /* On ATA_66 chips the bit was elsewhere */
+               pci_read_config_byte(dev, 0x52, &reg);
+               if (!(reg & 0x04))
+                       pci_write_config_byte(dev, 0x52, reg|0x04);
+               break;
+       case ATA_33:
+               /* On ATA_33 we didn't have a single bit to set */
+               pci_read_config_byte(dev, 0x09, &reg);
+               if ((reg & 0x0f) != 0x00)
+                       pci_write_config_byte(dev, 0x09, reg&0xf0);
+       case ATA_16:
+               /* force per drive recovery and active timings
+                  needed on ATA_33 and below chips */
+               pci_read_config_byte(dev, 0x52, &reg);
+               if (!(reg & 0x08))
+                       pci_write_config_byte(dev, 0x52, reg|0x08);
+               break;
        }
 
        return 0;
@@ -517,7 +514,7 @@ static const struct sis_laptop sis_laptop[] = {
        { 0, }
 };
 
-static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
+static u8 __devinit sis_cable_detect(ide_hwif_t *hwif)
 {
        struct pci_dev *pdev = to_pci_dev(hwif->dev);
        const struct sis_laptop *lap = &sis_laptop[0];
@@ -546,38 +543,44 @@ static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
        return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
 }
 
-static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
-{
-       u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f };
-
-       hwif->set_pio_mode = &sis_set_pio_mode;
-       hwif->set_dma_mode = &sis_set_dma_mode;
-
-       if (chipset_family >= ATA_133)
-               hwif->udma_filter = sis5513_ata133_udma_filter;
-
-       hwif->cable_detect = ata66_sis5513;
-
-       if (hwif->dma_base == 0)
-               return;
+static const struct ide_port_ops sis_port_ops = {
+       .set_pio_mode           = sis_set_pio_mode,
+       .set_dma_mode           = sis_set_dma_mode,
+       .cable_detect           = sis_cable_detect,
+};
 
-       hwif->ultra_mask = udma_rates[chipset_family];
-}
+static const struct ide_port_ops sis_ata133_port_ops = {
+       .set_pio_mode           = sis_set_pio_mode,
+       .set_dma_mode           = sis_set_dma_mode,
+       .udma_filter            = sis_ata133_udma_filter,
+       .cable_detect           = sis_cable_detect,
+};
 
 static const struct ide_port_info sis5513_chipset __devinitdata = {
        .name           = "SIS5513",
        .init_chipset   = init_chipset_sis5513,
-       .init_hwif      = init_hwif_sis5513,
-       .enablebits     = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
-       .host_flags     = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA |
-                         IDE_HFLAG_BOOTABLE,
+       .enablebits     = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} },
+       .host_flags     = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA,
        .pio_mask       = ATA_PIO4,
        .mwdma_mask     = ATA_MWDMA2,
 };
 
 static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &sis5513_chipset);
+       struct ide_port_info d = sis5513_chipset;
+       u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f };
+
+       if (sis_find_family(dev) == 0)
+               return -ENOTSUPP;
+
+       if (chipset_family >= ATA_133)
+               d.port_ops = &sis_ata133_port_ops;
+       else
+               d.port_ops = &sis_port_ops;
+
+       d.udma_mask = udma_rates[chipset_family];
+
+       return ide_setup_pci_device(dev, &d);
 }
 
 static const struct pci_device_id sis5513_pci_tbl[] = {
index 1f00251a4a875c02458cbf35a77aca0b9f245fff..ce84fa045d39186a05b08f41a643a00428ff4407 100644 (file)
@@ -179,7 +179,7 @@ static void sl82c105_dma_start(ide_drive_t *drive)
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        int reg                 = 0x44 + drive->dn * 4;
 
-       DBG(("%s(drive:%s)\n", __FUNCTION__, drive->name));
+       DBG(("%s(drive:%s)\n", __func__, drive->name));
 
        pci_write_config_word(dev, reg, drive->drive_data >> 16);
 
@@ -203,7 +203,7 @@ static int sl82c105_dma_end(ide_drive_t *drive)
        int reg                 = 0x44 + drive->dn * 4;
        int ret;
 
-       DBG(("%s(drive:%s)\n", __FUNCTION__, drive->name));
+       DBG(("%s(drive:%s)\n", __func__, drive->name));
 
        ret = __ide_dma_end(drive);
 
@@ -232,7 +232,7 @@ static void sl82c105_resetproc(ide_drive_t *drive)
  * Return the revision of the Winbond bridge
  * which this function is part of.
  */
-static unsigned int sl82c105_bridge_revision(struct pci_dev *dev)
+static u8 sl82c105_bridge_revision(struct pci_dev *dev)
 {
        struct pci_dev *bridge;
 
@@ -282,64 +282,59 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c
        return dev->irq;
 }
 
-/*
- * Initialise IDE channel
- */
-static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       unsigned int rev;
-
-       DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index));
-
-       hwif->set_pio_mode      = &sl82c105_set_pio_mode;
-       hwif->set_dma_mode      = &sl82c105_set_dma_mode;
-       hwif->resetproc         = &sl82c105_resetproc;
-
-       if (!hwif->dma_base)
-               return;
-
-       rev = sl82c105_bridge_revision(dev);
-       if (rev <= 5) {
-               /*
-                * Never ever EVER under any circumstances enable
-                * DMA when the bridge is this old.
-                */
-               printk("    %s: Winbond W83C553 bridge revision %d, "
-                      "BM-DMA disabled\n", hwif->name, rev);
-               return;
-       }
-
-       hwif->mwdma_mask = ATA_MWDMA2;
-
-       hwif->dma_lost_irq              = &sl82c105_dma_lost_irq;
-       hwif->dma_start                 = &sl82c105_dma_start;
-       hwif->ide_dma_end               = &sl82c105_dma_end;
-       hwif->dma_timeout               = &sl82c105_dma_timeout;
+static const struct ide_port_ops sl82c105_port_ops = {
+       .set_pio_mode           = sl82c105_set_pio_mode,
+       .set_dma_mode           = sl82c105_set_dma_mode,
+       .resetproc              = sl82c105_resetproc,
+};
 
-       if (hwif->mate)
-               hwif->serialized = hwif->mate->serialized = 1;
-}
+static const struct ide_dma_ops sl82c105_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = sl82c105_dma_start,
+       .dma_end                = sl82c105_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_lost_irq           = sl82c105_dma_lost_irq,
+       .dma_timeout            = sl82c105_dma_timeout,
+};
 
 static const struct ide_port_info sl82c105_chipset __devinitdata = {
        .name           = "W82C105",
        .init_chipset   = init_chipset_sl82c105,
-       .init_hwif      = init_hwif_sl82c105,
        .enablebits     = {{0x40,0x01,0x01}, {0x40,0x10,0x10}},
+       .port_ops       = &sl82c105_port_ops,
+       .dma_ops        = &sl82c105_dma_ops,
        .host_flags     = IDE_HFLAG_IO_32BIT |
                          IDE_HFLAG_UNMASK_IRQS |
 /* FIXME: check for Compatibility mode in generic IDE PCI code */
 #if defined(CONFIG_LOPEC) || defined(CONFIG_SANDPOINT)
                          IDE_HFLAG_FORCE_LEGACY_IRQS |
 #endif
-                         IDE_HFLAG_NO_AUTODMA |
-                         IDE_HFLAG_BOOTABLE,
+                         IDE_HFLAG_SERIALIZE_DMA |
+                         IDE_HFLAG_NO_AUTODMA,
        .pio_mask       = ATA_PIO5,
+       .mwdma_mask     = ATA_MWDMA2,
 };
 
 static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &sl82c105_chipset);
+       struct ide_port_info d = sl82c105_chipset;
+       u8 rev = sl82c105_bridge_revision(dev);
+
+       if (rev <= 5) {
+               /*
+                * Never ever EVER under any circumstances enable
+                * DMA when the bridge is this old.
+                */
+               printk(KERN_INFO "W82C105_IDE: Winbond W83C553 bridge "
+                                "revision %d, BM-DMA disabled\n", rev);
+               d.dma_ops = NULL;
+               d.mwdma_mask = 0;
+               d.host_flags &= ~IDE_HFLAG_SERIALIZE_DMA;
+       }
+
+       return ide_setup_pci_device(dev, &d);
 }
 
 static const struct pci_device_id sl82c105_pci_tbl[] = {
index 65f4c2ffaa5964604c713a1ca78719ee6112ae48..dae6e2c94d865dbdef0d8df0710ccdfe90854f53 100644 (file)
@@ -27,9 +27,9 @@ static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
        unsigned long flags;
        u16 master_data;
        u8 slave_data;
-       int control = 0;
+       int control = 0;
                                     /* ISP  RTC */
-       static const u8 timings[][2]= {
+       static const u8 timings[][2] = {
                                        { 0, 0 },
                                        { 0, 0 },
                                        { 1, 0 },
@@ -125,19 +125,17 @@ static u8 __devinit slc90e66_cable_detect(ide_hwif_t *hwif)
        return (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 }
 
-static void __devinit init_hwif_slc90e66(ide_hwif_t *hwif)
-{
-       hwif->set_pio_mode = &slc90e66_set_pio_mode;
-       hwif->set_dma_mode = &slc90e66_set_dma_mode;
-
-       hwif->cable_detect = slc90e66_cable_detect;
-}
+static const struct ide_port_ops slc90e66_port_ops = {
+       .set_pio_mode           = slc90e66_set_pio_mode,
+       .set_dma_mode           = slc90e66_set_dma_mode,
+       .cable_detect           = slc90e66_cable_detect,
+};
 
 static const struct ide_port_info slc90e66_chipset __devinitdata = {
        .name           = "SLC90E66",
-       .init_hwif      = init_hwif_slc90e66,
-       .enablebits     = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-       .host_flags     = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
+       .enablebits     = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} },
+       .port_ops       = &slc90e66_port_ops,
+       .host_flags     = IDE_HFLAG_LEGACY_IRQS,
        .pio_mask       = ATA_PIO4,
        .swdma_mask     = ATA_SWDMA2_ONLY,
        .mwdma_mask     = ATA_MWDMA12_ONLY,
index 1e4a6262bcef60733695c06797814f94972eba1c..9b4b27a4c71121c30298052a30c653f5ccffee05 100644 (file)
@@ -18,20 +18,20 @@ static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed)
        u16 mode, scr           = inw(scr_port);
 
        switch (speed) {
-               case XFER_UDMA_4:       mode = 0x00c0; break;
-               case XFER_UDMA_3:       mode = 0x00b0; break;
-               case XFER_UDMA_2:       mode = 0x00a0; break;
-               case XFER_UDMA_1:       mode = 0x0090; break;
-               case XFER_UDMA_0:       mode = 0x0080; break;
-               case XFER_MW_DMA_2:     mode = 0x0070; break;
-               case XFER_MW_DMA_1:     mode = 0x0060; break;
-               case XFER_MW_DMA_0:     mode = 0x0050; break;
-               case XFER_PIO_4:        mode = 0x0400; break;
-               case XFER_PIO_3:        mode = 0x0300; break;
-               case XFER_PIO_2:        mode = 0x0200; break;
-               case XFER_PIO_1:        mode = 0x0100; break;
-               case XFER_PIO_0:
-               default:                mode = 0x0000; break;
+       case XFER_UDMA_4:       mode = 0x00c0; break;
+       case XFER_UDMA_3:       mode = 0x00b0; break;
+       case XFER_UDMA_2:       mode = 0x00a0; break;
+       case XFER_UDMA_1:       mode = 0x0090; break;
+       case XFER_UDMA_0:       mode = 0x0080; break;
+       case XFER_MW_DMA_2:     mode = 0x0070; break;
+       case XFER_MW_DMA_1:     mode = 0x0060; break;
+       case XFER_MW_DMA_0:     mode = 0x0050; break;
+       case XFER_PIO_4:        mode = 0x0400; break;
+       case XFER_PIO_3:        mode = 0x0300; break;
+       case XFER_PIO_2:        mode = 0x0200; break;
+       case XFER_PIO_1:        mode = 0x0100; break;
+       case XFER_PIO_0:
+       default:                mode = 0x0000; break;
        }
 
        scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f;
@@ -157,11 +157,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
        /* Store the system control register base for convenience... */
        hwif->config_data = sc_base;
 
-       hwif->set_pio_mode = &tc86c001_set_pio_mode;
-       hwif->set_dma_mode = &tc86c001_set_mode;
-
-       hwif->cable_detect = tc86c001_cable_detect;
-
        if (!hwif->dma_base)
                return;
 
@@ -173,8 +168,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
 
        /* Sector Count Register limit */
        hwif->rqsize     = 0xffff;
-
-       hwif->dma_start         = &tc86c001_dma_start;
 }
 
 static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev,
@@ -187,10 +180,29 @@ static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev,
        return err;
 }
 
+static const struct ide_port_ops tc86c001_port_ops = {
+       .set_pio_mode           = tc86c001_set_pio_mode,
+       .set_dma_mode           = tc86c001_set_mode,
+       .cable_detect           = tc86c001_cable_detect,
+};
+
+static const struct ide_dma_ops tc86c001_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = tc86c001_dma_start,
+       .dma_end                = __ide_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
 static const struct ide_port_info tc86c001_chipset __devinitdata = {
        .name           = "TC86C001",
        .init_chipset   = init_chipset_tc86c001,
        .init_hwif      = init_hwif_tc86c001,
+       .port_ops       = &tc86c001_port_ops,
+       .dma_ops        = &tc86c001_dma_ops,
        .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD |
                          IDE_HFLAG_ABUSE_SET_DMA_MODE,
        .pio_mask       = ATA_PIO4,
index a67d02a3f96e108484f42b71cbbbeec9dc97a6aa..db65a558d4eca62b26bff026d5c6fa3682d69555 100644 (file)
@@ -87,17 +87,15 @@ static void triflex_set_pio_mode(ide_drive_t *drive, const u8 pio)
        triflex_set_mode(drive, XFER_PIO_0 + pio);
 }
 
-static void __devinit init_hwif_triflex(ide_hwif_t *hwif)
-{
-       hwif->set_pio_mode = &triflex_set_pio_mode;
-       hwif->set_dma_mode = &triflex_set_mode;
-}
+static const struct ide_port_ops triflex_port_ops = {
+       .set_pio_mode           = triflex_set_pio_mode,
+       .set_dma_mode           = triflex_set_mode,
+};
 
 static const struct ide_port_info triflex_device __devinitdata = {
        .name           = "TRIFLEX",
-       .init_hwif      = init_hwif_triflex,
        .enablebits     = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
-       .host_flags     = IDE_HFLAG_BOOTABLE,
+       .port_ops       = &triflex_port_ops,
        .pio_mask       = ATA_PIO4,
        .swdma_mask     = ATA_SWDMA2,
        .mwdma_mask     = ATA_MWDMA2,
index de750f7a43e97f12725a7673c3557b6ab1ed38b8..a8a3138682eff4841ac9784a4cce9d46f3ba1a89 100644 (file)
@@ -214,7 +214,7 @@ static void trm290_dma_start(ide_drive_t *drive)
 {
 }
 
-static int trm290_ide_dma_end (ide_drive_t *drive)
+static int trm290_dma_end(ide_drive_t *drive)
 {
        u16 status;
 
@@ -225,7 +225,7 @@ static int trm290_ide_dma_end (ide_drive_t *drive)
        return status != 0x00ff;
 }
 
-static int trm290_ide_dma_test_irq (ide_drive_t *drive)
+static int trm290_dma_test_irq(ide_drive_t *drive)
 {
        u16 status;
 
@@ -254,22 +254,11 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
        hwif->config_data = cfg_base;
        hwif->dma_base = (cfg_base + 4) ^ (hwif->channel ? 0x80 : 0);
 
-       printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx",
+       printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx\n",
               hwif->name, hwif->dma_base, hwif->dma_base + 3);
 
-       if (!request_region(hwif->dma_base, 4, hwif->name)) {
-               printk(KERN_CONT " -- Error, ports in use.\n");
+       if (ide_allocate_dma_engine(hwif))
                return;
-       }
-
-       hwif->dmatable_cpu = pci_alloc_consistent(dev, PRD_ENTRIES * PRD_BYTES,
-                                                 &hwif->dmatable_dma);
-       if (!hwif->dmatable_cpu) {
-               printk(KERN_CONT " -- Error, unable to allocate DMA table.\n");
-               release_region(hwif->dma_base, 4);
-               return;
-       }
-       printk(KERN_CONT "\n");
 
        local_irq_save(flags);
        /* put config reg into first byte of hwif->select_data */
@@ -291,14 +280,6 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
                /* sharing IRQ with mate */
                hwif->irq = hwif->mate->irq;
 
-       hwif->dma_host_set      = &trm290_dma_host_set;
-       hwif->dma_setup         = &trm290_dma_setup;
-       hwif->dma_exec_cmd      = &trm290_dma_exec_cmd;
-       hwif->dma_start         = &trm290_dma_start;
-       hwif->ide_dma_end       = &trm290_ide_dma_end;
-       hwif->ide_dma_test_irq  = &trm290_ide_dma_test_irq;
-
-       hwif->selectproc = &trm290_selectproc;
 #if 1
        {
        /*
@@ -317,7 +298,7 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
                if (old != compat && old_mask == 0xff) {
                        /* leave lower 10 bits untouched */
                        compat += (next_offset += 0x400);
-                       hwif->io_ports[IDE_CONTROL_OFFSET] = compat + 2;
+                       hwif->io_ports.ctl_addr = compat + 2;
                        outw(compat | 1, hwif->config_data);
                        new = inw(hwif->config_data);
                        printk(KERN_INFO "%s: control basereg workaround: "
@@ -328,16 +309,32 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
 #endif
 }
 
+static const struct ide_port_ops trm290_port_ops = {
+       .selectproc             = trm290_selectproc,
+};
+
+static struct ide_dma_ops trm290_dma_ops = {
+       .dma_host_set           = trm290_dma_host_set,
+       .dma_setup              = trm290_dma_setup,
+       .dma_exec_cmd           = trm290_dma_exec_cmd,
+       .dma_start              = trm290_dma_start,
+       .dma_end                = trm290_dma_end,
+       .dma_test_irq           = trm290_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
 static const struct ide_port_info trm290_chipset __devinitdata = {
        .name           = "TRM290",
        .init_hwif      = init_hwif_trm290,
        .chipset        = ide_trm290,
+       .port_ops       = &trm290_port_ops,
+       .dma_ops        = &trm290_dma_ops,
        .host_flags     = IDE_HFLAG_NO_ATAPI_DMA |
 #if 0 /* play it safe for now */
                          IDE_HFLAG_TRUST_BIOS_FOR_DMA |
 #endif
                          IDE_HFLAG_NO_AUTODMA |
-                         IDE_HFLAG_BOOTABLE |
                          IDE_HFLAG_NO_LBA48,
 };
 
index 9004e7521889a3ea2e7ca7d34d8fbf325ef3d97f..566e0ecb8db1251afe46065a7a371cdcea2f13b7 100644 (file)
@@ -340,7 +340,7 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const
         * Determine system bus clock.
         */
 
-       via_clock = system_bus_clock() * 1000;
+       via_clock = (ide_pci_clk ? ide_pci_clk : system_bus_clock()) * 1000;
 
        switch (via_clock) {
                case 33000: via_clock = 33333; break;
@@ -415,25 +415,21 @@ static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif)
                return ATA_CBL_PATA40;
 }
 
-static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
-{
-       hwif->set_pio_mode = &via_set_pio_mode;
-       hwif->set_dma_mode = &via_set_drive;
-
-       hwif->cable_detect = via82cxxx_cable_detect;
-}
+static const struct ide_port_ops via_port_ops = {
+       .set_pio_mode           = via_set_pio_mode,
+       .set_dma_mode           = via_set_drive,
+       .cable_detect           = via82cxxx_cable_detect,
+};
 
 static const struct ide_port_info via82cxxx_chipset __devinitdata = {
        .name           = "VP_IDE",
        .init_chipset   = init_chipset_via82cxxx,
-       .init_hwif      = init_hwif_via82cxxx,
        .enablebits     = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
+       .port_ops       = &via_port_ops,
        .host_flags     = IDE_HFLAG_PIO_NO_BLACKLIST |
-                         IDE_HFLAG_PIO_NO_DOWNGRADE |
                          IDE_HFLAG_ABUSE_SET_DMA_MODE |
                          IDE_HFLAG_POST_SET_MODE |
-                         IDE_HFLAG_IO_32BIT |
-                         IDE_HFLAG_BOOTABLE,
+                         IDE_HFLAG_IO_32BIT,
        .pio_mask       = ATA_PIO5,
        .swdma_mask     = ATA_SWDMA2,
        .mwdma_mask     = ATA_MWDMA2,
index a784a97ca7ece6ed8452ead741155384790794c4..f0e638dcc3ab5e7dd737abc8799d79179e202dda 100644 (file)
@@ -36,6 +36,8 @@
 #include <asm/machdep.h>
 #include <asm/irq.h>
 
+#define DRV_NAME "ide-mpc8xx"
+
 static int identify  (volatile u8 *p);
 static void print_fixed (volatile u8 *p);
 static void print_funcid (int func);
@@ -127,9 +129,9 @@ static int pcmcia_schlvl = PCMCIA_SCHLVL;
  * MPC8xx's internal PCMCIA interface
  */
 #if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT)
-static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
+static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
 {
-       unsigned long *p = hw->io_ports;
+       unsigned long *p = hw->io_ports_array;
        int i;
 
        typedef struct {
@@ -182,6 +184,13 @@ static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
                        pcmcia_phy_base, pcmcia_phy_end,
                        pcmcia_phy_end - pcmcia_phy_base);
 
+               if (!request_mem_region(pcmcia_phy_base,
+                                       pcmcia_phy_end - pcmcia_phy_base,
+                                       DRV_NAME)) {
+                       printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
+                       return -EBUSY;
+               }
+
                pcmcia_base=(unsigned long)ioremap(pcmcia_phy_base,
                                                   pcmcia_phy_end-pcmcia_phy_base);
 
@@ -236,7 +245,7 @@ static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
        if (pcmp->pcmc_pipr & (M8XX_PCMCIA_CD1(_slot_)|M8XX_PCMCIA_CD2(_slot_))) {
                printk ("No card in slot %c: PIPR=%08x\n",
                        'A' + _slot_, (u32) pcmp->pcmc_pipr);
-               return;         /* No card in slot */
+               return -ENODEV;         /* No card in slot */
        }
 
        check_ide_device (pcmcia_base);
@@ -279,9 +288,6 @@ static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
        }
 #endif /* CONFIG_IDE_8xx_PCCARD */
 
-       ide_hwifs[data_port].pio_mask = ATA_PIO4;
-       ide_hwifs[data_port].set_pio_mode = m8xx_ide_set_pio_mode;
-
        /* Enable Harddisk Interrupt,
         * and make it edge sensitive
         */
@@ -296,6 +302,8 @@ static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
        /* Enable falling edge irq */
        pcmp->pcmc_per = 0x100000 >> (16 * _slot_);
 #endif /* CONFIG_IDE_8xx_PCCARD */
+
+       return 0;
 }
 #endif /* CONFIG_IDE_8xx_PCCARD || CONFIG_IDE_8xx_DIRECT */
 
@@ -304,9 +312,9 @@ static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
  * MPC8xx's internal PCMCIA interface
  */
 #if defined(CONFIG_IDE_EXT_DIRECT)
-static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
+static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
 {
-       unsigned long *p = hw->io_ports;
+       unsigned long *p = hw->io_ports_array;
        int i;
 
        u32 ide_phy_base;
@@ -327,7 +335,12 @@ static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
                printk ("IDE phys mem : %08x...%08x (size %08x)\n",
                        ide_phy_base, ide_phy_end,
                        ide_phy_end - ide_phy_base);
-               
+
+               if (!request_mem_region(ide_phy_base, 0x200, DRV_NAME)) {
+                       printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
+                       return -EBUSY;
+               }
+
                ide_base=(unsigned long)ioremap(ide_phy_base,
                                                ide_phy_end-ide_phy_base);
 
@@ -357,15 +370,14 @@ static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
        hw->irq = ioport_dsc[data_port].irq;
        hw->ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
 
-       ide_hwifs[data_port].pio_mask = ATA_PIO4;
-       ide_hwifs[data_port].set_pio_mode = m8xx_ide_set_pio_mode;
-
        /* Enable Harddisk Interrupt,
         * and make it edge sensitive
         */
        /* (11-18) Set edge detect for irq, no wakeup from low power mode */
        ((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |=
                        (0x80000000 >> ioport_dsc[data_port].irq);
+
+       return 0;
 }
 #endif /* CONFIG_IDE_8xx_DIRECT */
 
@@ -426,10 +438,14 @@ static void m8xx_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
 #elif defined(CONFIG_IDE_EXT_DIRECT)
 
        printk("%s[%d] %s: not implemented yet!\n",
-               __FILE__,__LINE__,__FUNCTION__);
+               __FILE__, __LINE__, __func__);
 #endif /* defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_PCMCIA */
 }
 
+static const struct ide_port_ops m8xx_port_ops = {
+       .set_pio_mode           = m8xx_ide_set_pio_mode,
+};
+
 static void
 ide_interrupt_ack (void *dev)
 {
@@ -794,14 +810,30 @@ static int __init mpc8xx_ide_probe(void)
 
 #ifdef IDE0_BASE_OFFSET
        memset(&hw, 0, sizeof(hw));
-       m8xx_ide_init_ports(&hw, 0);
-       ide_init_port_hw(&ide_hwifs[0], &hw);
-       idx[0] = 0;
+       if (!m8xx_ide_init_ports(&hw, 0)) {
+               ide_hwif_t *hwif = ide_find_port();
+
+               if (hwif) {
+                       ide_init_port_hw(hwif, &hw);
+                       hwif->pio_mask = ATA_PIO4;
+                       hwif->port_ops = &m8xx_port_ops;
+
+                       idx[0] = hwif->index;
+               }
+       }
 #ifdef IDE1_BASE_OFFSET
        memset(&hw, 0, sizeof(hw));
-       m8xx_ide_init_ports(&hw, 1);
-       ide_init_port_hw(&ide_hwifs[1], &hw);
-       idx[1] = 1;
+       if (!m8xx_ide_init_ports(&hw, 1)) {
+               ide_hwif_t *mate = ide_find_port();
+
+               if (mate) {
+                       ide_init_port_hw(mate, &hw);
+                       mate->pio_mask = ATA_PIO4;
+                       mate->port_ops = &m8xx_port_ops;
+
+                       idx[1] = mate->index;
+               }
+       }
 #endif
 #endif
 
index 88619b50d9ef9ada1a475b74cfe2de355130a239..3cac6b2790dd7cfc77110c541ccc699ae4c6430a 100644 (file)
@@ -79,8 +79,6 @@ typedef struct pmac_ide_hwif {
        
 } pmac_ide_hwif_t;
 
-static pmac_ide_hwif_t pmac_ide[MAX_HWIFS];
-
 enum {
        controller_ohare,       /* OHare based */
        controller_heathrow,    /* Heathrow/Paddington */
@@ -411,7 +409,7 @@ kauai_lookup_timing(struct kauai_timing* table, int cycle_time)
  */
 #define IDE_WAKEUP_DELAY       (1*HZ)
 
-static int pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif);
+static int pmac_ide_init_dma(ide_hwif_t *, const struct ide_port_info *);
 static int pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq);
 static void pmac_ide_selectproc(ide_drive_t *drive);
 static void pmac_ide_kauai_selectproc(ide_drive_t *drive);
@@ -419,7 +417,7 @@ static void pmac_ide_kauai_selectproc(ide_drive_t *drive);
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 
 #define PMAC_IDE_REG(x) \
-       ((void __iomem *)((drive)->hwif->io_ports[IDE_DATA_OFFSET] + (x)))
+       ((void __iomem *)((drive)->hwif->io_ports.data_addr + (x)))
 
 /*
  * Apply the timings of the proper unit (master/slave) to the shared
@@ -920,12 +918,29 @@ pmac_ide_do_resume(ide_hwif_t *hwif)
        return 0;
 }
 
+static const struct ide_port_ops pmac_ide_ata6_port_ops = {
+       .set_pio_mode           = pmac_ide_set_pio_mode,
+       .set_dma_mode           = pmac_ide_set_dma_mode,
+       .selectproc             = pmac_ide_kauai_selectproc,
+};
+
+static const struct ide_port_ops pmac_ide_port_ops = {
+       .set_pio_mode           = pmac_ide_set_pio_mode,
+       .set_dma_mode           = pmac_ide_set_dma_mode,
+       .selectproc             = pmac_ide_selectproc,
+};
+
+static const struct ide_dma_ops pmac_dma_ops;
+
 static const struct ide_port_info pmac_port_info = {
+       .init_dma               = pmac_ide_init_dma,
        .chipset                = ide_pmac,
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+       .dma_ops                = &pmac_dma_ops,
+#endif
+       .port_ops               = &pmac_ide_port_ops,
        .host_flags             = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
-                                 IDE_HFLAG_PIO_NO_DOWNGRADE |
                                  IDE_HFLAG_POST_SET_MODE |
-                                 IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
                                  IDE_HFLAG_UNMASK_IRQS,
        .pio_mask               = ATA_PIO4,
        .mwdma_mask             = ATA_MWDMA2,
@@ -950,12 +965,15 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
        pmif->broken_dma = pmif->broken_dma_warn = 0;
        if (of_device_is_compatible(np, "shasta-ata")) {
                pmif->kind = controller_sh_ata6;
+               d.port_ops = &pmac_ide_ata6_port_ops;
                d.udma_mask = ATA_UDMA6;
        } else if (of_device_is_compatible(np, "kauai-ata")) {
                pmif->kind = controller_un_ata6;
+               d.port_ops = &pmac_ide_ata6_port_ops;
                d.udma_mask = ATA_UDMA5;
        } else if (of_device_is_compatible(np, "K2-UATA")) {
                pmif->kind = controller_k2_ata6;
+               d.port_ops = &pmac_ide_ata6_port_ops;
                d.udma_mask = ATA_UDMA5;
        } else if (of_device_is_compatible(np, "keylargo-ata")) {
                if (strcmp(np->name, "ata-4") == 0) {
@@ -1032,37 +1050,29 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
        default_hwif_mmiops(hwif);
                hwif->OUTBSYNC = pmac_outbsync;
 
-       /* Tell common code _not_ to mess with resources */
-       hwif->mmio = 1;
        hwif->hwif_data = pmif;
        ide_init_port_hw(hwif, hw);
-       hwif->noprobe = pmif->mediabay;
        hwif->cbl = pmif->cable_80 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
-       hwif->set_pio_mode = pmac_ide_set_pio_mode;
-       if (pmif->kind == controller_un_ata6
-           || pmif->kind == controller_k2_ata6
-           || pmif->kind == controller_sh_ata6)
-               hwif->selectproc = pmac_ide_kauai_selectproc;
-       else
-               hwif->selectproc = pmac_ide_selectproc;
-       hwif->set_dma_mode = pmac_ide_set_dma_mode;
 
        printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n",
               hwif->index, model_name[pmif->kind], pmif->aapl_bus_id,
               pmif->mediabay ? " (mediabay)" : "", hwif->irq);
-                       
+
+       if (pmif->mediabay) {
 #ifdef CONFIG_PMAC_MEDIABAY
-       if (pmif->mediabay && check_media_bay_by_base(pmif->regbase, MB_CD) == 0)
-               hwif->noprobe = 0;
-#endif /* CONFIG_PMAC_MEDIABAY */
+               if (check_media_bay_by_base(pmif->regbase, MB_CD)) {
+#else
+               if (1) {
+#endif
+                       hwif->drives[0].noprobe = 1;
+                       hwif->drives[1].noprobe = 1;
+               }
+       }
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
        if (pmif->cable_80 == 0)
                d.udma_mask &= ATA_UDMA2;
-       /* has a DBDMA controller channel */
-       if (pmif->dma_regs == 0 || pmac_ide_setup_dma(pmif, hwif) < 0)
 #endif
-               d.udma_mask = d.mwdma_mask = 0;
 
        idx[0] = hwif->index;
 
@@ -1076,8 +1086,9 @@ static void __devinit pmac_ide_init_ports(hw_regs_t *hw, unsigned long base)
        int i;
 
        for (i = 0; i < 8; ++i)
-               hw->io_ports[i] = base + i * 0x10;
-       hw->io_ports[8] = base + 0x160;
+               hw->io_ports_array[i] = base + i * 0x10;
+
+       hw->io_ports.ctl_addr = base + 0x160;
 }
 
 /*
@@ -1088,35 +1099,36 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
 {
        void __iomem *base;
        unsigned long regbase;
-       int irq;
        ide_hwif_t *hwif;
        pmac_ide_hwif_t *pmif;
-       int i, rc;
+       int irq, rc;
        hw_regs_t hw;
 
-       i = 0;
-       while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0
-           || pmac_ide[i].node != NULL))
-               ++i;
-       if (i >= MAX_HWIFS) {
+       pmif = kzalloc(sizeof(*pmif), GFP_KERNEL);
+       if (pmif == NULL)
+               return -ENOMEM;
+
+       hwif = ide_find_port();
+       if (hwif == NULL) {
                printk(KERN_ERR "ide-pmac: MacIO interface attach with no slot\n");
                printk(KERN_ERR "          %s\n", mdev->ofdev.node->full_name);
-               return -ENODEV;
+               rc = -ENODEV;
+               goto out_free_pmif;
        }
 
-       pmif = &pmac_ide[i];
-       hwif = &ide_hwifs[i];
-
        if (macio_resource_count(mdev) == 0) {
-               printk(KERN_WARNING "ide%d: no address for %s\n",
-                      i, mdev->ofdev.node->full_name);
-               return -ENXIO;
+               printk(KERN_WARNING "ide-pmac: no address for %s\n",
+                                   mdev->ofdev.node->full_name);
+               rc = -ENXIO;
+               goto out_free_pmif;
        }
 
        /* Request memory resource for IO ports */
        if (macio_request_resource(mdev, 0, "ide-pmac (ports)")) {
-               printk(KERN_ERR "ide%d: can't request mmio resource !\n", i);
-               return -EBUSY;
+               printk(KERN_ERR "ide-pmac: can't request MMIO resource for "
+                               "%s!\n", mdev->ofdev.node->full_name);
+               rc = -EBUSY;
+               goto out_free_pmif;
        }
                        
        /* XXX This is bogus. Should be fixed in the registry by checking
@@ -1125,8 +1137,8 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
         * where that happens though...
         */
        if (macio_irq_count(mdev) == 0) {
-               printk(KERN_WARNING "ide%d: no intrs for device %s, using 13\n",
-                       i, mdev->ofdev.node->full_name);
+               printk(KERN_WARNING "ide-pmac: no intrs for device %s, using "
+                                   "13\n", mdev->ofdev.node->full_name);
                irq = irq_create_mapping(NULL, 13);
        } else
                irq = macio_irq(mdev, 0);
@@ -1144,7 +1156,9 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
        if (macio_resource_count(mdev) >= 2) {
                if (macio_request_resource(mdev, 1, "ide-pmac (dma)"))
-                       printk(KERN_WARNING "ide%d: can't request DMA resource !\n", i);
+                       printk(KERN_WARNING "ide-pmac: can't request DMA "
+                                           "resource for %s!\n",
+                                           mdev->ofdev.node->full_name);
                else
                        pmif->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x1000);
        } else
@@ -1166,11 +1180,15 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
                        iounmap(pmif->dma_regs);
                        macio_release_resource(mdev, 1);
                }
-               memset(pmif, 0, sizeof(*pmif));
                macio_release_resource(mdev, 0);
+               kfree(pmif);
        }
 
        return rc;
+
+out_free_pmif:
+       kfree(pmif);
+       return rc;
 }
 
 static int
@@ -1215,7 +1233,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
        pmac_ide_hwif_t *pmif;
        void __iomem *base;
        unsigned long rbase, rlen;
-       int i, rc;
+       int rc;
        hw_regs_t hw;
 
        np = pci_device_to_OF_node(pdev);
@@ -1223,30 +1241,32 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
                printk(KERN_ERR "ide-pmac: cannot find MacIO node for Kauai ATA interface\n");
                return -ENODEV;
        }
-       i = 0;
-       while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0
-           || pmac_ide[i].node != NULL))
-               ++i;
-       if (i >= MAX_HWIFS) {
+
+       pmif = kzalloc(sizeof(*pmif), GFP_KERNEL);
+       if (pmif == NULL)
+               return -ENOMEM;
+
+       hwif = ide_find_port();
+       if (hwif == NULL) {
                printk(KERN_ERR "ide-pmac: PCI interface attach with no slot\n");
                printk(KERN_ERR "          %s\n", np->full_name);
-               return -ENODEV;
+               rc = -ENODEV;
+               goto out_free_pmif;
        }
 
-       pmif = &pmac_ide[i];
-       hwif = &ide_hwifs[i];
-
        if (pci_enable_device(pdev)) {
-               printk(KERN_WARNING "ide%i: Can't enable PCI device for %s\n",
-                       i, np->full_name);
-               return -ENXIO;
+               printk(KERN_WARNING "ide-pmac: Can't enable PCI device for "
+                                   "%s\n", np->full_name);
+               rc = -ENXIO;
+               goto out_free_pmif;
        }
        pci_set_master(pdev);
                        
        if (pci_request_regions(pdev, "Kauai ATA")) {
-               printk(KERN_ERR "ide%d: Cannot obtain PCI resources for %s\n",
-                       i, np->full_name);
-               return -ENXIO;
+               printk(KERN_ERR "ide-pmac: Cannot obtain PCI resources for "
+                               "%s\n", np->full_name);
+               rc = -ENXIO;
+               goto out_free_pmif;
        }
 
        hwif->dev = &pdev->dev;
@@ -1276,11 +1296,15 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
                /* The inteface is released to the common IDE layer */
                pci_set_drvdata(pdev, NULL);
                iounmap(base);
-               memset(pmif, 0, sizeof(*pmif));
                pci_release_regions(pdev);
+               kfree(pmif);
        }
 
        return rc;
+
+out_free_pmif:
+       kfree(pmif);
+       return rc;
 }
 
 static int
@@ -1652,18 +1676,31 @@ pmac_ide_dma_lost_irq (ide_drive_t *drive)
        printk(KERN_ERR "ide-pmac lost interrupt, dma status: %lx\n", status);
 }
 
+static const struct ide_dma_ops pmac_dma_ops = {
+       .dma_host_set           = pmac_ide_dma_host_set,
+       .dma_setup              = pmac_ide_dma_setup,
+       .dma_exec_cmd           = pmac_ide_dma_exec_cmd,
+       .dma_start              = pmac_ide_dma_start,
+       .dma_end                = pmac_ide_dma_end,
+       .dma_test_irq           = pmac_ide_dma_test_irq,
+       .dma_timeout            = ide_dma_timeout,
+       .dma_lost_irq           = pmac_ide_dma_lost_irq,
+};
+
 /*
  * Allocate the data structures needed for using DMA with an interface
  * and fill the proper list of functions pointers
  */
-static int __devinit pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
+static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif,
+                                      const struct ide_port_info *d)
 {
+       pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
        struct pci_dev *dev = to_pci_dev(hwif->dev);
 
        /* We won't need pci_dev if we switch to generic consistent
         * DMA routines ...
         */
-       if (dev == NULL)
+       if (dev == NULL || pmif->dma_regs == 0)
                return -ENODEV;
        /*
         * Allocate space for the DBDMA commands.
@@ -1682,18 +1719,14 @@ static int __devinit pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
 
        hwif->sg_max_nents = MAX_DCMDS;
 
-       hwif->dma_host_set = &pmac_ide_dma_host_set;
-       hwif->dma_setup = &pmac_ide_dma_setup;
-       hwif->dma_exec_cmd = &pmac_ide_dma_exec_cmd;
-       hwif->dma_start = &pmac_ide_dma_start;
-       hwif->ide_dma_end = &pmac_ide_dma_end;
-       hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq;
-       hwif->dma_timeout = &ide_dma_timeout;
-       hwif->dma_lost_irq = &pmac_ide_dma_lost_irq;
-
        return 0;
 }
-
+#else
+static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif,
+                                      const struct ide_port_info *d)
+{
+       return -EOPNOTSUPP;
+}
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 
 module_init(pmac_ide_probe);
index f7ede0e42881f5ae56d63780fdbd8d635548a355..5171601fb2556646544587466a14b8e973389a15 100644 (file)
 #include <asm/io.h>
 #include <asm/irq.h>
 
-
-/**
- *     ide_match_hwif  -       match a PCI IDE against an ide_hwif
- *     @io_base: I/O base of device
- *     @bootable: set if its bootable
- *     @name: name of device
- *
- *     Match a PCI IDE port against an entry in ide_hwifs[],
- *     based on io_base port if possible. Return the matching hwif,
- *     or a new hwif. If we find an error (clashing, out of devices, etc)
- *     return NULL
- *
- *     FIXME: we need to handle mmio matches here too
- */
-
-static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char *name)
-{
-       int h;
-       ide_hwif_t *hwif;
-
-       /*
-        * Look for a hwif with matching io_base default value.
-        * If chipset is "ide_unknown", then claim that hwif slot.
-        * Otherwise, some other chipset has already claimed it..  :(
-        */
-       for (h = 0; h < MAX_HWIFS; ++h) {
-               hwif = &ide_hwifs[h];
-               if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) {
-                       if (hwif->chipset == ide_unknown)
-                               return hwif; /* match */
-                       printk(KERN_ERR "%s: port 0x%04lx already claimed by %s\n",
-                               name, io_base, hwif->name);
-                       return NULL;    /* already claimed */
-               }
-       }
-       /*
-        * Okay, there is no hwif matching our io_base,
-        * so we'll just claim an unassigned slot.
-        * Give preference to claiming other slots before claiming ide0/ide1,
-        * just in case there's another interface yet-to-be-scanned
-        * which uses ports 1f0/170 (the ide0/ide1 defaults).
-        *
-        * Unless there is a bootable card that does not use the standard
-        * ports 1f0/170 (the ide0/ide1 defaults). The (bootable) flag.
-        */
-       if (bootable) {
-               for (h = 0; h < MAX_HWIFS; ++h) {
-                       hwif = &ide_hwifs[h];
-                       if (hwif->chipset == ide_unknown)
-                               return hwif;    /* pick an unused entry */
-               }
-       } else {
-               for (h = 2; h < MAX_HWIFS; ++h) {
-                       hwif = ide_hwifs + h;
-                       if (hwif->chipset == ide_unknown)
-                               return hwif;    /* pick an unused entry */
-               }
-       }
-       for (h = 0; h < 2 && h < MAX_HWIFS; ++h) {
-               hwif = ide_hwifs + h;
-               if (hwif->chipset == ide_unknown)
-                       return hwif;    /* pick an unused entry */
-       }
-       printk(KERN_ERR "%s: too many IDE interfaces, no room in table\n", name);
-       return NULL;
-}
-
 /**
  *     ide_setup_pci_baseregs  -       place a PCI IDE controller native
  *     @dev: PCI device of interface to switch native
@@ -94,13 +27,13 @@ static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char
  *
  *     We attempt to place the PCI interface into PCI native mode. If
  *     we succeed the BARs are ok and the controller is in PCI mode.
- *     Returns 0 on success or an errno code. 
+ *     Returns 0 on success or an errno code.
  *
  *     FIXME: if we program the interface and then fail to set the BARS
  *     we don't switch it back to legacy mode. Do we actually care ??
  */
-static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)
+
+static int ide_setup_pci_baseregs(struct pci_dev *dev, const char *name)
 {
        u8 progif = 0;
 
@@ -139,16 +72,16 @@ static void ide_pci_clear_simplex(unsigned long dma_base, const char *name)
 }
 
 /**
- *     ide_get_or_set_dma_base         -       setup BMIBA
- *     @d: IDE port info
+ *     ide_pci_dma_base        -       setup BMIBA
  *     @hwif: IDE interface
+ *     @d: IDE port info
  *
  *     Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space.
  *     Where a device has a partner that is already in DMA mode we check
  *     and enforce IDE simplex rules.
  */
 
-static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_hwif_t *hwif)
+unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
        unsigned long dma_base = 0;
@@ -199,6 +132,31 @@ static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_
 out:
        return dma_base;
 }
+EXPORT_SYMBOL_GPL(ide_pci_dma_base);
+
+/*
+ * Set up BM-DMA capability (PnP BIOS should have done this)
+ */
+int ide_pci_set_master(struct pci_dev *dev, const char *name)
+{
+       u16 pcicmd;
+
+       pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
+
+       if ((pcicmd & PCI_COMMAND_MASTER) == 0) {
+               pci_set_master(dev);
+
+               if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) ||
+                   (pcicmd & PCI_COMMAND_MASTER) == 0) {
+                       printk(KERN_ERR "%s: error updating PCICMD on %s\n",
+                                       name, pci_name(dev));
+                       return -EIO;
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ide_pci_set_master);
 #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
 
 void ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d)
@@ -207,7 +165,6 @@ void ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d)
                         " PCI slot %s\n", d->name, dev->vendor, dev->device,
                         dev->revision, pci_name(dev));
 }
-
 EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
 
 
@@ -220,13 +177,13 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
  *     but if that fails then we only need IO space. The PCI code should
  *     have setup the proper resources for us already for controllers in
  *     legacy mode.
- *     
+ *
  *     Returns zero on success or an error code
  */
 
 static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
 {
-       int ret;
+       int ret, bars;
 
        if (pci_enable_device(dev)) {
                ret = pci_enable_device_io(dev);
@@ -249,13 +206,21 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
                goto out;
        }
 
-       /* FIXME: Temporary - until we put in the hotplug interface logic
-          Check that the bits we want are not in use by someone else. */
-       ret = pci_request_region(dev, 4, "ide_tmp");
-       if (ret < 0)
-               goto out;
+       if (d->host_flags & IDE_HFLAG_SINGLE)
+               bars = (1 << 2) - 1;
+       else
+               bars = (1 << 4) - 1;
+
+       if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) {
+               if (d->host_flags & IDE_HFLAG_CS5520)
+                       bars |= (1 << 2);
+               else
+                       bars |= (1 << 4);
+       }
 
-       pci_release_region(dev, 4);
+       ret = pci_request_selected_regions(dev, bars, d->name);
+       if (ret < 0)
+               printk(KERN_ERR "%s: can't reserve resources\n", d->name);
 out:
        return ret;
 }
@@ -279,8 +244,8 @@ static int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d)
         * Maybe the user deliberately *disabled* the device,
         * but we'll eventually ignore it again if no drives respond.
         */
-       if (ide_setup_pci_baseregs(dev, d->name) || pci_write_config_word(dev, PCI_COMMAND, pcicmd|PCI_COMMAND_IO)) 
-       {
+       if (ide_setup_pci_baseregs(dev, d->name) ||
+           pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) {
                printk(KERN_INFO "%s: device disabled (BIOS)\n", d->name);
                return -ENODEV;
        }
@@ -301,26 +266,24 @@ static int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d)
  *     @d: IDE port info
  *     @bar: BAR number
  *
- *     Checks if a BAR is configured and points to MMIO space. If so
- *     print an error and return an error code. Otherwise return 0
+ *     Checks if a BAR is configured and points to MMIO space. If so,
+ *     return an error code. Otherwise return 0
  */
 
-static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *d, int bar)
+static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *d,
+                              int bar)
 {
        ulong flags = pci_resource_flags(dev, bar);
-       
+
        /* Unconfigured ? */
        if (!flags || pci_resource_len(dev, bar) == 0)
                return 0;
 
-       /* I/O space */         
-       if(flags & PCI_BASE_ADDRESS_IO_MASK)
+       /* I/O space */
+       if (flags & IORESOURCE_IO)
                return 0;
-               
+
        /* Bad */
-       printk(KERN_ERR "%s: IO baseregs (BIOS) are reported "
-                       "as MEM, report to "
-                       "<andre@linux-ide.org>.\n", d->name);
        return -EINVAL;
 }
 
@@ -344,14 +307,16 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
 {
        unsigned long ctl = 0, base = 0;
        ide_hwif_t *hwif;
-       u8 bootable = (d->host_flags & IDE_HFLAG_BOOTABLE) ? 1 : 0;
        struct hw_regs_s hw;
 
        if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) {
-               /*  Possibly we should fail if these checks report true */
-               ide_pci_check_iomem(dev, d, 2*port);
-               ide_pci_check_iomem(dev, d, 2*port+1);
+               if (ide_pci_check_iomem(dev, d, 2 * port) ||
+                   ide_pci_check_iomem(dev, d, 2 * port + 1)) {
+                       printk(KERN_ERR "%s: I/O baseregs (BIOS) are reported "
+                                       "as MEM for port %d!\n", d->name, port);
+                       return NULL;
+               }
+
                ctl  = pci_resource_start(dev, 2*port+1);
                base = pci_resource_start(dev, 2*port);
                if ((ctl && !base) || (base && !ctl)) {
@@ -360,14 +325,18 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
                        return NULL;
                }
        }
-       if (!ctl)
-       {
+       if (!ctl) {
                /* Use default values */
                ctl = port ? 0x374 : 0x3f4;
                base = port ? 0x170 : 0x1f0;
        }
-       if ((hwif = ide_match_hwif(base, bootable, d->name)) == NULL)
-               return NULL;    /* no room in ide_hwifs[] */
+
+       hwif = ide_find_port_slot(d);
+       if (hwif == NULL) {
+               printk(KERN_ERR "%s: too many IDE interfaces, no room in "
+                               "table\n", d->name);
+               return NULL;
+       }
 
        memset(&hw, 0, sizeof(hw));
        hw.irq = irq;
@@ -378,7 +347,6 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
        ide_init_port_hw(hwif, &hw);
 
        hwif->dev = &dev->dev;
-       hwif->cds = d;
 
        return hwif;
 }
@@ -394,40 +362,33 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
  *     state
  */
 
-void ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
+int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
-       u16 pcicmd;
-
-       pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
 
        if ((d->host_flags & IDE_HFLAG_NO_AUTODMA) == 0 ||
            ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
             (dev->class & 0x80))) {
-               unsigned long dma_base = ide_get_or_set_dma_base(d, hwif);
-               if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
-                       /*
-                        * Set up BM-DMA capability
-                        * (PnP BIOS should have done this)
-                        */
-                       pci_set_master(dev);
-                       if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) {
-                               printk(KERN_ERR "%s: %s error updating PCICMD\n",
-                                       hwif->name, d->name);
-                               dma_base = 0;
-                       }
-               }
-               if (dma_base) {
-                       if (d->init_dma) {
-                               d->init_dma(hwif, dma_base);
-                       } else {
-                               ide_setup_dma(hwif, dma_base);
-                       }
-               } else {
-                       printk(KERN_INFO "%s: %s Bus-Master DMA disabled "
-                               "(BIOS)\n", hwif->name, d->name);
-               }
+               unsigned long base = ide_pci_dma_base(hwif, d);
+
+               if (base == 0 || ide_pci_set_master(dev, d->name) < 0)
+                       return -1;
+
+               if (hwif->mmio)
+                       printk(KERN_INFO "    %s: MMIO-DMA\n", hwif->name);
+               else
+                       printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx\n",
+                                        hwif->name, base, base + 7);
+
+               hwif->extra_base = base + (hwif->channel ? 8 : 16);
+
+               if (ide_allocate_dma_engine(hwif))
+                       return -1;
+
+               ide_setup_dma(hwif, base);
        }
+
+       return 0;
 }
 #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
 
@@ -514,7 +475,6 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int
                *(idx + port) = hwif->index;
        }
 }
-
 EXPORT_SYMBOL_GPL(ide_pci_setup_ports);
 
 /*
@@ -597,7 +557,6 @@ int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d)
 
        return ret;
 }
-
 EXPORT_SYMBOL_GPL(ide_setup_pci_device);
 
 int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
@@ -621,5 +580,4 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
 out:
        return ret;
 }
-
 EXPORT_SYMBOL_GPL(ide_setup_pci_devices);
index 6228fadacd388d7ffd014548796dec4263cfe454..9d19aec5820a303145d8b286e2d1ce2e72b4a586 100644 (file)
@@ -2167,6 +2167,7 @@ static const struct file_operations dv1394_fops=
 /*
  * Export information about protocols/devices supported by this driver.
  */
+#ifdef MODULE
 static struct ieee1394_device_id dv1394_id_table[] = {
        {
                .match_flags    = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
@@ -2177,6 +2178,7 @@ static struct ieee1394_device_id dv1394_id_table[] = {
 };
 
 MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table);
+#endif /* MODULE */
 
 static struct hpsb_protocol_driver dv1394_driver = {
        .name = "dv1394",
index b94e55e6eaa59034c9c5825fc656f2de3a7fe54e..b5de5f21ef78a57e45032500867fdb24538de00e 100644 (file)
@@ -123,6 +123,8 @@ struct hpsb_iso {
 
        /* how many times the buffer has overflowed or underflowed */
        atomic_t overflows;
+       /* how many cycles were skipped for a given context */
+       atomic_t skips;
 
        /* Current number of bytes lost in discarded packets */
        int bytes_discarded;
index 0690469fcecf9acfdb53ce4140c5ba4e5c99dd9a..e509e13cb7a7cdb4c2d154835dea19857082f418 100644 (file)
@@ -1723,6 +1723,8 @@ struct ohci_iso_xmit {
        struct dma_prog_region prog;
        struct ohci1394_iso_tasklet task;
        int task_active;
+       int last_cycle;
+       atomic_t skips;
 
        u32 ContextControlSet;
        u32 ContextControlClear;
@@ -1759,6 +1761,8 @@ static int ohci_iso_xmit_init(struct hpsb_iso *iso)
        iso->hostdata = xmit;
        xmit->ohci = iso->host->hostdata;
        xmit->task_active = 0;
+       xmit->last_cycle = -1;
+       atomic_set(&iso->skips, 0);
 
        dma_prog_region_init(&xmit->prog);
 
@@ -1856,6 +1860,26 @@ static void ohci_iso_xmit_task(unsigned long data)
                /* parse cycle */
                cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF;
 
+               if (xmit->last_cycle > -1) {
+                       int cycle_diff = cycle - xmit->last_cycle;
+                       int skip;
+
+                       /* unwrap */
+                       if (cycle_diff < 0) {
+                               cycle_diff += 8000;
+                               if (cycle_diff < 0)
+                                       PRINT(KERN_ERR, "bogus cycle diff %d\n",
+                                             cycle_diff);
+                       }
+
+                       skip = cycle_diff - 1;
+                       if (skip > 0) {
+                               DBGMSG("skipped %d cycles without packet loss", skip);
+                               atomic_add(skip, &iso->skips);
+                       }
+               }
+               xmit->last_cycle = cycle;
+
                /* tell the subsystem the packet has gone out */
                hpsb_iso_packet_sent(iso, cycle, event != 0x11);
 
@@ -1943,6 +1967,16 @@ static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info
        prev->output_last.branchAddress = cpu_to_le32(
                dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3);
 
+       /*
+        * Link the skip address to this descriptor itself. This causes a
+        * context to skip a cycle whenever lost cycles or FIFO overruns occur,
+        * without dropping the data at that point the application should then
+        * decide whether this is an error condition or not. Some protocols
+        * can deal with this by dropping some rate-matching padding packets.
+        */
+       next->output_more_immediate.branchAddress =
+                       prev->output_last.branchAddress;
+
        /* disable interrupt, unless required by the IRQ interval */
        if (prev_i % iso->irq_interval) {
                prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */
index 04e96ba56e090af3cd4ff6ab44e5b1fb147d2fd1..ec2a0adbedb248f2a493b2ca716fc8d7971c98ed 100644 (file)
@@ -2356,13 +2356,16 @@ static void rawiso_activity_cb(struct hpsb_iso *iso)
 static void raw1394_iso_fill_status(struct hpsb_iso *iso,
                                    struct raw1394_iso_status *stat)
 {
+       int overflows = atomic_read(&iso->overflows);
+       int skips = atomic_read(&iso->skips);
+
        stat->config.data_buf_size = iso->buf_size;
        stat->config.buf_packets = iso->buf_packets;
        stat->config.channel = iso->channel;
        stat->config.speed = iso->speed;
        stat->config.irq_interval = iso->irq_interval;
        stat->n_packets = hpsb_iso_n_ready(iso);
-       stat->overflows = atomic_read(&iso->overflows);
+       stat->overflows = ((skips & 0xFFFF) << 16) | ((overflows & 0xFFFF));
        stat->xmit_cycle = iso->xmit_cycle;
 }
 
@@ -2437,6 +2440,8 @@ static int raw1394_iso_get_status(struct file_info *fi, void __user * uaddr)
 
        /* reset overflow counter */
        atomic_set(&iso->overflows, 0);
+       /* reset skip counter */
+       atomic_set(&iso->skips, 0);
 
        return 0;
 }
@@ -2935,6 +2940,7 @@ static int raw1394_release(struct inode *inode, struct file *file)
 /*
  * Export information about protocols/devices supported by this driver.
  */
+#ifdef MODULE
 static struct ieee1394_device_id raw1394_id_table[] = {
        {
         .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
@@ -2956,6 +2962,7 @@ static struct ieee1394_device_id raw1394_id_table[] = {
 };
 
 MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table);
+#endif /* MODULE */
 
 static struct hpsb_protocol_driver raw1394_driver = {
        .name = "raw1394",
index e03024eeeac135fac1da8b5422b7b84e3a4d16d3..e24772d336e1ae6c726d8e0a05ae5ea25a9207e0 100644 (file)
@@ -1293,6 +1293,7 @@ static const struct file_operations video1394_fops=
 /*
  * Export information about protocols/devices supported by this driver.
  */
+#ifdef MODULE
 static struct ieee1394_device_id video1394_id_table[] = {
        {
                .match_flags    = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
@@ -1313,6 +1314,7 @@ static struct ieee1394_device_id video1394_id_table[] = {
 };
 
 MODULE_DEVICE_TABLE(ieee1394, video1394_id_table);
+#endif /* MODULE */
 
 static struct hpsb_protocol_driver video1394_driver = {
        .name = VIDEO1394_DRIVER_NAME,
index 0d13fe0a260b182678134ac29acef7ac90bf4648..3d6d9461c31da089eb2aee091a9286e4d994e6e9 100644 (file)
@@ -160,6 +160,7 @@ struct ehca_qp {
        };
        u32 qp_type;
        enum ehca_ext_qp_type ext_type;
+       enum ib_qp_state state;
        struct ipz_queue ipz_squeue;
        struct ipz_queue ipz_rqueue;
        struct h_galpas galpas;
index b5ca94c6b8d91a603aebff7f907c42f3234bb31e..ca5eb0cb628cf74cb4df726667cd2f378199448c 100644 (file)
@@ -633,7 +633,7 @@ static inline int find_next_online_cpu(struct ehca_comp_pool *pool)
        unsigned long flags;
 
        WARN_ON_ONCE(!in_interrupt());
-       if (ehca_debug_level)
+       if (ehca_debug_level >= 3)
                ehca_dmp(&cpu_online_map, sizeof(cpumask_t), "");
 
        spin_lock_irqsave(&pool->last_cpu_lock, flags);
index 65b3362cdb9b5a82321ce56ebaf71d3ce6b3ca4c..65048976198c5ed63863de8b21b04f576783f744 100644 (file)
@@ -50,7 +50,7 @@
 #include "ehca_tools.h"
 #include "hcp_if.h"
 
-#define HCAD_VERSION "0025"
+#define HCAD_VERSION "0026"
 
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
@@ -60,7 +60,6 @@ MODULE_VERSION(HCAD_VERSION);
 static int ehca_open_aqp1     = 0;
 static int ehca_hw_level      = 0;
 static int ehca_poll_all_eqs  = 1;
-static int ehca_mr_largepage  = 1;
 
 int ehca_debug_level   = 0;
 int ehca_nr_ports      = 2;
@@ -70,45 +69,40 @@ int ehca_static_rate   = -1;
 int ehca_scaling_code  = 0;
 int ehca_lock_hcalls   = -1;
 
-module_param_named(open_aqp1,     ehca_open_aqp1,     int, S_IRUGO);
-module_param_named(debug_level,   ehca_debug_level,   int, S_IRUGO);
-module_param_named(hw_level,      ehca_hw_level,      int, S_IRUGO);
-module_param_named(nr_ports,      ehca_nr_ports,      int, S_IRUGO);
-module_param_named(use_hp_mr,     ehca_use_hp_mr,     int, S_IRUGO);
-module_param_named(port_act_time, ehca_port_act_time, int, S_IRUGO);
-module_param_named(poll_all_eqs,  ehca_poll_all_eqs,  int, S_IRUGO);
-module_param_named(static_rate,   ehca_static_rate,   int, S_IRUGO);
-module_param_named(scaling_code,  ehca_scaling_code,  int, S_IRUGO);
-module_param_named(mr_largepage,  ehca_mr_largepage,  int, S_IRUGO);
+module_param_named(open_aqp1,     ehca_open_aqp1,     bool, S_IRUGO);
+module_param_named(debug_level,   ehca_debug_level,   int,  S_IRUGO);
+module_param_named(hw_level,      ehca_hw_level,      int,  S_IRUGO);
+module_param_named(nr_ports,      ehca_nr_ports,      int,  S_IRUGO);
+module_param_named(use_hp_mr,     ehca_use_hp_mr,     bool, S_IRUGO);
+module_param_named(port_act_time, ehca_port_act_time, int,  S_IRUGO);
+module_param_named(poll_all_eqs,  ehca_poll_all_eqs,  bool, S_IRUGO);
+module_param_named(static_rate,   ehca_static_rate,   int,  S_IRUGO);
+module_param_named(scaling_code,  ehca_scaling_code,  bool, S_IRUGO);
 module_param_named(lock_hcalls,   ehca_lock_hcalls,   bool, S_IRUGO);
 
 MODULE_PARM_DESC(open_aqp1,
-                "AQP1 on startup (0: no (default), 1: yes)");
+                "Open AQP1 on startup (default: no)");
 MODULE_PARM_DESC(debug_level,
-                "debug level"
-                " (0: no debug traces (default), 1: with debug traces)");
+                "Amount of debug output (0: none (default), 1: traces, "
+                "2: some dumps, 3: lots)");
 MODULE_PARM_DESC(hw_level,
-                "hardware level"
-                " (0: autosensing (default), 1: v. 0.20, 2: v. 0.21)");
+                "Hardware level (0: autosensing (default), "
+                "0x10..0x14: eHCA, 0x20..0x23: eHCA2)");
 MODULE_PARM_DESC(nr_ports,
                 "number of connected ports (-1: autodetect, 1: port one only, "
                 "2: two ports (default)");
 MODULE_PARM_DESC(use_hp_mr,
-                "high performance MRs (0: no (default), 1: yes)");
+                "Use high performance MRs (default: no)");
 MODULE_PARM_DESC(port_act_time,
-                "time to wait for port activation (default: 30 sec)");
+                "Time to wait for port activation (default: 30 sec)");
 MODULE_PARM_DESC(poll_all_eqs,
-                "polls all event queues periodically"
-                " (0: no, 1: yes (default))");
+                "Poll all event queues periodically (default: yes)");
 MODULE_PARM_DESC(static_rate,
-                "set permanent static rate (default: disabled)");
+                "Set permanent static rate (default: no static rate)");
 MODULE_PARM_DESC(scaling_code,
-                "set scaling code (0: disabled/default, 1: enabled)");
-MODULE_PARM_DESC(mr_largepage,
-                "use large page for MR (0: use PAGE_SIZE (default), "
-                "1: use large page depending on MR size");
+                "Enable scaling code (default: no)");
 MODULE_PARM_DESC(lock_hcalls,
-                "serialize all hCalls made by the driver "
+                "Serialize all hCalls made by the driver "
                 "(default: autodetect)");
 
 DEFINE_RWLOCK(ehca_qp_idr_lock);
@@ -275,6 +269,7 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
        u64 h_ret;
        struct hipz_query_hca *rblock;
        struct hipz_query_port *port;
+       const char *loc_code;
 
        static const u32 pgsize_map[] = {
                HCA_CAP_MR_PGSIZE_4K,  0x1000,
@@ -283,6 +278,12 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
                HCA_CAP_MR_PGSIZE_16M, 0x1000000,
        };
 
+       ehca_gen_dbg("Probing adapter %s...",
+                    shca->ofdev->node->full_name);
+       loc_code = of_get_property(shca->ofdev->node, "ibm,loc-code", NULL);
+       if (loc_code)
+               ehca_gen_dbg(" ... location lode=%s", loc_code);
+
        rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
        if (!rblock) {
                ehca_gen_err("Cannot allocate rblock memory.");
@@ -350,11 +351,9 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
 
        /* translate supported MR page sizes; always support 4K */
        shca->hca_cap_mr_pgsize = EHCA_PAGESIZE;
-       if (ehca_mr_largepage) { /* support extra sizes only if enabled */
-               for (i = 0; i < ARRAY_SIZE(pgsize_map); i += 2)
-                       if (rblock->memory_page_size_supported & pgsize_map[i])
-                               shca->hca_cap_mr_pgsize |= pgsize_map[i + 1];
-       }
+       for (i = 0; i < ARRAY_SIZE(pgsize_map); i += 2)
+               if (rblock->memory_page_size_supported & pgsize_map[i])
+                       shca->hca_cap_mr_pgsize |= pgsize_map[i + 1];
 
        /* query max MTU from first port -- it's the same for all ports */
        port = (struct hipz_query_port *)rblock;
@@ -567,8 +566,7 @@ static int ehca_destroy_aqp1(struct ehca_sport *sport)
 
 static ssize_t ehca_show_debug_level(struct device_driver *ddp, char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-                       ehca_debug_level);
+       return snprintf(buf, PAGE_SIZE, "%d\n", ehca_debug_level);
 }
 
 static ssize_t ehca_store_debug_level(struct device_driver *ddp,
@@ -657,14 +655,6 @@ static ssize_t ehca_show_adapter_handle(struct device *dev,
 }
 static DEVICE_ATTR(adapter_handle, S_IRUGO, ehca_show_adapter_handle, NULL);
 
-static ssize_t ehca_show_mr_largepage(struct device *dev,
-                                     struct device_attribute *attr,
-                                     char *buf)
-{
-       return sprintf(buf, "%d\n", ehca_mr_largepage);
-}
-static DEVICE_ATTR(mr_largepage, S_IRUGO, ehca_show_mr_largepage, NULL);
-
 static struct attribute *ehca_dev_attrs[] = {
        &dev_attr_adapter_handle.attr,
        &dev_attr_num_ports.attr,
@@ -681,7 +671,6 @@ static struct attribute *ehca_dev_attrs[] = {
        &dev_attr_cur_mw.attr,
        &dev_attr_max_pd.attr,
        &dev_attr_max_ah.attr,
-       &dev_attr_mr_largepage.attr,
        NULL
 };
 
index f26997fc00f88b810761aa6c742b254468694e4b..46ae4eb2c4e1e096a4bce1bbef180474d64ec335 100644 (file)
@@ -1794,8 +1794,9 @@ static int ehca_check_kpages_per_ate(struct scatterlist *page_list,
        int t;
        for (t = start_idx; t <= end_idx; t++) {
                u64 pgaddr = page_to_pfn(sg_page(&page_list[t])) << PAGE_SHIFT;
-               ehca_gen_dbg("chunk_page=%lx value=%016lx", pgaddr,
-                            *(u64 *)abs_to_virt(phys_to_abs(pgaddr)));
+               if (ehca_debug_level >= 3)
+                       ehca_gen_dbg("chunk_page=%lx value=%016lx", pgaddr,
+                                    *(u64 *)abs_to_virt(phys_to_abs(pgaddr)));
                if (pgaddr - PAGE_SIZE != *prev_pgaddr) {
                        ehca_gen_err("uncontiguous page found pgaddr=%lx "
                                     "prev_pgaddr=%lx page_list_i=%x",
@@ -1862,10 +1863,13 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
                                                pgaddr &
                                                ~(pginfo->hwpage_size - 1));
                                }
-                               ehca_gen_dbg("kpage=%lx chunk_page=%lx "
-                                            "value=%016lx", *kpage, pgaddr,
-                                            *(u64 *)abs_to_virt(
-                                                    phys_to_abs(pgaddr)));
+                               if (ehca_debug_level >= 3) {
+                                       u64 val = *(u64 *)abs_to_virt(
+                                               phys_to_abs(pgaddr));
+                                       ehca_gen_dbg("kpage=%lx chunk_page=%lx "
+                                                    "value=%016lx",
+                                                    *kpage, pgaddr, val);
+                               }
                                prev_pgaddr = pgaddr;
                                i++;
                                pginfo->kpage_cnt++;
index 3eb14a52cbf2bc4ebb5a2a46c129861a05ebdb28..57bef1152cc2d3bc7459836c61a4b8a24baed2de 100644 (file)
@@ -550,6 +550,7 @@ static struct ehca_qp *internal_create_qp(
        spin_lock_init(&my_qp->spinlock_r);
        my_qp->qp_type = qp_type;
        my_qp->ext_type = parms.ext_type;
+       my_qp->state = IB_QPS_RESET;
 
        if (init_attr->recv_cq)
                my_qp->recv_cq =
@@ -965,7 +966,7 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,
                 qp_num, bad_send_wqe_p);
        /* convert wqe pointer to vadr */
        bad_send_wqe_v = abs_to_virt((u64)bad_send_wqe_p);
-       if (ehca_debug_level)
+       if (ehca_debug_level >= 2)
                ehca_dmp(bad_send_wqe_v, 32, "qp_num=%x bad_wqe", qp_num);
        squeue = &my_qp->ipz_squeue;
        if (ipz_queue_abs_to_offset(squeue, (u64)bad_send_wqe_p, &q_ofs)) {
@@ -978,7 +979,7 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,
        wqe = (struct ehca_wqe *)ipz_qeit_calc(squeue, q_ofs);
        *bad_wqe_cnt = 0;
        while (wqe->optype != 0xff && wqe->wqef != 0xff) {
-               if (ehca_debug_level)
+               if (ehca_debug_level >= 2)
                        ehca_dmp(wqe, 32, "qp_num=%x wqe", qp_num);
                wqe->nr_of_data_seg = 0; /* suppress data access */
                wqe->wqef = WQEF_PURGE; /* WQE to be purged */
@@ -1450,7 +1451,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
                /* no support for max_send/recv_sge yet */
        }
 
-       if (ehca_debug_level)
+       if (ehca_debug_level >= 2)
                ehca_dmp(mqpcb, 4*70, "qp_num=%x", ibqp->qp_num);
 
        h_ret = hipz_h_modify_qp(shca->ipz_hca_handle,
@@ -1508,6 +1509,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
        if (attr_mask & IB_QP_QKEY)
                my_qp->qkey = attr->qkey;
 
+       my_qp->state = qp_new_state;
+
 modify_qp_exit2:
        if (squeue_locked) { /* this means: sqe -> rts */
                spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
@@ -1763,7 +1766,7 @@ int ehca_query_qp(struct ib_qp *qp,
        if (qp_init_attr)
                *qp_init_attr = my_qp->init_attr;
 
-       if (ehca_debug_level)
+       if (ehca_debug_level >= 2)
                ehca_dmp(qpcb, 4*70, "qp_num=%x", qp->qp_num);
 
 query_qp_exit1:
@@ -1811,7 +1814,7 @@ int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
                goto modify_srq_exit0;
        }
 
-       if (ehca_debug_level)
+       if (ehca_debug_level >= 2)
                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,
@@ -1864,7 +1867,7 @@ int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr)
        srq_attr->srq_limit = EHCA_BMASK_GET(
                MQPCB_CURR_SRQ_LIMIT, qpcb->curr_srq_limit);
 
-       if (ehca_debug_level)
+       if (ehca_debug_level >= 2)
                ehca_dmp(qpcb, 4*70, "qp_num=%x", my_qp->real_qp_num);
 
 query_srq_exit1:
index a20bbf4661881a095a34aab7cf13f5a443b832df..bbe0436f4f75a9b459c0d893deff27fa1e237e03 100644 (file)
@@ -81,7 +81,7 @@ static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue,
                        recv_wr->sg_list[cnt_ds].length;
        }
 
-       if (ehca_debug_level) {
+       if (ehca_debug_level >= 3) {
                ehca_gen_dbg("RECEIVE WQE written into ipz_rqueue=%p",
                             ipz_rqueue);
                ehca_dmp(wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "recv wqe");
@@ -281,7 +281,7 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
                return -EINVAL;
        }
 
-       if (ehca_debug_level) {
+       if (ehca_debug_level >= 3) {
                ehca_gen_dbg("SEND WQE written into queue qp=%p ", qp);
                ehca_dmp( wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "send wqe");
        }
@@ -421,6 +421,11 @@ int ehca_post_send(struct ib_qp *qp,
        int ret = 0;
        unsigned long flags;
 
+       if (unlikely(my_qp->state != IB_QPS_RTS)) {
+               ehca_err(qp->device, "QP not in RTS state  qpn=%x", qp->qp_num);
+               return -EINVAL;
+       }
+
        /* LOCK the QUEUE */
        spin_lock_irqsave(&my_qp->spinlock_s, flags);
 
@@ -454,13 +459,14 @@ int ehca_post_send(struct ib_qp *qp,
                        goto post_send_exit0;
                }
                wqe_cnt++;
-               ehca_dbg(qp->device, "ehca_qp=%p qp_num=%x wqe_cnt=%d",
-                        my_qp, qp->qp_num, wqe_cnt);
        } /* eof for cur_send_wr */
 
 post_send_exit0:
        iosync(); /* serialize GAL register access */
        hipz_update_sqa(my_qp, wqe_cnt);
+       if (unlikely(ret || ehca_debug_level >= 2))
+               ehca_dbg(qp->device, "ehca_qp=%p qp_num=%x wqe_cnt=%d ret=%i",
+                        my_qp, qp->qp_num, wqe_cnt, ret);
        my_qp->message_count += wqe_cnt;
        spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
        return ret;
@@ -520,13 +526,14 @@ static int internal_post_recv(struct ehca_qp *my_qp,
                        goto post_recv_exit0;
                }
                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:
        iosync(); /* serialize GAL register access */
        hipz_update_rqa(my_qp, wqe_cnt);
+       if (unlikely(ret || ehca_debug_level >= 2))
+           ehca_dbg(dev, "ehca_qp=%p qp_num=%x wqe_cnt=%d ret=%i",
+                    my_qp, my_qp->real_qp_num, wqe_cnt, ret);
        spin_unlock_irqrestore(&my_qp->spinlock_r, flags);
        return ret;
 }
@@ -570,16 +577,17 @@ static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc)
        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;
+       int cqe_count = 0, is_error;
 
 poll_cq_one_read_cqe:
        cqe = (struct ehca_cqe *)
                ipz_qeit_get_inc_valid(&my_cq->ipz_queue);
        if (!cqe) {
                ret = -EAGAIN;
-               ehca_dbg(cq->device, "Completion queue is empty ehca_cq=%p "
-                        "cq_num=%x ret=%i", my_cq, my_cq->cq_number, ret);
-               goto  poll_cq_one_exit0;
+               if (ehca_debug_level >= 3)
+                       ehca_dbg(cq->device, "Completion queue is empty  "
+                                "my_cq=%p cq_num=%x", my_cq, my_cq->cq_number);
+               goto poll_cq_one_exit0;
        }
 
        /* prevents loads being reordered across this point */
@@ -609,7 +617,7 @@ poll_cq_one_read_cqe:
                        ehca_dbg(cq->device,
                                 "Got CQE with purged bit qp_num=%x src_qp=%x",
                                 cqe->local_qp_number, cqe->remote_qp_number);
-                       if (ehca_debug_level)
+                       if (ehca_debug_level >= 2)
                                ehca_dmp(cqe, 64, "qp_num=%x src_qp=%x",
                                         cqe->local_qp_number,
                                         cqe->remote_qp_number);
@@ -622,11 +630,13 @@ poll_cq_one_read_cqe:
                }
        }
 
-       /* tracing cqe */
-       if (unlikely(ehca_debug_level)) {
+       is_error = cqe->status & WC_STATUS_ERROR_BIT;
+
+       /* trace error CQEs if debug_level >= 1, trace all CQEs if >= 3 */
+       if (unlikely(ehca_debug_level >= 3 || (ehca_debug_level && is_error))) {
                ehca_dbg(cq->device,
-                        "Received COMPLETION ehca_cq=%p cq_num=%x -----",
-                        my_cq, my_cq->cq_number);
+                        "Received %sCOMPLETION ehca_cq=%p cq_num=%x -----",
+                        is_error ? "ERROR " : "", my_cq, my_cq->cq_number);
                ehca_dmp(cqe, 64, "ehca_cq=%p cq_num=%x",
                         my_cq, my_cq->cq_number);
                ehca_dbg(cq->device,
@@ -649,8 +659,9 @@ poll_cq_one_read_cqe:
                /* update also queue adder to throw away this entry!!! */
                goto poll_cq_one_exit0;
        }
+
        /* eval ib_wc_status */
-       if (unlikely(cqe->status & WC_STATUS_ERROR_BIT)) {
+       if (unlikely(is_error)) {
                /* complete with errors */
                map_ib_wc_status(cqe->status, &wc->status);
                wc->vendor_err = wc->status;
@@ -671,14 +682,6 @@ poll_cq_one_read_cqe:
        wc->imm_data = cpu_to_be32(cqe->immediate_data);
        wc->sl = cqe->service_level;
 
-       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 "
-                        "cqe=%p", my_cq, my_cq->cq_number, cqe->optype,
-                        cqe->status, cqe->local_qp_number,
-                        cqe->remote_qp_number, cqe->work_request_id, cqe);
-
 poll_cq_one_exit0:
        if (cqe_count > 0)
                hipz_update_feca(my_cq, cqe_count);
index 1b07f2beafaf1426713d1475fa2969db4b485141..e43ed8f8a0c84a51b79c52e34590b821fbaf89dd 100644 (file)
@@ -211,8 +211,7 @@ static int ehca_mmap_qp(struct vm_area_struct *vma, struct ehca_qp *qp,
                break;
 
        case 1: /* qp rqueue_addr */
-               ehca_dbg(qp->ib_qp.device, "qp_num=%x rqueue",
-                        qp->ib_qp.qp_num);
+               ehca_dbg(qp->ib_qp.device, "qp_num=%x rq", qp->ib_qp.qp_num);
                ret = ehca_mmap_queue(vma, &qp->ipz_rqueue,
                                      &qp->mm_count_rqueue);
                if (unlikely(ret)) {
@@ -224,8 +223,7 @@ static int ehca_mmap_qp(struct vm_area_struct *vma, struct ehca_qp *qp,
                break;
 
        case 2: /* qp squeue_addr */
-               ehca_dbg(qp->ib_qp.device, "qp_num=%x squeue",
-                        qp->ib_qp.qp_num);
+               ehca_dbg(qp->ib_qp.device, "qp_num=%x sq", qp->ib_qp.qp_num);
                ret = ehca_mmap_queue(vma, &qp->ipz_squeue,
                                      &qp->mm_count_squeue);
                if (unlikely(ret)) {
index 7029aa6537517b043321004a4da114590c5ca04f..5245e13c3a30aac8dc4ebfdc3728499f4c2270f6 100644 (file)
@@ -123,8 +123,9 @@ static long ehca_plpar_hcall_norets(unsigned long opcode,
        int i, sleep_msecs;
        unsigned long flags = 0;
 
-       ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
-                    opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+       if (unlikely(ehca_debug_level >= 2))
+               ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
+                            opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
 
        for (i = 0; i < 5; i++) {
                /* serialize hCalls to work around firmware issue */
@@ -148,7 +149,8 @@ static long ehca_plpar_hcall_norets(unsigned long opcode,
                                     opcode, ret, arg1, arg2, arg3,
                                     arg4, arg5, arg6, arg7);
                else
-                       ehca_gen_dbg("opcode=%lx ret=%li", opcode, ret);
+                       if (unlikely(ehca_debug_level >= 2))
+                               ehca_gen_dbg("opcode=%lx ret=%li", opcode, ret);
 
                return ret;
        }
@@ -172,8 +174,10 @@ static long ehca_plpar_hcall9(unsigned long opcode,
        int i, sleep_msecs;
        unsigned long flags = 0;
 
-       ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,
-                    arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+       if (unlikely(ehca_debug_level >= 2))
+               ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,
+                            arg1, arg2, arg3, arg4, arg5,
+                            arg6, arg7, arg8, arg9);
 
        for (i = 0; i < 5; i++) {
                /* serialize hCalls to work around firmware issue */
@@ -201,7 +205,7 @@ static long ehca_plpar_hcall9(unsigned long opcode,
                                     ret, outs[0], outs[1], outs[2], outs[3],
                                     outs[4], outs[5], outs[6], outs[7],
                                     outs[8]);
-               } else
+               } else if (unlikely(ehca_debug_level >= 2))
                        ehca_gen_dbg("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,
                                     ret, outs[0], outs[1], outs[2], outs[3],
                                     outs[4], outs[5], outs[6], outs[7],
@@ -381,7 +385,7 @@ u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
                                      r_cb,                  /* r6 */
                                      0, 0, 0, 0);
 
-       if (ehca_debug_level)
+       if (ehca_debug_level >= 2)
                ehca_dmp(query_port_response_block, 64, "response_block");
 
        return ret;
@@ -731,9 +735,6 @@ u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
        u64 ret;
        u64 outs[PLPAR_HCALL9_BUFSIZE];
 
-       ehca_gen_dbg("kernel PAGE_SIZE=%x access_ctrl=%016x "
-                    "vaddr=%lx length=%lx",
-                    (u32)PAGE_SIZE, access_ctrl, vaddr, length);
        ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
                                adapter_handle.handle,            /* r4 */
                                5,                                /* r5 */
@@ -758,7 +759,7 @@ u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
 {
        u64 ret;
 
-       if (unlikely(ehca_debug_level >= 2)) {
+       if (unlikely(ehca_debug_level >= 3)) {
                if (count > 1) {
                        u64 *kpage;
                        int i;
index 3557e7edc9b6590e4973b9f847f3518c2f75c1f1..5e570bb0bb6f57fe6912bce4485b8cde60d90658 100644 (file)
@@ -204,7 +204,7 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
 
                uar = &to_mucontext(context)->uar;
        } else {
-               err = mlx4_ib_db_alloc(dev, &cq->db, 1);
+               err = mlx4_db_alloc(dev->dev, &cq->db, 1);
                if (err)
                        goto err_cq;
 
@@ -250,7 +250,7 @@ err_mtt:
 
 err_db:
        if (!context)
-               mlx4_ib_db_free(dev, &cq->db);
+               mlx4_db_free(dev->dev, &cq->db);
 
 err_cq:
        kfree(cq);
@@ -435,7 +435,7 @@ int mlx4_ib_destroy_cq(struct ib_cq *cq)
                ib_umem_release(mcq->umem);
        } else {
                mlx4_ib_free_cq_buf(dev, &mcq->buf, cq->cqe + 1);
-               mlx4_ib_db_free(dev, &mcq->db);
+               mlx4_db_free(dev->dev, &mcq->db);
        }
 
        kfree(mcq);
index 1c36087aef140d0dd1f9e0fa44dc7d2c245c8980..8e342cc9baec95430033bf2019547c7a4d90d4e6 100644 (file)
 
 #include "mlx4_ib.h"
 
-struct mlx4_ib_db_pgdir {
-       struct list_head        list;
-       DECLARE_BITMAP(order0, MLX4_IB_DB_PER_PAGE);
-       DECLARE_BITMAP(order1, MLX4_IB_DB_PER_PAGE / 2);
-       unsigned long          *bits[2];
-       __be32                 *db_page;
-       dma_addr_t              db_dma;
-};
-
-static struct mlx4_ib_db_pgdir *mlx4_ib_alloc_db_pgdir(struct mlx4_ib_dev *dev)
-{
-       struct mlx4_ib_db_pgdir *pgdir;
-
-       pgdir = kzalloc(sizeof *pgdir, GFP_KERNEL);
-       if (!pgdir)
-               return NULL;
-
-       bitmap_fill(pgdir->order1, MLX4_IB_DB_PER_PAGE / 2);
-       pgdir->bits[0] = pgdir->order0;
-       pgdir->bits[1] = pgdir->order1;
-       pgdir->db_page = dma_alloc_coherent(dev->ib_dev.dma_device,
-                                           PAGE_SIZE, &pgdir->db_dma,
-                                           GFP_KERNEL);
-       if (!pgdir->db_page) {
-               kfree(pgdir);
-               return NULL;
-       }
-
-       return pgdir;
-}
-
-static int mlx4_ib_alloc_db_from_pgdir(struct mlx4_ib_db_pgdir *pgdir,
-                                      struct mlx4_ib_db *db, int order)
-{
-       int o;
-       int i;
-
-       for (o = order; o <= 1; ++o) {
-               i = find_first_bit(pgdir->bits[o], MLX4_IB_DB_PER_PAGE >> o);
-               if (i < MLX4_IB_DB_PER_PAGE >> o)
-                       goto found;
-       }
-
-       return -ENOMEM;
-
-found:
-       clear_bit(i, pgdir->bits[o]);
-
-       i <<= o;
-
-       if (o > order)
-               set_bit(i ^ 1, pgdir->bits[order]);
-
-       db->u.pgdir = pgdir;
-       db->index   = i;
-       db->db      = pgdir->db_page + db->index;
-       db->dma     = pgdir->db_dma  + db->index * 4;
-       db->order   = order;
-
-       return 0;
-}
-
-int mlx4_ib_db_alloc(struct mlx4_ib_dev *dev, struct mlx4_ib_db *db, int order)
-{
-       struct mlx4_ib_db_pgdir *pgdir;
-       int ret = 0;
-
-       mutex_lock(&dev->pgdir_mutex);
-
-       list_for_each_entry(pgdir, &dev->pgdir_list, list)
-               if (!mlx4_ib_alloc_db_from_pgdir(pgdir, db, order))
-                       goto out;
-
-       pgdir = mlx4_ib_alloc_db_pgdir(dev);
-       if (!pgdir) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       list_add(&pgdir->list, &dev->pgdir_list);
-
-       /* This should never fail -- we just allocated an empty page: */
-       WARN_ON(mlx4_ib_alloc_db_from_pgdir(pgdir, db, order));
-
-out:
-       mutex_unlock(&dev->pgdir_mutex);
-
-       return ret;
-}
-
-void mlx4_ib_db_free(struct mlx4_ib_dev *dev, struct mlx4_ib_db *db)
-{
-       int o;
-       int i;
-
-       mutex_lock(&dev->pgdir_mutex);
-
-       o = db->order;
-       i = db->index;
-
-       if (db->order == 0 && test_bit(i ^ 1, db->u.pgdir->order0)) {
-               clear_bit(i ^ 1, db->u.pgdir->order0);
-               ++o;
-       }
-
-       i >>= o;
-       set_bit(i, db->u.pgdir->bits[o]);
-
-       if (bitmap_full(db->u.pgdir->order1, MLX4_IB_DB_PER_PAGE / 2)) {
-               dma_free_coherent(dev->ib_dev.dma_device, PAGE_SIZE,
-                                 db->u.pgdir->db_page, db->u.pgdir->db_dma);
-               list_del(&db->u.pgdir->list);
-               kfree(db->u.pgdir);
-       }
-
-       mutex_unlock(&dev->pgdir_mutex);
-}
-
 struct mlx4_ib_user_db_page {
        struct list_head        list;
        struct ib_umem         *umem;
@@ -160,7 +42,7 @@ struct mlx4_ib_user_db_page {
 };
 
 int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt,
-                       struct mlx4_ib_db *db)
+                       struct mlx4_db *db)
 {
        struct mlx4_ib_user_db_page *page;
        struct ib_umem_chunk *chunk;
@@ -202,7 +84,7 @@ out:
        return err;
 }
 
-void mlx4_ib_db_unmap_user(struct mlx4_ib_ucontext *context, struct mlx4_ib_db *db)
+void mlx4_ib_db_unmap_user(struct mlx4_ib_ucontext *context, struct mlx4_db *db)
 {
        mutex_lock(&context->db_page_mutex);
 
index 4d9b5ac42202cc3df5b81961068f18e65beb00ac..4d61e32866c6029c2dab38f873f6cbbc189df999 100644 (file)
@@ -557,9 +557,6 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
                goto err_uar;
        MLX4_INIT_DOORBELL_LOCK(&ibdev->uar_lock);
 
-       INIT_LIST_HEAD(&ibdev->pgdir_list);
-       mutex_init(&ibdev->pgdir_mutex);
-
        ibdev->dev = dev;
 
        strlcpy(ibdev->ib_dev.name, "mlx4_%d", IB_DEVICE_NAME_MAX);
index 9e637323c155769ff659439c801a8782aa8fb533..5cf994794d25f2ff3f99828696a990c49d58dd31 100644 (file)
 #include <linux/mlx4/device.h>
 #include <linux/mlx4/doorbell.h>
 
-enum {
-       MLX4_IB_DB_PER_PAGE     = PAGE_SIZE / 4
-};
-
-struct mlx4_ib_db_pgdir;
-struct mlx4_ib_user_db_page;
-
-struct mlx4_ib_db {
-       __be32                 *db;
-       union {
-               struct mlx4_ib_db_pgdir        *pgdir;
-               struct mlx4_ib_user_db_page    *user_page;
-       }                       u;
-       dma_addr_t              dma;
-       int                     index;
-       int                     order;
-};
-
 struct mlx4_ib_ucontext {
        struct ib_ucontext      ibucontext;
        struct mlx4_uar         uar;
@@ -88,7 +70,7 @@ struct mlx4_ib_cq {
        struct mlx4_cq          mcq;
        struct mlx4_ib_cq_buf   buf;
        struct mlx4_ib_cq_resize *resize_buf;
-       struct mlx4_ib_db       db;
+       struct mlx4_db          db;
        spinlock_t              lock;
        struct mutex            resize_mutex;
        struct ib_umem         *umem;
@@ -127,7 +109,7 @@ struct mlx4_ib_qp {
        struct mlx4_qp          mqp;
        struct mlx4_buf         buf;
 
-       struct mlx4_ib_db       db;
+       struct mlx4_db          db;
        struct mlx4_ib_wq       rq;
 
        u32                     doorbell_qpn;
@@ -154,7 +136,7 @@ struct mlx4_ib_srq {
        struct ib_srq           ibsrq;
        struct mlx4_srq         msrq;
        struct mlx4_buf         buf;
-       struct mlx4_ib_db       db;
+       struct mlx4_db          db;
        u64                    *wrid;
        spinlock_t              lock;
        int                     head;
@@ -175,9 +157,6 @@ struct mlx4_ib_dev {
        struct mlx4_dev        *dev;
        void __iomem           *uar_map;
 
-       struct list_head        pgdir_list;
-       struct mutex            pgdir_mutex;
-
        struct mlx4_uar         priv_uar;
        u32                     priv_pdn;
        MLX4_DECLARE_DOORBELL_LOCK(uar_lock);
@@ -248,11 +227,9 @@ static inline struct mlx4_ib_ah *to_mah(struct ib_ah *ibah)
        return container_of(ibah, struct mlx4_ib_ah, ibah);
 }
 
-int mlx4_ib_db_alloc(struct mlx4_ib_dev *dev, struct mlx4_ib_db *db, int order);
-void mlx4_ib_db_free(struct mlx4_ib_dev *dev, struct mlx4_ib_db *db);
 int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt,
-                       struct mlx4_ib_db *db);
-void mlx4_ib_db_unmap_user(struct mlx4_ib_ucontext *context, struct mlx4_ib_db *db);
+                       struct mlx4_db *db);
+void mlx4_ib_db_unmap_user(struct mlx4_ib_ucontext *context, struct mlx4_db *db);
 
 struct ib_mr *mlx4_ib_get_dma_mr(struct ib_pd *pd, int acc);
 int mlx4_ib_umem_write_mtt(struct mlx4_ib_dev *dev, struct mlx4_mtt *mtt,
index b75efae7e449f0d974b16672dc283a1e8ccb618d..80ea8b9e7761656cde75df7de58e33a50f3afdf3 100644 (file)
@@ -514,7 +514,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
                        goto err;
 
                if (!init_attr->srq) {
-                       err = mlx4_ib_db_alloc(dev, &qp->db, 0);
+                       err = mlx4_db_alloc(dev->dev, &qp->db, 0);
                        if (err)
                                goto err;
 
@@ -580,7 +580,7 @@ err_buf:
 
 err_db:
        if (!pd->uobject && !init_attr->srq)
-               mlx4_ib_db_free(dev, &qp->db);
+               mlx4_db_free(dev->dev, &qp->db);
 
 err:
        return err;
@@ -666,7 +666,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
                kfree(qp->rq.wrid);
                mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
                if (!qp->ibqp.srq)
-                       mlx4_ib_db_free(dev, &qp->db);
+                       mlx4_db_free(dev->dev, &qp->db);
        }
 }
 
index beaa3b06cf58b1eae91d08c2d6004b83223fcff0..204619702f9d7d9401bf5dd65012fbf2e0062de6 100644 (file)
@@ -129,7 +129,7 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
                if (err)
                        goto err_mtt;
        } else {
-               err = mlx4_ib_db_alloc(dev, &srq->db, 0);
+               err = mlx4_db_alloc(dev->dev, &srq->db, 0);
                if (err)
                        goto err_srq;
 
@@ -200,7 +200,7 @@ err_buf:
 
 err_db:
        if (!pd->uobject)
-               mlx4_ib_db_free(dev, &srq->db);
+               mlx4_db_free(dev->dev, &srq->db);
 
 err_srq:
        kfree(srq);
@@ -267,7 +267,7 @@ int mlx4_ib_destroy_srq(struct ib_srq *srq)
                kfree(msrq->wrid);
                mlx4_buf_free(dev->dev, msrq->msrq.max << msrq->msrq.wqe_shift,
                              &msrq->buf);
-               mlx4_ib_db_free(dev, &msrq->db);
+               mlx4_db_free(dev->dev, &msrq->db);
        }
 
        kfree(msrq);
index b046262ed638114bb8ce8c3d64ff9dd22267a62b..a4e9269a29bd106b604d1c8012efc25b4f1ab9c9 100644 (file)
@@ -139,8 +139,9 @@ static int nes_inetaddr_event(struct notifier_block *notifier,
 
        addr = ntohl(ifa->ifa_address);
        mask = ntohl(ifa->ifa_mask);
-       nes_debug(NES_DBG_NETDEV, "nes_inetaddr_event: ip address %08X, netmask %08X.\n",
-                       addr, mask);
+       nes_debug(NES_DBG_NETDEV, "nes_inetaddr_event: ip address " NIPQUAD_FMT
+                 ", netmask " NIPQUAD_FMT ".\n",
+                 HIPQUAD(addr), HIPQUAD(mask));
        list_for_each_entry(nesdev, &nes_dev_list, list) {
                nes_debug(NES_DBG_NETDEV, "Nesdev list entry = 0x%p. (%s)\n",
                                nesdev, nesdev->netdev[0]->name);
@@ -353,13 +354,11 @@ struct ib_qp *nes_get_qp(struct ib_device *device, int qpn)
  */
 static void nes_print_macaddr(struct net_device *netdev)
 {
-       nes_debug(NES_DBG_INIT, "%s: MAC %02X:%02X:%02X:%02X:%02X:%02X, IRQ %u\n",
-                       netdev->name,
-                       netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
-                       netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5],
-                       netdev->irq);
-}
+       DECLARE_MAC_BUF(mac);
 
+       nes_debug(NES_DBG_INIT, "%s: %s, IRQ %u\n",
+                 netdev->name, print_mac(mac, netdev->dev_addr), netdev->irq);
+}
 
 /**
  * nes_interrupt - handle interrupts
index d0738623bcf3529ecbef5ae6f64f8f7037720e33..d940fc27129afdc37e3457115eb58fb8a5ab25ef 100644 (file)
@@ -852,8 +852,8 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
        /* get a handle on the hte */
        hte = &cm_core->connected_nodes;
 
-       nes_debug(NES_DBG_CM, "Searching for an owner node:%x:%x from core %p->%p\n",
-                       loc_addr, loc_port, cm_core, hte);
+       nes_debug(NES_DBG_CM, "Searching for an owner node: " NIPQUAD_FMT ":%x from core %p->%p\n",
+                 HIPQUAD(loc_addr), loc_port, cm_core, hte);
 
        /* walk list and find cm_node associated with this session ID */
        spin_lock_irqsave(&cm_core->ht_lock, flags);
@@ -902,8 +902,8 @@ static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
        }
        spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
 
-       nes_debug(NES_DBG_CM, "Unable to find listener- %x:%x\n",
-                       dst_addr, dst_port);
+       nes_debug(NES_DBG_CM, "Unable to find listener for " NIPQUAD_FMT ":%x\n",
+                 HIPQUAD(dst_addr), dst_port);
 
        /* no listener */
        return NULL;
@@ -1054,6 +1054,7 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
        int arpindex = 0;
        struct nes_device *nesdev;
        struct nes_adapter *nesadapter;
+       DECLARE_MAC_BUF(mac);
 
        /* create an hte and cm_node for this instance */
        cm_node = kzalloc(sizeof(*cm_node), GFP_ATOMIC);
@@ -1066,8 +1067,9 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
        cm_node->loc_port = cm_info->loc_port;
        cm_node->rem_port = cm_info->rem_port;
        cm_node->send_write0 = send_first;
-       nes_debug(NES_DBG_CM, "Make node addresses : loc = %x:%x, rem = %x:%x\n",
-                       cm_node->loc_addr, cm_node->loc_port, cm_node->rem_addr, cm_node->rem_port);
+       nes_debug(NES_DBG_CM, "Make node addresses : loc = " NIPQUAD_FMT ":%x, rem = " NIPQUAD_FMT ":%x\n",
+                 HIPQUAD(cm_node->loc_addr), cm_node->loc_port,
+                 HIPQUAD(cm_node->rem_addr), cm_node->rem_port);
        cm_node->listener = listener;
        cm_node->netdev = nesvnic->netdev;
        cm_node->cm_id = cm_info->cm_id;
@@ -1116,11 +1118,8 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
 
        /* copy the mac addr to node context */
        memcpy(cm_node->rem_mac, nesadapter->arp_table[arpindex].mac_addr, ETH_ALEN);
-       nes_debug(NES_DBG_CM, "Remote mac addr from arp table:%02x,"
-                       " %02x, %02x, %02x, %02x, %02x\n",
-                       cm_node->rem_mac[0], cm_node->rem_mac[1],
-                       cm_node->rem_mac[2], cm_node->rem_mac[3],
-                       cm_node->rem_mac[4], cm_node->rem_mac[5]);
+       nes_debug(NES_DBG_CM, "Remote mac addr from arp table: %s\n",
+                 print_mac(mac, cm_node->rem_mac));
 
        add_hte_node(cm_core, cm_node);
        atomic_inc(&cm_nodes_created);
@@ -1850,8 +1849,10 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core, struct nes_vnic *nesvni
        nfo.rem_addr = ntohl(iph->saddr);
        nfo.rem_port = ntohs(tcph->source);
 
-       nes_debug(NES_DBG_CM, "Received packet: dest=0x%08X:0x%04X src=0x%08X:0x%04X\n",
-                       iph->daddr, tcph->dest, iph->saddr, tcph->source);
+       nes_debug(NES_DBG_CM, "Received packet: dest=" NIPQUAD_FMT
+                 ":0x%04X src=" NIPQUAD_FMT ":0x%04X\n",
+                 NIPQUAD(iph->daddr), tcph->dest,
+                 NIPQUAD(iph->saddr), tcph->source);
 
        /* note: this call is going to increment cm_node ref count */
        cm_node = find_node(cm_core,
index aa53aab91bf8a3341dd3df72d155c4b2201db2c1..08964cc7e98aead2bc4813c8505d1abdbafc2bc2 100644 (file)
@@ -636,6 +636,15 @@ static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_
                        nes_debug(NES_DBG_INIT, "Did not see full soft reset done.\n");
                        return 0;
                }
+
+               i = 0;
+               while ((nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS) != 0x80) && i++ < 10000)
+                       mdelay(1);
+               if (i >= 10000) {
+                       printk(KERN_ERR PFX "Internal CPU not ready, status = %02X\n",
+                              nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS));
+                       return 0;
+               }
        }
 
        /* port reset */
@@ -684,17 +693,6 @@ static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_
                }
        }
 
-
-
-       i = 0;
-       while ((nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS) != 0x80) && i++ < 10000)
-               mdelay(1);
-       if (i >= 10000) {
-               printk(KERN_ERR PFX "Internal CPU not ready, status = %02X\n",
-                               nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS));
-               return 0;
-       }
-
        return port_count;
 }
 
index b7e2844f096b620489c0b338e65e400937c16c4a..8f36e231bdf5db1e54e54a2707fb0bd12b165d0c 100644 (file)
@@ -905,7 +905,7 @@ struct nes_hw_qp {
 };
 
 struct nes_hw_cq {
-       struct nes_hw_cqe volatile *cq_vbase;   /* PCI memory for host rings */
+       struct nes_hw_cqe *cq_vbase;    /* PCI memory for host rings */
        void (*ce_handler)(struct nes_device *nesdev, struct nes_hw_cq *cq);
        dma_addr_t cq_pbase;    /* PCI memory for host rings */
        u16 cq_head;
index 01cd0effc492b0712e880ac016117d082a295ae6..e5366b013c1afc472c8f295f56791d21663e424a 100644 (file)
@@ -787,16 +787,14 @@ static int nes_netdev_set_mac_address(struct net_device *netdev, void *p)
        int i;
        u32 macaddr_low;
        u16 macaddr_high;
+       DECLARE_MAC_BUF(mac);
 
        if (!is_valid_ether_addr(mac_addr->sa_data))
                return -EADDRNOTAVAIL;
 
        memcpy(netdev->dev_addr, mac_addr->sa_data, netdev->addr_len);
-       printk(PFX "%s: Address length = %d, Address = %02X%02X%02X%02X%02X%02X..\n",
-                  __func__, netdev->addr_len,
-                  mac_addr->sa_data[0], mac_addr->sa_data[1],
-                  mac_addr->sa_data[2], mac_addr->sa_data[3],
-                  mac_addr->sa_data[4], mac_addr->sa_data[5]);
+       printk(PFX "%s: Address length = %d, Address = %s\n",
+              __func__, netdev->addr_len, print_mac(mac, mac_addr->sa_data));
        macaddr_high = ((u16)netdev->dev_addr[0]) << 8;
        macaddr_high += (u16)netdev->dev_addr[1];
        macaddr_low = ((u32)netdev->dev_addr[2]) << 24;
@@ -878,11 +876,11 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
                        if (mc_nic_index < 0)
                                mc_nic_index = nesvnic->nic_index;
                        if (multicast_addr) {
-                               nes_debug(NES_DBG_NIC_RX, "Assigning MC Address = %02X%02X%02X%02X%02X%02X to register 0x%04X nic_idx=%d\n",
-                                                 multicast_addr->dmi_addr[0], multicast_addr->dmi_addr[1],
-                                                 multicast_addr->dmi_addr[2], multicast_addr->dmi_addr[3],
-                                                 multicast_addr->dmi_addr[4], multicast_addr->dmi_addr[5],
-                                                 perfect_filter_register_address+(mc_index * 8), mc_nic_index);
+                               DECLARE_MAC_BUF(mac);
+                               nes_debug(NES_DBG_NIC_RX, "Assigning MC Address %s to register 0x%04X nic_idx=%d\n",
+                                         print_mac(mac, multicast_addr->dmi_addr),
+                                         perfect_filter_register_address+(mc_index * 8),
+                                         mc_nic_index);
                                macaddr_high = ((u16)multicast_addr->dmi_addr[0]) << 8;
                                macaddr_high += (u16)multicast_addr->dmi_addr[1];
                                macaddr_low = ((u32)multicast_addr->dmi_addr[2]) << 24;
index f9db07c2717d81e7f4e7eb7ecdcccc20d303f3ed..c6d5631a699546ddee342b255965b01c72c7c434 100644 (file)
@@ -660,7 +660,9 @@ int nes_arp_table(struct nes_device *nesdev, u32 ip_addr, u8 *mac_addr, u32 acti
 
        /* DELETE or RESOLVE */
        if (arp_index == nesadapter->arp_table_size) {
-               nes_debug(NES_DBG_NETDEV, "mac address not in ARP table - cannot delete or resolve\n");
+               nes_debug(NES_DBG_NETDEV, "MAC for " NIPQUAD_FMT " not in ARP table - cannot %s\n",
+                         HIPQUAD(ip_addr),
+                         action == NES_ARP_RESOLVE ? "resolve" : "delete");
                return -1;
        }
 
index f9a5d43908923081526b50e4eed3a709c5b4b8e0..ee74f7c7a6da85b3b163f0f1a5ab9171691705a5 100644 (file)
@@ -1976,7 +1976,7 @@ static int nes_destroy_cq(struct ib_cq *ib_cq)
 
        if (nescq->cq_mem_size)
                pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size,
-                               (void *)nescq->hw_cq.cq_vbase, nescq->hw_cq.cq_pbase);
+                                   nescq->hw_cq.cq_vbase, nescq->hw_cq.cq_pbase);
        kfree(nescq);
 
        return ret;
@@ -3610,6 +3610,12 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
        while (cqe_count < num_entries) {
                if (le32_to_cpu(nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) &
                                NES_CQE_VALID) {
+                       /*
+                        * Make sure we read CQ entry contents *after*
+                        * we've checked the valid bit.
+                        */
+                       rmb();
+
                        cqe = nescq->hw_cq.cq_vbase[head];
                        nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0;
                        u32temp = le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]);
index 73b2b176ad0e45e98adbb257d724fb1f814f507a..f1f142dc64b17e8608f0f668345a13af3b65fb65 100644 (file)
 /* constants */
 
 enum {
-       IPOIB_PACKET_SIZE         = 2048,
-       IPOIB_BUF_SIZE            = IPOIB_PACKET_SIZE + IB_GRH_BYTES,
-
        IPOIB_ENCAP_LEN           = 4,
 
+       IPOIB_UD_HEAD_SIZE        = IB_GRH_BYTES + IPOIB_ENCAP_LEN,
+       IPOIB_UD_RX_SG            = 2, /* max buffer needed for 4K mtu */
+
        IPOIB_CM_MTU              = 0x10000 - 0x10, /* padding to align header to 16 */
        IPOIB_CM_BUF_SIZE         = IPOIB_CM_MTU  + IPOIB_ENCAP_LEN,
        IPOIB_CM_HEAD_SIZE        = IPOIB_CM_BUF_SIZE % PAGE_SIZE,
@@ -139,7 +139,7 @@ struct ipoib_mcast {
 
 struct ipoib_rx_buf {
        struct sk_buff *skb;
-       u64             mapping;
+       u64             mapping[IPOIB_UD_RX_SG];
 };
 
 struct ipoib_tx_buf {
@@ -294,6 +294,7 @@ struct ipoib_dev_priv {
 
        unsigned int admin_mtu;
        unsigned int mcast_mtu;
+       unsigned int max_ib_mtu;
 
        struct ipoib_rx_buf *rx_ring;
 
@@ -305,6 +306,9 @@ struct ipoib_dev_priv {
        struct ib_send_wr    tx_wr;
        unsigned             tx_outstanding;
 
+       struct ib_recv_wr    rx_wr;
+       struct ib_sge        rx_sge[IPOIB_UD_RX_SG];
+
        struct ib_wc ibwc[IPOIB_NUM_WC];
 
        struct list_head dead_ahs;
@@ -366,6 +370,14 @@ struct ipoib_neigh {
        struct list_head    list;
 };
 
+#define IPOIB_UD_MTU(ib_mtu)           (ib_mtu - IPOIB_ENCAP_LEN)
+#define IPOIB_UD_BUF_SIZE(ib_mtu)      (ib_mtu + IB_GRH_BYTES)
+
+static inline int ipoib_ud_need_sg(unsigned int ib_mtu)
+{
+       return IPOIB_UD_BUF_SIZE(ib_mtu) > PAGE_SIZE;
+}
+
 /*
  * We stash a pointer to our private neighbour information after our
  * hardware address in neigh->ha.  The ALIGN() expression here makes
index 0205eb7c1bd3328bcefd4e8a5c31d62e01a6c01c..7cf1fa7074abfa28ca31e298c8c2c04a53b75ab8 100644 (file)
@@ -89,28 +89,59 @@ void ipoib_free_ah(struct kref *kref)
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
+static void ipoib_ud_dma_unmap_rx(struct ipoib_dev_priv *priv,
+                                 u64 mapping[IPOIB_UD_RX_SG])
+{
+       if (ipoib_ud_need_sg(priv->max_ib_mtu)) {
+               ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_UD_HEAD_SIZE,
+                                   DMA_FROM_DEVICE);
+               ib_dma_unmap_page(priv->ca, mapping[1], PAGE_SIZE,
+                                 DMA_FROM_DEVICE);
+       } else
+               ib_dma_unmap_single(priv->ca, mapping[0],
+                                   IPOIB_UD_BUF_SIZE(priv->max_ib_mtu),
+                                   DMA_FROM_DEVICE);
+}
+
+static void ipoib_ud_skb_put_frags(struct ipoib_dev_priv *priv,
+                                  struct sk_buff *skb,
+                                  unsigned int length)
+{
+       if (ipoib_ud_need_sg(priv->max_ib_mtu)) {
+               skb_frag_t *frag = &skb_shinfo(skb)->frags[0];
+               unsigned int size;
+               /*
+                * There is only two buffers needed for max_payload = 4K,
+                * first buf size is IPOIB_UD_HEAD_SIZE
+                */
+               skb->tail += IPOIB_UD_HEAD_SIZE;
+               skb->len  += length;
+
+               size = length - IPOIB_UD_HEAD_SIZE;
+
+               frag->size     = size;
+               skb->data_len += size;
+               skb->truesize += size;
+       } else
+               skb_put(skb, length);
+
+}
+
 static int ipoib_ib_post_receive(struct net_device *dev, int id)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
-       struct ib_sge list;
-       struct ib_recv_wr param;
        struct ib_recv_wr *bad_wr;
        int ret;
 
-       list.addr     = priv->rx_ring[id].mapping;
-       list.length   = IPOIB_BUF_SIZE;
-       list.lkey     = priv->mr->lkey;
+       priv->rx_wr.wr_id   = id | IPOIB_OP_RECV;
+       priv->rx_sge[0].addr = priv->rx_ring[id].mapping[0];
+       priv->rx_sge[1].addr = priv->rx_ring[id].mapping[1];
 
-       param.next    = NULL;
-       param.wr_id   = id | IPOIB_OP_RECV;
-       param.sg_list = &list;
-       param.num_sge = 1;
 
-       ret = ib_post_recv(priv->qp, &param, &bad_wr);
+       ret = ib_post_recv(priv->qp, &priv->rx_wr, &bad_wr);
        if (unlikely(ret)) {
                ipoib_warn(priv, "receive failed for buf %d (%d)\n", id, ret);
-               ib_dma_unmap_single(priv->ca, priv->rx_ring[id].mapping,
-                                   IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
+               ipoib_ud_dma_unmap_rx(priv, priv->rx_ring[id].mapping);
                dev_kfree_skb_any(priv->rx_ring[id].skb);
                priv->rx_ring[id].skb = NULL;
        }
@@ -118,15 +149,21 @@ static int ipoib_ib_post_receive(struct net_device *dev, int id)
        return ret;
 }
 
-static int ipoib_alloc_rx_skb(struct net_device *dev, int id)
+static struct sk_buff *ipoib_alloc_rx_skb(struct net_device *dev, int id)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct sk_buff *skb;
-       u64 addr;
+       int buf_size;
+       u64 *mapping;
 
-       skb = dev_alloc_skb(IPOIB_BUF_SIZE + 4);
-       if (!skb)
-               return -ENOMEM;
+       if (ipoib_ud_need_sg(priv->max_ib_mtu))
+               buf_size = IPOIB_UD_HEAD_SIZE;
+       else
+               buf_size = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu);
+
+       skb = dev_alloc_skb(buf_size + 4);
+       if (unlikely(!skb))
+               return NULL;
 
        /*
         * IB will leave a 40 byte gap for a GRH and IPoIB adds a 4 byte
@@ -135,17 +172,32 @@ static int ipoib_alloc_rx_skb(struct net_device *dev, int id)
         */
        skb_reserve(skb, 4);
 
-       addr = ib_dma_map_single(priv->ca, skb->data, IPOIB_BUF_SIZE,
-                                DMA_FROM_DEVICE);
-       if (unlikely(ib_dma_mapping_error(priv->ca, addr))) {
-               dev_kfree_skb_any(skb);
-               return -EIO;
+       mapping = priv->rx_ring[id].mapping;
+       mapping[0] = ib_dma_map_single(priv->ca, skb->data, buf_size,
+                                      DMA_FROM_DEVICE);
+       if (unlikely(ib_dma_mapping_error(priv->ca, mapping[0])))
+               goto error;
+
+       if (ipoib_ud_need_sg(priv->max_ib_mtu)) {
+               struct page *page = alloc_page(GFP_ATOMIC);
+               if (!page)
+                       goto partial_error;
+               skb_fill_page_desc(skb, 0, page, 0, PAGE_SIZE);
+               mapping[1] =
+                       ib_dma_map_page(priv->ca, skb_shinfo(skb)->frags[0].page,
+                                       0, PAGE_SIZE, DMA_FROM_DEVICE);
+               if (unlikely(ib_dma_mapping_error(priv->ca, mapping[1])))
+                       goto partial_error;
        }
 
-       priv->rx_ring[id].skb     = skb;
-       priv->rx_ring[id].mapping = addr;
+       priv->rx_ring[id].skb = skb;
+       return skb;
 
-       return 0;
+partial_error:
+       ib_dma_unmap_single(priv->ca, mapping[0], buf_size, DMA_FROM_DEVICE);
+error:
+       dev_kfree_skb_any(skb);
+       return NULL;
 }
 
 static int ipoib_ib_post_receives(struct net_device *dev)
@@ -154,7 +206,7 @@ static int ipoib_ib_post_receives(struct net_device *dev)
        int i;
 
        for (i = 0; i < ipoib_recvq_size; ++i) {
-               if (ipoib_alloc_rx_skb(dev, i)) {
+               if (!ipoib_alloc_rx_skb(dev, i)) {
                        ipoib_warn(priv, "failed to allocate receive buffer %d\n", i);
                        return -ENOMEM;
                }
@@ -172,7 +224,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        unsigned int wr_id = wc->wr_id & ~IPOIB_OP_RECV;
        struct sk_buff *skb;
-       u64 addr;
+       u64 mapping[IPOIB_UD_RX_SG];
 
        ipoib_dbg_data(priv, "recv completion: id %d, status: %d\n",
                       wr_id, wc->status);
@@ -184,15 +236,13 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
        }
 
        skb  = priv->rx_ring[wr_id].skb;
-       addr = priv->rx_ring[wr_id].mapping;
 
        if (unlikely(wc->status != IB_WC_SUCCESS)) {
                if (wc->status != IB_WC_WR_FLUSH_ERR)
                        ipoib_warn(priv, "failed recv event "
                                   "(status=%d, wrid=%d vend_err %x)\n",
                                   wc->status, wr_id, wc->vendor_err);
-               ib_dma_unmap_single(priv->ca, addr,
-                                   IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
+               ipoib_ud_dma_unmap_rx(priv, priv->rx_ring[wr_id].mapping);
                dev_kfree_skb_any(skb);
                priv->rx_ring[wr_id].skb = NULL;
                return;
@@ -205,11 +255,14 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
        if (wc->slid == priv->local_lid && wc->src_qp == priv->qp->qp_num)
                goto repost;
 
+       memcpy(mapping, priv->rx_ring[wr_id].mapping,
+              IPOIB_UD_RX_SG * sizeof *mapping);
+
        /*
         * If we can't allocate a new RX buffer, dump
         * this packet and reuse the old buffer.
         */
-       if (unlikely(ipoib_alloc_rx_skb(dev, wr_id))) {
+       if (unlikely(!ipoib_alloc_rx_skb(dev, wr_id))) {
                ++dev->stats.rx_dropped;
                goto repost;
        }
@@ -217,9 +270,9 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
        ipoib_dbg_data(priv, "received %d bytes, SLID 0x%04x\n",
                       wc->byte_len, wc->slid);
 
-       ib_dma_unmap_single(priv->ca, addr, IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
+       ipoib_ud_dma_unmap_rx(priv, mapping);
+       ipoib_ud_skb_put_frags(priv, skb, wc->byte_len);
 
-       skb_put(skb, wc->byte_len);
        skb_pull(skb, IB_GRH_BYTES);
 
        skb->protocol = ((struct ipoib_header *) skb->data)->proto;
@@ -733,10 +786,8 @@ int ipoib_ib_dev_stop(struct net_device *dev, int flush)
                                rx_req = &priv->rx_ring[i];
                                if (!rx_req->skb)
                                        continue;
-                               ib_dma_unmap_single(priv->ca,
-                                                   rx_req->mapping,
-                                                   IPOIB_BUF_SIZE,
-                                                   DMA_FROM_DEVICE);
+                               ipoib_ud_dma_unmap_rx(priv,
+                                                     priv->rx_ring[i].mapping);
                                dev_kfree_skb_any(rx_req->skb);
                                rx_req->skb = NULL;
                        }
index bd07f02cf02be6e36864db79fca3494d8a9bed05..7a4ed9d3d8447368466aad077abea153c5b776c0 100644 (file)
@@ -195,7 +195,7 @@ static int ipoib_change_mtu(struct net_device *dev, int new_mtu)
                return 0;
        }
 
-       if (new_mtu > IPOIB_PACKET_SIZE - IPOIB_ENCAP_LEN)
+       if (new_mtu > IPOIB_UD_MTU(priv->max_ib_mtu))
                return -EINVAL;
 
        priv->admin_mtu = new_mtu;
@@ -971,10 +971,6 @@ static void ipoib_setup(struct net_device *dev)
                                    NETIF_F_LLTX                |
                                    NETIF_F_HIGHDMA);
 
-       /* MTU will be reset when mcast join happens */
-       dev->mtu                 = IPOIB_PACKET_SIZE - IPOIB_ENCAP_LEN;
-       priv->mcast_mtu          = priv->admin_mtu = dev->mtu;
-
        memcpy(dev->broadcast, ipv4_bcast_addr, INFINIBAND_ALEN);
 
        netif_carrier_off(dev);
@@ -1107,6 +1103,7 @@ static struct net_device *ipoib_add_port(const char *format,
 {
        struct ipoib_dev_priv *priv;
        struct ib_device_attr *device_attr;
+       struct ib_port_attr attr;
        int result = -ENOMEM;
 
        priv = ipoib_intf_alloc(format);
@@ -1115,6 +1112,18 @@ static struct net_device *ipoib_add_port(const char *format,
 
        SET_NETDEV_DEV(priv->dev, hca->dma_device);
 
+       if (!ib_query_port(hca, port, &attr))
+               priv->max_ib_mtu = ib_mtu_enum_to_int(attr.max_mtu);
+       else {
+               printk(KERN_WARNING "%s: ib_query_port %d failed\n",
+                      hca->name, port);
+               goto device_init_failed;
+       }
+
+       /* MTU will be reset when mcast join happens */
+       priv->dev->mtu  = IPOIB_UD_MTU(priv->max_ib_mtu);
+       priv->mcast_mtu  = priv->admin_mtu = priv->dev->mtu;
+
        result = ib_query_pkey(hca, port, 0, &priv->pkey);
        if (result) {
                printk(KERN_WARNING "%s: ib_query_pkey port %d failed (ret = %d)\n",
index 31a53c5bcb1317cd52dc2be80dd3f43238184d6e..d00a2c174aee2c2c3a91453f94b2fb51d3840b2c 100644 (file)
@@ -567,8 +567,7 @@ void ipoib_mcast_join_task(struct work_struct *work)
                return;
        }
 
-       priv->mcast_mtu = ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu) -
-               IPOIB_ENCAP_LEN;
+       priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu));
 
        if (!ipoib_cm_admin_enabled(dev))
                dev->mtu = min(priv->mcast_mtu, priv->admin_mtu);
index 8a20e3742c4356119a1c899514e1520eb049b963..07c03f178a498b0ff6488a32a1cfe45057864c5b 100644 (file)
@@ -150,7 +150,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
                        .max_send_wr  = ipoib_sendq_size,
                        .max_recv_wr  = ipoib_recvq_size,
                        .max_send_sge = 1,
-                       .max_recv_sge = 1
+                       .max_recv_sge = IPOIB_UD_RX_SG
                },
                .sq_sig_type = IB_SIGNAL_ALL_WR,
                .qp_type     = IB_QPT_UD
@@ -215,6 +215,19 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
        priv->tx_wr.sg_list     = priv->tx_sge;
        priv->tx_wr.send_flags  = IB_SEND_SIGNALED;
 
+       priv->rx_sge[0].lkey = priv->mr->lkey;
+       if (ipoib_ud_need_sg(priv->max_ib_mtu)) {
+               priv->rx_sge[0].length = IPOIB_UD_HEAD_SIZE;
+               priv->rx_sge[1].length = PAGE_SIZE;
+               priv->rx_sge[1].lkey = priv->mr->lkey;
+               priv->rx_wr.num_sge = IPOIB_UD_RX_SG;
+       } else {
+               priv->rx_sge[0].length = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu);
+               priv->rx_wr.num_sge = 1;
+       }
+       priv->rx_wr.next = NULL;
+       priv->rx_wr.sg_list = priv->rx_sge;
+
        return 0;
 
 out_free_cq:
index 293f5b892e3f5f20d33ababa2a50f1688254f891..431fdeaa2dc4f8075fd9ecb5c7b0b41382dcd207 100644 (file)
@@ -89,6 +89,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
                goto err;
        }
 
+       priv->max_ib_mtu = ppriv->max_ib_mtu;
        set_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags);
 
        priv->pkey = pkey;
index 9dea14db724ca1a186f8d7f765b94c28ed0db3a3..5f9d860925a17c7f8799880ba096fe2ccd41dc3c 100644 (file)
@@ -149,6 +149,15 @@ config INPUT_APMPOWER
          To compile this driver as a module, choose M here: the
          module will be called apm-power.
 
+config XEN_KBDDEV_FRONTEND
+       tristate "Xen virtual keyboard and mouse support"
+       depends on XEN_FBDEV_FRONTEND
+       default y
+       help
+         This driver implements the front-end of the Xen virtual
+         keyboard and mouse device driver.  It communicates with a back-end
+         in another domain.
+
 comment "Input Device Drivers"
 
 source "drivers/input/keyboard/Kconfig"
index 2ae87b19caa891cfe21ce1b49bc5923e15909a99..98c4f9a778768d40af7a4942624caf8f46f13260 100644 (file)
@@ -23,3 +23,5 @@ obj-$(CONFIG_INPUT_TOUCHSCREEN)       += touchscreen/
 obj-$(CONFIG_INPUT_MISC)       += misc/
 
 obj-$(CONFIG_INPUT_APMPOWER)   += apm-power.o
+
+obj-$(CONFIG_XEN_KBDDEV_FRONTEND)      += xen-kbdfront.o
index 490918a5d1922789f1f206c2746579c6c78a7009..0d3ce7a50fb1a345ab10a8ff1926dc4635475a90 100644 (file)
@@ -73,7 +73,7 @@ static void input_polled_device_work(struct work_struct *work)
 
 static int input_open_polled_device(struct input_dev *input)
 {
-       struct input_polled_dev *dev = input->private;
+       struct input_polled_dev *dev = input_get_drvdata(input);
        int error;
 
        error = input_polldev_start_workqueue();
@@ -91,7 +91,7 @@ static int input_open_polled_device(struct input_dev *input)
 
 static void input_close_polled_device(struct input_dev *input)
 {
-       struct input_polled_dev *dev = input->private;
+       struct input_polled_dev *dev = input_get_drvdata(input);
 
        cancel_delayed_work_sync(&dev->work);
        input_polldev_stop_workqueue();
@@ -151,10 +151,10 @@ int input_register_polled_device(struct input_polled_dev *dev)
 {
        struct input_dev *input = dev->input;
 
+       input_set_drvdata(input, dev);
        INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
        if (!dev->poll_interval)
                dev->poll_interval = 500;
-       input->private = dev;
        input->open = input_open_polled_device;
        input->close = input_close_polled_device;
 
index 7c662ee594a3e9fdf85761765ae6776ddecf05d9..be5c14a5a0a4f8afcff50c18ee6ecd4343d44411 100644 (file)
@@ -193,6 +193,18 @@ config JOYSTICK_TWIDJOY
          To compile this driver as a module, choose M here: the
          module will be called twidjoy.
 
+config JOYSTICK_ZHENHUA
+       tristate "5-byte Zhenhua RC transmitter"
+       select SERIO
+       help
+         Say Y here if you have a Zhen Hua PPM-4CH transmitter which is
+         supplied with a ready to fly micro electric indoor helicopters
+         such as EasyCopter, Lama, MiniCopter, DragonFly or Jabo and want
+         to use it via serial cable as a joystick.
+
+         To compile this driver as a module, choose M here: the
+         module will be called zhenhua.
+
 config JOYSTICK_DB9
        tristate "Multisystem, Sega Genesis, Saturn joysticks and gamepads"
        depends on PARPORT
index e855abb0cc5175e0ffc9692e9e3f5b20efb937ef..fdbf8c4c2876083686f8fc868427776792f80997 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_JOYSTICK_GF2K)           += gf2k.o
 obj-$(CONFIG_JOYSTICK_GRIP)            += grip.o
 obj-$(CONFIG_JOYSTICK_GRIP_MP)         += grip_mp.o
 obj-$(CONFIG_JOYSTICK_GUILLEMOT)       += guillemot.o
+obj-$(CONFIG_JOYSTICK_IFORCE)          += iforce/
 obj-$(CONFIG_JOYSTICK_INTERACT)                += interact.o
 obj-$(CONFIG_JOYSTICK_JOYDUMP)         += joydump.o
 obj-$(CONFIG_JOYSTICK_MAGELLAN)                += magellan.o
@@ -27,5 +28,5 @@ obj-$(CONFIG_JOYSTICK_TURBOGRAFX)     += turbografx.o
 obj-$(CONFIG_JOYSTICK_TWIDJOY)         += twidjoy.o
 obj-$(CONFIG_JOYSTICK_WARRIOR)         += warrior.o
 obj-$(CONFIG_JOYSTICK_XPAD)            += xpad.o
+obj-$(CONFIG_JOYSTICK_ZHENHUA)         += zhenhua.o
 
-obj-$(CONFIG_JOYSTICK_IFORCE)          += iforce/
index 0380597249bba224e84b55eb672cf474ff9c7496..b29e3affb805a97126ccee39dcc867cd6e40dfe3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * X-Box gamepad - v0.0.6
+ * X-Box gamepad driver
  *
  * Copyright (c) 2002 Marko Friedemann <mfr@bmx-chemnitz.de>
  *               2004 Oliver Schwartz <Oliver.Schwartz@gmx.de>,
@@ -68,6 +68,8 @@
  *  - dance pads will map D-PAD to buttons, not axes
  *  - pass the module paramater 'dpad_to_buttons' to force
  *    the D-PAD to map to buttons if your pad is not detected
+ *
+ * Later changes can be tracked in SCM.
  */
 
 #include <linux/kernel.h>
@@ -77,7 +79,6 @@
 #include <linux/module.h>
 #include <linux/usb/input.h>
 
-#define DRIVER_VERSION "v0.0.6"
 #define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>"
 #define DRIVER_DESC "X-Box pad driver"
 
    but we map them to axes when possible to simplify things */
 #define MAP_DPAD_TO_BUTTONS    0
 #define MAP_DPAD_TO_AXES       1
-#define MAP_DPAD_UNKNOWN       -1
+#define MAP_DPAD_UNKNOWN       2
 
 #define XTYPE_XBOX        0
 #define XTYPE_XBOX360     1
+#define XTYPE_XBOX360W    2
+#define XTYPE_UNKNOWN     3
 
 static int dpad_to_buttons;
 module_param(dpad_to_buttons, bool, S_IRUGO);
@@ -107,8 +110,10 @@ static const struct xpad_device {
        { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
        { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
        { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+       { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
        { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
        { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+       { 0x046d, 0xc242, "Logitech Chillstream Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
        { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
        { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES, XTYPE_XBOX },
        { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
@@ -135,18 +140,26 @@ static const struct xpad_device {
        { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
        { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
        { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+       { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
        { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
        { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
        { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
-       { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_XBOX }
+       { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN }
 };
 
-static const signed short xpad_btn[] = {
-       BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z,       /* "analog" buttons */
+/* buttons shared with xbox and xbox360 */
+static const signed short xpad_common_btn[] = {
+       BTN_A, BTN_B, BTN_X, BTN_Y,                     /* "analog" buttons */
        BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR,    /* start/back/sticks */
        -1                                              /* terminating entry */
 };
 
+/* original xbox controllers only */
+static const signed short xpad_btn[] = {
+       BTN_C, BTN_Z,           /* "analog" buttons */
+       -1                      /* terminating entry */
+};
+
 /* only used if MAP_DPAD_TO_BUTTONS */
 static const signed short xpad_btn_pad[] = {
        BTN_LEFT, BTN_RIGHT,            /* d-pad left, right */
@@ -173,12 +186,27 @@ static const signed short xpad_abs_pad[] = {
        -1                      /* terminating entry */
 };
 
-/* Xbox 360 has a vendor-specific (sub)class, so we cannot match it with only
- * USB_INTERFACE_INFO, more to that this device has 4 InterfaceProtocols,
- * but we need only one of them. */
+/* Xbox 360 has a vendor-specific class, so we cannot match it with only
+ * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we
+ * match against vendor id as well. Wired Xbox 360 devices have protocol 1,
+ * wireless controllers have protocol 129. */
+#define XPAD_XBOX360_VENDOR_PROTOCOL(vend,pr) \
+       .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \
+       .idVendor = (vend), \
+       .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
+       .bInterfaceSubClass = 93, \
+       .bInterfaceProtocol = (pr)
+#define XPAD_XBOX360_VENDOR(vend) \
+       { XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \
+       { XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) }
+
 static struct usb_device_id xpad_table [] = {
        { USB_INTERFACE_INFO('X', 'B', 0) },    /* X-Box USB-IF not approved class */
-       { USB_DEVICE_INTERFACE_PROTOCOL(0x045e, 0x028e, 1) },   /* X-Box 360 controller */
+       XPAD_XBOX360_VENDOR(0x045e),            /* Microsoft X-Box 360 controllers */
+       XPAD_XBOX360_VENDOR(0x046d),            /* Logitech X-Box 360 style controllers */
+       XPAD_XBOX360_VENDOR(0x0738),            /* Mad Catz X-Box 360 controllers */
+       XPAD_XBOX360_VENDOR(0x0e6f),            /* 0x0e6f X-Box 360 controllers */
+       XPAD_XBOX360_VENDOR(0x1430),            /* RedOctane X-Box 360 controllers */
        { }
 };
 
@@ -188,10 +216,15 @@ struct usb_xpad {
        struct input_dev *dev;          /* input device interface */
        struct usb_device *udev;        /* usb device */
 
+       int pad_present;
+
        struct urb *irq_in;             /* urb for interrupt in report */
        unsigned char *idata;           /* input data */
        dma_addr_t idata_dma;
 
+       struct urb *bulk_out;
+       unsigned char *bdata;
+
 #if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
        struct urb *irq_out;            /* urb for interrupt out report */
        unsigned char *odata;           /* output data */
@@ -227,13 +260,13 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
        input_report_abs(dev, ABS_X,
                         (__s16) le16_to_cpup((__le16 *)(data + 12)));
        input_report_abs(dev, ABS_Y,
-                        (__s16) le16_to_cpup((__le16 *)(data + 14)));
+                        ~(__s16) le16_to_cpup((__le16 *)(data + 14)));
 
        /* right stick */
        input_report_abs(dev, ABS_RX,
                         (__s16) le16_to_cpup((__le16 *)(data + 16)));
        input_report_abs(dev, ABS_RY,
-                        (__s16) le16_to_cpup((__le16 *)(data + 18)));
+                        ~(__s16) le16_to_cpup((__le16 *)(data + 18)));
 
        /* triggers left/right */
        input_report_abs(dev, ABS_Z, data[10]);
@@ -321,13 +354,13 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
        input_report_abs(dev, ABS_X,
                         (__s16) le16_to_cpup((__le16 *)(data + 6)));
        input_report_abs(dev, ABS_Y,
-                        (__s16) le16_to_cpup((__le16 *)(data + 8)));
+                        ~(__s16) le16_to_cpup((__le16 *)(data + 8)));
 
        /* right stick */
        input_report_abs(dev, ABS_RX,
                         (__s16) le16_to_cpup((__le16 *)(data + 10)));
        input_report_abs(dev, ABS_RY,
-                        (__s16) le16_to_cpup((__le16 *)(data + 12)));
+                        ~(__s16) le16_to_cpup((__le16 *)(data + 12)));
 
        /* triggers left/right */
        input_report_abs(dev, ABS_Z, data[4]);
@@ -336,12 +369,47 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
        input_sync(dev);
 }
 
+/*
+ * xpad360w_process_packet
+ *
+ * Completes a request by converting the data into events for the
+ * input subsystem. It is version for xbox 360 wireless controller.
+ *
+ * Byte.Bit
+ * 00.1 - Status change: The controller or headset has connected/disconnected
+ *                       Bits 01.7 and 01.6 are valid
+ * 01.7 - Controller present
+ * 01.6 - Headset present
+ * 01.1 - Pad state (Bytes 4+) valid
+ *
+ */
+
+static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
+{
+       /* Presence change */
+       if (data[0] & 0x08) {
+               if (data[1] & 0x80) {
+                       xpad->pad_present = 1;
+                       usb_submit_urb(xpad->bulk_out, GFP_ATOMIC);
+               } else
+                       xpad->pad_present = 0;
+       }
+
+       /* Valid pad data */
+       if (!(data[1] & 0x1))
+               return;
+
+       xpad360_process_packet(xpad, cmd, &data[4]);
+}
+
 static void xpad_irq_in(struct urb *urb)
 {
        struct usb_xpad *xpad = urb->context;
-       int retval;
+       int retval, status;
 
-       switch (urb->status) {
+       status = urb->status;
+
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -350,18 +418,24 @@ static void xpad_irq_in(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;
        }
 
-       if (xpad->xtype == XTYPE_XBOX360)
+       switch (xpad->xtype) {
+       case XTYPE_XBOX360:
                xpad360_process_packet(xpad, 0, xpad->idata);
-       else
+               break;
+       case XTYPE_XBOX360W:
+               xpad360w_process_packet(xpad, 0, xpad->idata);
+               break;
+       default:
                xpad_process_packet(xpad, 0, xpad->idata);
+       }
 
 exit:
        retval = usb_submit_urb (urb, GFP_ATOMIC);
@@ -370,12 +444,31 @@ exit:
                     __FUNCTION__, retval);
 }
 
+static void xpad_bulk_out(struct urb *urb)
+{
+       switch (urb->status) {
+       case 0:
+               /* success */
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               break;
+       default:
+               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+       }
+}
+
 #if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
 static void xpad_irq_out(struct urb *urb)
 {
-       int retval;
+       int retval, status;
 
-       switch (urb->status) {
+       status = urb->status;
+
+       switch (status) {
                case 0:
                /* success */
                break;
@@ -384,11 +477,11 @@ static void xpad_irq_out(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;
        }
 
@@ -408,7 +501,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
                return 0;
 
        xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN,
-                                      GFP_ATOMIC, &xpad->odata_dma );
+                                      GFP_KERNEL, &xpad->odata_dma);
        if (!xpad->odata)
                goto fail1;
 
@@ -469,6 +562,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data,
                xpad->odata[5] = 0x00;
                xpad->odata[6] = 0x00;
                xpad->odata[7] = 0x00;
+               xpad->irq_out->transfer_buffer_length = 8;
                usb_submit_urb(xpad->irq_out, GFP_KERNEL);
        }
 
@@ -477,6 +571,9 @@ static int xpad_play_effect(struct input_dev *dev, void *data,
 
 static int xpad_init_ff(struct usb_xpad *xpad)
 {
+       if (xpad->xtype != XTYPE_XBOX360)
+               return 0;
+
        input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
 
        return input_ff_create_memless(xpad->dev, NULL, xpad_play_effect);
@@ -502,6 +599,7 @@ static void xpad_send_led_command(struct usb_xpad *xpad, int command)
                xpad->odata[0] = 0x01;
                xpad->odata[1] = 0x03;
                xpad->odata[2] = command;
+               xpad->irq_out->transfer_buffer_length = 3;
                usb_submit_urb(xpad->irq_out, GFP_KERNEL);
                mutex_unlock(&xpad->odata_mutex);
        }
@@ -574,6 +672,10 @@ static int xpad_open(struct input_dev *dev)
 {
        struct usb_xpad *xpad = input_get_drvdata(dev);
 
+       /* URB was submitted in probe */
+       if(xpad->xtype == XTYPE_XBOX360W)
+               return 0;
+
        xpad->irq_in->dev = xpad->udev;
        if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
                return -EIO;
@@ -585,7 +687,8 @@ static void xpad_close(struct input_dev *dev)
 {
        struct usb_xpad *xpad = input_get_drvdata(dev);
 
-       usb_kill_urb(xpad->irq_in);
+       if(xpad->xtype != XTYPE_XBOX360W)
+               usb_kill_urb(xpad->irq_in);
        xpad_stop_output(xpad);
 }
 
@@ -632,7 +735,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
                goto fail1;
 
        xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN,
-                                      GFP_ATOMIC, &xpad->idata_dma);
+                                      GFP_KERNEL, &xpad->idata_dma);
        if (!xpad->idata)
                goto fail1;
 
@@ -644,7 +747,16 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
        xpad->dpad_mapping = xpad_device[i].dpad_mapping;
        xpad->xtype = xpad_device[i].xtype;
        if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN)
-               xpad->dpad_mapping = dpad_to_buttons;
+               xpad->dpad_mapping = !dpad_to_buttons;
+       if (xpad->xtype == XTYPE_UNKNOWN) {
+               if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
+                       if (intf->cur_altsetting->desc.bInterfaceProtocol == 129)
+                               xpad->xtype = XTYPE_XBOX360W;
+                       else
+                               xpad->xtype = XTYPE_XBOX360;
+               } else
+                       xpad->xtype = XTYPE_XBOX;
+       }
        xpad->dev = input_dev;
        usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
        strlcat(xpad->phys, "/input0", sizeof(xpad->phys));
@@ -662,11 +774,14 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 
        /* set up buttons */
-       for (i = 0; xpad_btn[i] >= 0; i++)
-               set_bit(xpad_btn[i], input_dev->keybit);
-       if (xpad->xtype == XTYPE_XBOX360)
+       for (i = 0; xpad_common_btn[i] >= 0; i++)
+               set_bit(xpad_common_btn[i], input_dev->keybit);
+       if ((xpad->xtype == XTYPE_XBOX360) || (xpad->xtype == XTYPE_XBOX360W))
                for (i = 0; xpad360_btn[i] >= 0; i++)
                        set_bit(xpad360_btn[i], input_dev->keybit);
+       else
+               for (i = 0; xpad_btn[i] >= 0; i++)
+                       set_bit(xpad_btn[i], input_dev->keybit);
        if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS)
                for (i = 0; xpad_btn_pad[i] >= 0; i++)
                        set_bit(xpad_btn_pad[i], input_dev->keybit);
@@ -703,8 +818,57 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
                goto fail4;
 
        usb_set_intfdata(intf, xpad);
+
+       /*
+        * Submit the int URB immediatly rather than waiting for open
+        * because we get status messages from the device whether
+        * or not any controllers are attached.  In fact, it's
+        * exactly the message that a controller has arrived that
+        * we're waiting for.
+        */
+       if (xpad->xtype == XTYPE_XBOX360W) {
+               xpad->irq_in->dev = xpad->udev;
+               error = usb_submit_urb(xpad->irq_in, GFP_KERNEL);
+               if (error)
+                       goto fail4;
+
+               /*
+                * Setup the message to set the LEDs on the
+                * controller when it shows up
+                */
+               xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL);
+               if(!xpad->bulk_out)
+                       goto fail5;
+
+               xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL);
+               if(!xpad->bdata)
+                       goto fail6;
+
+               xpad->bdata[2] = 0x08;
+               switch (intf->cur_altsetting->desc.bInterfaceNumber) {
+               case 0:
+                       xpad->bdata[3] = 0x42;
+                       break;
+               case 2:
+                       xpad->bdata[3] = 0x43;
+                       break;
+               case 4:
+                       xpad->bdata[3] = 0x44;
+                       break;
+               case 6:
+                       xpad->bdata[3] = 0x45;
+               }
+
+               ep_irq_in = &intf->cur_altsetting->endpoint[1].desc;
+               usb_fill_bulk_urb(xpad->bulk_out, udev,
+                               usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress),
+                               xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad);
+       }
+
        return 0;
 
+ fail6:        usb_free_urb(xpad->bulk_out);
+ fail5:        usb_kill_urb(xpad->irq_in);
  fail4:        usb_free_urb(xpad->irq_in);
  fail3:        xpad_deinit_output(xpad);
  fail2:        usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
@@ -723,6 +887,11 @@ static void xpad_disconnect(struct usb_interface *intf)
                xpad_led_disconnect(xpad);
                input_unregister_device(xpad->dev);
                xpad_deinit_output(xpad);
+               if (xpad->xtype == XTYPE_XBOX360W) {
+                       usb_kill_urb(xpad->bulk_out);
+                       usb_free_urb(xpad->bulk_out);
+                       usb_kill_urb(xpad->irq_in);
+               }
                usb_free_urb(xpad->irq_in);
                usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
                                xpad->idata, xpad->idata_dma);
@@ -741,7 +910,7 @@ static int __init usb_xpad_init(void)
 {
        int result = usb_register(&xpad_driver);
        if (result == 0)
-               info(DRIVER_DESC ":" DRIVER_VERSION);
+               info(DRIVER_DESC);
        return result;
 }
 
diff --git a/drivers/input/joystick/zhenhua.c b/drivers/input/joystick/zhenhua.c
new file mode 100644 (file)
index 0000000..b585312
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ *  derived from "twidjoy.c"
+ *
+ *  Copyright (c) 2008 Martin Kebert
+ *  Copyright (c) 2001 Arndt Schoenewald
+ *  Copyright (c) 2000-2001 Vojtech Pavlik
+ *  Copyright (c) 2000 Mark Fletcher
+ *
+ */
+
+/*
+ * Driver to use 4CH RC transmitter using Zhen Hua 5-byte protocol (Walkera Lama,
+ * EasyCopter etc.) as a joystick under Linux.
+ *
+ * RC transmitters using Zhen Hua 5-byte protocol are cheap four channels
+ * transmitters for control a RC planes or RC helicopters with possibility to
+ * connect on a serial port.
+ * Data coming from transmitter is in this order:
+ * 1. byte = synchronisation byte
+ * 2. byte = X axis
+ * 3. byte = Y axis
+ * 4. byte = RZ axis
+ * 5. byte = Z axis
+ * (and this is repeated)
+ *
+ * For questions or feedback regarding this driver module please contact:
+ * Martin Kebert <gkmarty@gmail.com> - but I am not a C-programmer nor kernel
+ * coder :-(
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+#define DRIVER_DESC    "RC transmitter with 5-byte Zhen Hua protocol joystick driver"
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/*
+ * Constants.
+ */
+
+#define ZHENHUA_MAX_LENGTH 5
+
+/*
+ * Zhen Hua data.
+ */
+
+struct zhenhua {
+       struct input_dev *dev;
+       int idx;
+       unsigned char data[ZHENHUA_MAX_LENGTH];
+       char phys[32];
+};
+
+
+/* bits in all incoming bytes needs to be "reversed" */
+static int zhenhua_bitreverse(int x)
+{
+       x = ((x & 0xaa) >> 1) | ((x & 0x55) << 1);
+       x = ((x & 0xcc) >> 2) | ((x & 0x33) << 2);
+       x = ((x & 0xf0) >> 4) | ((x & 0x0f) << 4);
+       return x;
+}
+
+/*
+ * zhenhua_process_packet() decodes packets the driver receives from the
+ * RC transmitter. It updates the data accordingly.
+ */
+
+static void zhenhua_process_packet(struct zhenhua *zhenhua)
+{
+       struct input_dev *dev = zhenhua->dev;
+       unsigned char *data = zhenhua->data;
+
+       input_report_abs(dev, ABS_Y, data[1]);
+       input_report_abs(dev, ABS_X, data[2]);
+       input_report_abs(dev, ABS_RZ, data[3]);
+       input_report_abs(dev, ABS_Z, data[4]);
+
+       input_sync(dev);
+}
+
+/*
+ * zhenhua_interrupt() is called by the low level driver when characters
+ * are ready for us. We then buffer them for further processing, or call the
+ * packet processing routine.
+ */
+
+static irqreturn_t zhenhua_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
+{
+       struct zhenhua *zhenhua = serio_get_drvdata(serio);
+
+       /* All Zhen Hua packets are 5 bytes. The fact that the first byte
+        * is allways 0xf7 and all others are in range 0x32 - 0xc8 (50-200)
+        * can be used to check and regain sync. */
+
+       if (data == 0xef)
+               zhenhua->idx = 0;       /* this byte starts a new packet */
+       else if (zhenhua->idx == 0)
+               return IRQ_HANDLED;     /* wrong MSB -- ignore this byte */
+
+       if (zhenhua->idx < ZHENHUA_MAX_LENGTH)
+               zhenhua->data[zhenhua->idx++] = zhenhua_bitreverse(data);
+
+       if (zhenhua->idx == ZHENHUA_MAX_LENGTH) {
+               zhenhua_process_packet(zhenhua);
+               zhenhua->idx = 0;
+       }
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * zhenhua_disconnect() is the opposite of zhenhua_connect()
+ */
+
+static void zhenhua_disconnect(struct serio *serio)
+{
+       struct zhenhua *zhenhua = serio_get_drvdata(serio);
+
+       serio_close(serio);
+       serio_set_drvdata(serio, NULL);
+       input_unregister_device(zhenhua->dev);
+       kfree(zhenhua);
+}
+
+/*
+ * zhenhua_connect() is the routine that is called when someone adds a
+ * new serio device. It looks for the Twiddler, and if found, registers
+ * it as an input device.
+ */
+
+static int zhenhua_connect(struct serio *serio, struct serio_driver *drv)
+{
+       struct zhenhua *zhenhua;
+       struct input_dev *input_dev;
+       int err = -ENOMEM;
+
+       zhenhua = kzalloc(sizeof(struct zhenhua), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!zhenhua || !input_dev)
+               goto fail1;
+
+       zhenhua->dev = input_dev;
+       snprintf(zhenhua->phys, sizeof(zhenhua->phys), "%s/input0", serio->phys);
+
+       input_dev->name = "Zhen Hua 5-byte device";
+       input_dev->phys = zhenhua->phys;
+       input_dev->id.bustype = BUS_RS232;
+       input_dev->id.vendor = SERIO_ZHENHUA;
+       input_dev->id.product = 0x0001;
+       input_dev->id.version = 0x0100;
+       input_dev->dev.parent = &serio->dev;
+
+       input_dev->evbit[0] = BIT(EV_ABS);
+       input_set_abs_params(input_dev, ABS_X, 50, 200, 0, 0);
+       input_set_abs_params(input_dev, ABS_Y, 50, 200, 0, 0);
+       input_set_abs_params(input_dev, ABS_Z, 50, 200, 0, 0);
+       input_set_abs_params(input_dev, ABS_RZ, 50, 200, 0, 0);
+
+       serio_set_drvdata(serio, zhenhua);
+
+       err = serio_open(serio, drv);
+       if (err)
+               goto fail2;
+
+       err = input_register_device(zhenhua->dev);
+       if (err)
+               goto fail3;
+
+       return 0;
+
+ fail3:        serio_close(serio);
+ fail2:        serio_set_drvdata(serio, NULL);
+ fail1:        input_free_device(input_dev);
+       kfree(zhenhua);
+       return err;
+}
+
+/*
+ * The serio driver structure.
+ */
+
+static struct serio_device_id zhenhua_serio_ids[] = {
+       {
+               .type   = SERIO_RS232,
+               .proto  = SERIO_ZHENHUA,
+               .id     = SERIO_ANY,
+               .extra  = SERIO_ANY,
+       },
+       { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, zhenhua_serio_ids);
+
+static struct serio_driver zhenhua_drv = {
+       .driver         = {
+               .name   = "zhenhua",
+       },
+       .description    = DRIVER_DESC,
+       .id_table       = zhenhua_serio_ids,
+       .interrupt      = zhenhua_interrupt,
+       .connect        = zhenhua_connect,
+       .disconnect     = zhenhua_disconnect,
+};
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+static int __init zhenhua_init(void)
+{
+       return serio_register_driver(&zhenhua_drv);
+}
+
+static void __exit zhenhua_exit(void)
+{
+       serio_unregister_driver(&zhenhua_drv);
+}
+
+module_init(zhenhua_init);
+module_exit(zhenhua_exit);
index 72abc196ce66580000b25e0800e5b4908fc03383..a293e8b3f508a4ef2303bbe5a03391bc8a3694e2 100644 (file)
@@ -156,11 +156,15 @@ static int __devexit aaedkbd_remove(struct platform_device *pdev)
        return 0;
 }
 
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:aaed2000-keyboard");
+
 static struct platform_driver aaedkbd_driver = {
        .probe          = aaedkbd_probe,
        .remove         = __devexit_p(aaedkbd_remove),
        .driver         = {
                .name   = "aaed2000-keyboard",
+               .owner  = THIS_MODULE,
        },
 };
 
index 05e3494cf8b87f4bb80fc9b904cda36099e6b6e5..54ed8e2e1c021c540f2c06adaef5ae009f3d056b 100644 (file)
@@ -312,6 +312,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev)
 
        bfin_write_KPAD_CTL(bfin_read_KPAD_CTL() | KPAD_EN);
 
+       device_init_wakeup(&pdev->dev, 1);
+
        printk(KERN_ERR DRV_NAME
                ": Blackfin BF54x Keypad registered IRQ %d\n", bf54x_kpad->irq);
 
@@ -354,12 +356,40 @@ static int __devexit bfin_kpad_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int bfin_kpad_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
+
+       if (device_may_wakeup(&pdev->dev))
+               enable_irq_wake(bf54x_kpad->irq);
+
+       return 0;
+}
+
+static int bfin_kpad_resume(struct platform_device *pdev)
+{
+       struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
+
+       if (device_may_wakeup(&pdev->dev))
+               disable_irq_wake(bf54x_kpad->irq);
+
+       return 0;
+}
+#else
+# define bfin_kpad_suspend NULL
+# define bfin_kpad_resume  NULL
+#endif
+
 struct platform_driver bfin_kpad_device_driver = {
-       .probe          = bfin_kpad_probe,
-       .remove         = __devexit_p(bfin_kpad_remove),
        .driver         = {
                .name   = DRV_NAME,
-       }
+               .owner  = THIS_MODULE,
+       },
+       .probe          = bfin_kpad_probe,
+       .remove         = __devexit_p(bfin_kpad_remove),
+       .suspend        = bfin_kpad_suspend,
+       .resume         = bfin_kpad_resume,
 };
 
 static int __init bfin_kpad_init(void)
@@ -378,3 +408,4 @@ module_exit(bfin_kpad_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 MODULE_DESCRIPTION("Keypad driver for BF54x Processors");
+MODULE_ALIAS("platform:bf54x-keys");
index 5d6cc7f1dc947d74c9de6a955080fb388c087c6d..29fbec6218b92cfc12f70c5e19a9df03dc301e7c 100644 (file)
@@ -393,6 +393,7 @@ static struct platform_driver corgikbd_driver = {
        .resume         = corgikbd_resume,
        .driver         = {
                .name   = "corgi-keyboard",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -412,3 +413,4 @@ module_exit(corgikbd_exit);
 MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
 MODULE_DESCRIPTION("Corgi Keyboard Driver");
 MODULE_LICENSE("GPLv2");
+MODULE_ALIAS("platform:corgi-keyboard");
index 6a9ca4bdcb74acfa1dd9abc5bfec06bd2abeda62..bbd00c3fe98ca18999b19c011a8c0040f3e9fb9b 100644 (file)
@@ -43,10 +43,11 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
 
                        input_event(input, type, button->code, !!state);
                        input_sync(input);
+                       return IRQ_HANDLED;
                }
        }
 
-       return IRQ_HANDLED;
+       return IRQ_NONE;
 }
 
 static int __devinit gpio_keys_probe(struct platform_device *pdev)
@@ -213,6 +214,7 @@ struct platform_driver gpio_keys_device_driver = {
        .resume         = gpio_keys_resume,
        .driver         = {
                .name   = "gpio-keys",
+               .owner  = THIS_MODULE,
        }
 };
 
@@ -232,3 +234,4 @@ module_exit(gpio_keys_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>");
 MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
+MODULE_ALIAS("platform:gpio-keys");
index a23633a2e1b46654979633556ef8564d1e160aa3..9387da343f9753edce0133f2d33436d9d1ddf663 100644 (file)
@@ -254,6 +254,7 @@ static int __devexit jornada680kbd_remove(struct platform_device *pdev)
 static struct platform_driver jornada680kbd_driver = {
        .driver = {
                .name   = "jornada680_kbd",
+               .owner  = THIS_MODULE,
        },
        .probe  = jornada680kbd_probe,
        .remove = __devexit_p(jornada680kbd_remove),
@@ -275,3 +276,4 @@ module_exit(jornada680kbd_exit);
 MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
 MODULE_DESCRIPTION("HP Jornada 620/660/680/690 Keyboard Driver");
 MODULE_LICENSE("GPLv2");
+MODULE_ALIAS("platform:jornada680_kbd");
index 986f93cfc6b8a0211020e8978f374c9c29b272d2..a1164a0c7736c4b557daa942bd3014e2861c8dc2 100644 (file)
@@ -162,9 +162,13 @@ static int __devexit jornada720_kbd_remove(struct platform_device *pdev)
        return 0;
 }
 
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:jornada720_kbd");
+
 static struct platform_driver jornada720_kbd_driver = {
        .driver  = {
                .name    = "jornada720_kbd",
+               .owner  = THIS_MODULE,
         },
        .probe   = jornada720_kbd_probe,
        .remove  = __devexit_p(jornada720_kbd_remove),
index 5a0ca18d6755827b77d776af407364b1a8b2d30d..9caed30f3bbba29203377d45e61e633a21cfec7f 100644 (file)
@@ -1,14 +1,12 @@
 /*
- *  Copyright (c) 2005 John Lenz
+ * LoCoMo keyboard driver for Linux-based ARM PDAs:
+ *     - SHARP Zaurus Collie (SL-5500)
+ *     - SHARP Zaurus Poodle (SL-5600)
  *
+ * Copyright (c) 2005 John Lenz
  * Based on from xtkbd.c
- */
-
-/*
- * LoCoMo keyboard driver for Linux/ARM
- */
-
-/*
+ *
+ *
  * This 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
@@ -47,7 +45,8 @@ MODULE_LICENSE("GPL");
 #define KEY_CONTACT            KEY_F18
 #define KEY_CENTER             KEY_F15
 
-static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
+static const unsigned char
+locomokbd_keycode[LOCOMOKBD_NUMKEYS] __devinitconst = {
        0, KEY_ESC, KEY_ACTIVITY, 0, 0, 0, 0, 0, 0, 0,                          /* 0 - 9 */
        0, 0, 0, 0, 0, 0, 0, KEY_MENU, KEY_HOME, KEY_CONTACT,                   /* 10 - 19 */
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                                           /* 20 - 29 */
@@ -67,22 +66,21 @@ static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
 #define KB_COLS                        8
 #define KB_ROWMASK(r)          (1 << (r))
 #define SCANCODE(c,r)          ( ((c)<<4) + (r) + 1 )
-#define        NR_SCANCODES            128
 
 #define KB_DELAY               8
 #define SCAN_INTERVAL          (HZ/10)
-#define LOCOMOKBD_PRESSED      1
 
 struct locomokbd {
        unsigned char keycode[LOCOMOKBD_NUMKEYS];
        struct input_dev *input;
        char phys[32];
 
-       struct locomo_dev *ldev;
        unsigned long base;
        spinlock_t lock;
 
        struct timer_list timer;
+       unsigned long suspend_jiffies;
+       unsigned int count_cancel;
 };
 
 /* helper functions for reading the keyboard matrix */
@@ -128,7 +126,7 @@ static inline void locomokbd_reset_col(unsigned long membase, int col)
 /* Scan the hardware keyboard and push any changes up through the input layer */
 static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
 {
-       unsigned int row, col, rowd, scancode;
+       unsigned int row, col, rowd;
        unsigned long flags;
        unsigned int num_pressed;
        unsigned long membase = locomokbd->base;
@@ -145,13 +143,33 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
 
                rowd = ~locomo_readl(membase + LOCOMO_KIB);
                for (row = 0; row < KB_ROWS; row++) {
+                       unsigned int scancode, pressed, key;
+
                        scancode = SCANCODE(col, row);
-                       if (rowd & KB_ROWMASK(row)) {
-                               num_pressed += 1;
-                               input_report_key(locomokbd->input, locomokbd->keycode[scancode], 1);
-                       } else {
-                               input_report_key(locomokbd->input, locomokbd->keycode[scancode], 0);
-                       }
+                       pressed = rowd & KB_ROWMASK(row);
+                       key = locomokbd->keycode[scancode];
+
+                       input_report_key(locomokbd->input, key, pressed);
+                       if (likely(!pressed))
+                               continue;
+
+                       num_pressed++;
+
+                       /* The "Cancel/ESC" key is labeled "On/Off" on
+                        * Collie and Poodle and should suspend the device
+                        * if it was pressed for more than a second. */
+                       if (unlikely(key == KEY_ESC)) {
+                               if (!time_after(jiffies,
+                                       locomokbd->suspend_jiffies + HZ))
+                                       continue;
+                               if (locomokbd->count_cancel++
+                                       != (HZ/SCAN_INTERVAL + 1))
+                                       continue;
+                               input_event(locomokbd->input, EV_PWR,
+                                       KEY_SUSPEND, 1);
+                               locomokbd->suspend_jiffies = jiffies;
+                       } else
+                               locomokbd->count_cancel = 0;
                }
                locomokbd_reset_col(membase, col);
        }
@@ -162,6 +180,8 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
        /* if any keys are pressed, enable the timer */
        if (num_pressed)
                mod_timer(&locomokbd->timer, jiffies + SCAN_INTERVAL);
+       else
+               locomokbd->count_cancel = 0;
 
        spin_unlock_irqrestore(&locomokbd->lock, flags);
 }
@@ -186,10 +206,11 @@ static irqreturn_t locomokbd_interrupt(int irq, void *dev_id)
 static void locomokbd_timer_callback(unsigned long data)
 {
        struct locomokbd *locomokbd = (struct locomokbd *) data;
+
        locomokbd_scankeyboard(locomokbd);
 }
 
-static int locomokbd_probe(struct locomo_dev *dev)
+static int __devinit locomokbd_probe(struct locomo_dev *dev)
 {
        struct locomokbd *locomokbd;
        struct input_dev *input_dev;
@@ -211,7 +232,6 @@ static int locomokbd_probe(struct locomo_dev *dev)
                goto err_free_mem;
        }
 
-       locomokbd->ldev = dev;
        locomo_set_drvdata(dev, locomokbd);
 
        locomokbd->base = (unsigned long) dev->mapbase;
@@ -222,6 +242,8 @@ static int locomokbd_probe(struct locomo_dev *dev)
        locomokbd->timer.function = locomokbd_timer_callback;
        locomokbd->timer.data = (unsigned long) locomokbd;
 
+       locomokbd->suspend_jiffies = jiffies;
+
        locomokbd->input = input_dev;
        strcpy(locomokbd->phys, "locomokbd/input0");
 
@@ -233,9 +255,10 @@ static int locomokbd_probe(struct locomo_dev *dev)
        input_dev->id.version = 0x0100;
        input_dev->dev.parent = &dev->dev;
 
-       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
+       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
+                               BIT_MASK(EV_PWR);
        input_dev->keycode = locomokbd->keycode;
-       input_dev->keycodesize = sizeof(unsigned char);
+       input_dev->keycodesize = sizeof(locomokbd_keycode[0]);
        input_dev->keycodemax = ARRAY_SIZE(locomokbd_keycode);
 
        memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode));
@@ -268,7 +291,7 @@ static int locomokbd_probe(struct locomo_dev *dev)
        return err;
 }
 
-static int locomokbd_remove(struct locomo_dev *dev)
+static int __devexit locomokbd_remove(struct locomo_dev *dev)
 {
        struct locomokbd *locomokbd = locomo_get_drvdata(dev);
 
@@ -292,7 +315,7 @@ static struct locomo_driver keyboard_driver = {
        },
        .devid  = LOCOMO_DEVID_KEYBOARD,
        .probe  = locomokbd_probe,
-       .remove = locomokbd_remove,
+       .remove = __devexit_p(locomokbd_remove),
 };
 
 static int __init locomokbd_init(void)
index babc913d5492b617b388ee3eb7781ce0facd535e..10afd2068068aa35fe5ae1f84d0f034cf746e625 100644 (file)
@@ -352,6 +352,9 @@ static int __init omap_kp_probe(struct platform_device *pdev)
                        }
                        omap_set_gpio_direction(row_gpios[row_idx], 1);
                }
+       } else {
+               col_idx = 0;
+               row_idx = 0;
        }
 
        setup_timer(&omap_kp->timer, omap_kp_timer, (unsigned long)omap_kp);
@@ -415,10 +418,10 @@ err4:
 err3:
        device_remove_file(&pdev->dev, &dev_attr_enable);
 err2:
-       for (i = row_idx-1; i >=0; i--)
+       for (i = row_idx - 1; i >=0; i--)
                omap_free_gpio(row_gpios[i]);
 err1:
-       for (i = col_idx-1; i >=0; i--)
+       for (i = col_idx - 1; i >=0; i--)
                omap_free_gpio(col_gpios[i]);
 
        kfree(omap_kp);
@@ -464,6 +467,7 @@ static struct platform_driver omap_kp_driver = {
        .resume         = omap_kp_resume,
        .driver         = {
                .name   = "omap-keypad",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -484,3 +488,4 @@ module_exit(omap_kp_exit);
 MODULE_AUTHOR("Timo Teräs");
 MODULE_DESCRIPTION("OMAP Keypad Driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:omap-keypad");
index 4e651c11c1dad71c64fe033381447cb31212f079..3dea0c5077a9ad623b35dfb7a5c627f6da5a5d28 100644 (file)
@@ -545,6 +545,9 @@ static int __devexit pxa27x_keypad_remove(struct platform_device *pdev)
        return 0;
 }
 
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:pxa27x-keypad");
+
 static struct platform_driver pxa27x_keypad_driver = {
        .probe          = pxa27x_keypad_probe,
        .remove         = __devexit_p(pxa27x_keypad_remove),
@@ -552,6 +555,7 @@ static struct platform_driver pxa27x_keypad_driver = {
        .resume         = pxa27x_keypad_resume,
        .driver         = {
                .name   = "pxa27x-keypad",
+               .owner  = THIS_MODULE,
        },
 };
 
index 0be74bfc58fe0ae084f6f7ec1e88a38eeabf0554..61e401bc91099abe18d200d9af486aac8a7706a8 100644 (file)
@@ -495,3 +495,4 @@ module_exit(spitzkbd_exit);
 MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
 MODULE_DESCRIPTION("Spitz Keyboard Driver");
 MODULE_LICENSE("GPLv2");
+MODULE_ALIAS("platform:spitz-keyboard");
index 3884d1e3f070f33a74c68da0f13f27d94aa4cb53..94e444b4ee1523c4539b687383eaa9c35a52fcfe 100644 (file)
@@ -52,7 +52,7 @@ KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_
 struct tosakbd {
        unsigned int keycode[ARRAY_SIZE(tosakbd_keycode)];
        struct input_dev *input;
-
+       int suspended;
        spinlock_t lock; /* protect kbd scanning */
        struct timer_list timer;
 };
@@ -133,6 +133,9 @@ static void tosakbd_scankeyboard(struct platform_device *dev)
 
        spin_lock_irqsave(&tosakbd->lock, flags);
 
+       if (tosakbd->suspended)
+               goto out;
+
        for (col = 0; col < TOSA_KEY_STROBE_NUM; col++) {
                /*
                 * Discharge the output driver capacitatance
@@ -174,6 +177,7 @@ static void tosakbd_scankeyboard(struct platform_device *dev)
        if (num_pressed)
                mod_timer(&tosakbd->timer, jiffies + SCAN_INTERVAL);
 
+ out:
        spin_unlock_irqrestore(&tosakbd->lock, flags);
 }
 
@@ -200,6 +204,7 @@ static irqreturn_t tosakbd_interrupt(int irq, void *__dev)
 static void tosakbd_timer_callback(unsigned long __dev)
 {
        struct platform_device *dev = (struct platform_device *)__dev;
+
        tosakbd_scankeyboard(dev);
 }
 
@@ -207,6 +212,13 @@ static void tosakbd_timer_callback(unsigned long __dev)
 static int tosakbd_suspend(struct platform_device *dev, pm_message_t state)
 {
        struct tosakbd *tosakbd = platform_get_drvdata(dev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&tosakbd->lock, flags);
+       PGSR1 = (PGSR1 & ~TOSA_GPIO_LOW_STROBE_BIT);
+       PGSR2 = (PGSR2 & ~TOSA_GPIO_HIGH_STROBE_BIT);
+       tosakbd->suspended = 1;
+       spin_unlock_irqrestore(&tosakbd->lock, flags);
 
        del_timer_sync(&tosakbd->timer);
 
@@ -215,6 +227,9 @@ static int tosakbd_suspend(struct platform_device *dev, pm_message_t state)
 
 static int tosakbd_resume(struct platform_device *dev)
 {
+       struct tosakbd *tosakbd = platform_get_drvdata(dev);
+
+       tosakbd->suspended = 0;
        tosakbd_scankeyboard(dev);
 
        return 0;
@@ -365,8 +380,8 @@ fail:
        return error;
 }
 
-static int __devexit tosakbd_remove(struct platform_device *dev) {
-
+static int __devexit tosakbd_remove(struct platform_device *dev)
+{
        int i;
        struct tosakbd *tosakbd = platform_get_drvdata(dev);
 
@@ -394,6 +409,7 @@ static struct platform_driver tosakbd_driver = {
        .resume         = tosakbd_resume,
        .driver         = {
                .name   = "tosa-keyboard",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -413,3 +429,4 @@ module_exit(tosakbd_exit);
 MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>");
 MODULE_DESCRIPTION("Tosa Keyboard Driver");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:tosa-keyboard");
index 5511ef006a66c591cf59df2ffde421001f282758..6a1f48b76e3298649130c8d341123bcbf2e0f131 100644 (file)
@@ -148,6 +148,9 @@ static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
        return 0;
 }
 
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:Cobalt buttons");
+
 static struct platform_driver cobalt_buttons_driver = {
        .probe  = cobalt_buttons_probe,
        .remove = __devexit_p(cobalt_buttons_remove),
index 0936d6ba015c5a1221ee1021e7f6844670944dc4..3392901848711f4f5053b4d042387ce5d69a2611 100644 (file)
@@ -171,10 +171,14 @@ static int __devexit gpio_mouse_remove(struct platform_device *pdev)
        return 0;
 }
 
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:gpio_mouse");
+
 struct platform_driver gpio_mouse_device_driver = {
        .remove         = __devexit_p(gpio_mouse_remove),
        .driver         = {
                .name   = "gpio_mouse",
+               .owner  = THIS_MODULE,
        }
 };
 
index b88569e21d60e017625a073e44c765601d8e1017..ec4b6610f730ea7d18a1e5e924201be4ac0a1123 100644 (file)
@@ -88,6 +88,16 @@ config SERIO_RPCKBD
          To compile this driver as a module, choose M here: the
          module will be called rpckbd.
 
+config SERIO_AT32PSIF
+       tristate "AVR32 PSIF PS/2 keyboard and mouse controller"
+       depends on AVR32
+       help
+         Say Y here if you want to use the PSIF peripheral on AVR32 devices
+         and connect a PS/2 keyboard and/or mouse to it.
+
+         To compile this driver as a module, choose M here: the module will
+         be called at32psif.
+
 config SERIO_AMBAKMI
        tristate "AMBA KMI keyboard controller"
        depends on ARM_AMBA
index 4155197867a33be98b0f106cff9eb243c2e98440..38b886887cbc2459aeae5d76c850b3031780061b 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_SERIO_CT82C710)  += ct82c710.o
 obj-$(CONFIG_SERIO_RPCKBD)     += rpckbd.o
 obj-$(CONFIG_SERIO_SA1111)     += sa1111ps2.o
 obj-$(CONFIG_SERIO_AMBAKMI)    += ambakmi.o
+obj-$(CONFIG_SERIO_AT32PSIF)   += at32psif.o
 obj-$(CONFIG_SERIO_Q40KBD)     += q40kbd.o
 obj-$(CONFIG_SERIO_GSCPS2)     += gscps2.o
 obj-$(CONFIG_HP_SDC)           += hp_sdc.o
diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c
new file mode 100644 (file)
index 0000000..41fda8c
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * Driver for the AT32AP700X PS/2 controller (PSIF).
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/serio.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+/* PSIF register offsets */
+#define PSIF_CR                                0x00
+#define PSIF_RHR                       0x04
+#define PSIF_THR                       0x08
+#define PSIF_SR                                0x10
+#define PSIF_IER                       0x14
+#define PSIF_IDR                       0x18
+#define PSIF_IMR                       0x1c
+#define PSIF_PSR                       0x24
+
+/* Bitfields in control register. */
+#define PSIF_CR_RXDIS_OFFSET           1
+#define PSIF_CR_RXDIS_SIZE             1
+#define PSIF_CR_RXEN_OFFSET            0
+#define PSIF_CR_RXEN_SIZE              1
+#define PSIF_CR_SWRST_OFFSET           15
+#define PSIF_CR_SWRST_SIZE             1
+#define PSIF_CR_TXDIS_OFFSET           9
+#define PSIF_CR_TXDIS_SIZE             1
+#define PSIF_CR_TXEN_OFFSET            8
+#define PSIF_CR_TXEN_SIZE              1
+
+/* Bitfields in interrupt disable, enable, mask and status register. */
+#define PSIF_NACK_OFFSET               8
+#define PSIF_NACK_SIZE                 1
+#define PSIF_OVRUN_OFFSET              5
+#define PSIF_OVRUN_SIZE                        1
+#define PSIF_PARITY_OFFSET             9
+#define PSIF_PARITY_SIZE               1
+#define PSIF_RXRDY_OFFSET              4
+#define PSIF_RXRDY_SIZE                        1
+#define PSIF_TXEMPTY_OFFSET            1
+#define PSIF_TXEMPTY_SIZE              1
+#define PSIF_TXRDY_OFFSET              0
+#define PSIF_TXRDY_SIZE                        1
+
+/* Bitfields in prescale register. */
+#define PSIF_PSR_PRSCV_OFFSET          0
+#define PSIF_PSR_PRSCV_SIZE            12
+
+/* Bitfields in receive hold register. */
+#define PSIF_RHR_RXDATA_OFFSET         0
+#define PSIF_RHR_RXDATA_SIZE           8
+
+/* Bitfields in transmit hold register. */
+#define PSIF_THR_TXDATA_OFFSET         0
+#define PSIF_THR_TXDATA_SIZE           8
+
+/* Bit manipulation macros */
+#define PSIF_BIT(name)                                 \
+       (1 << PSIF_##name##_OFFSET)
+
+#define PSIF_BF(name, value)                           \
+       (((value) & ((1 << PSIF_##name##_SIZE) - 1))    \
+        << PSIF_##name##_OFFSET)
+
+#define PSIF_BFEXT(name, value)                                \
+       (((value) >> PSIF_##name##_OFFSET)              \
+        & ((1 << PSIF_##name##_SIZE) - 1))
+
+#define PSIF_BFINS(name, value, old)                   \
+       (((old) & ~(((1 << PSIF_##name##_SIZE) - 1)     \
+                   << PSIF_##name##_OFFSET))           \
+        | PSIF_BF(name, value))
+
+/* Register access macros */
+#define psif_readl(port, reg)                          \
+       __raw_readl((port)->regs + PSIF_##reg)
+
+#define psif_writel(port, reg, value)                  \
+       __raw_writel((value), (port)->regs + PSIF_##reg)
+
+struct psif {
+       struct platform_device  *pdev;
+       struct clk              *pclk;
+       struct serio            *io;
+       void __iomem            *regs;
+       unsigned int            irq;
+       unsigned int            open;
+       /* Prevent concurrent writes to PSIF THR. */
+       spinlock_t              lock;
+};
+
+static irqreturn_t psif_interrupt(int irq, void *_ptr)
+{
+       struct psif *psif = _ptr;
+       int retval = IRQ_NONE;
+       unsigned int io_flags = 0;
+       unsigned long status;
+
+       status = psif_readl(psif, SR);
+
+       if (status & PSIF_BIT(RXRDY)) {
+               unsigned char val = (unsigned char) psif_readl(psif, RHR);
+
+               if (status & PSIF_BIT(PARITY))
+                       io_flags |= SERIO_PARITY;
+               if (status & PSIF_BIT(OVRUN))
+                       dev_err(&psif->pdev->dev, "overrun read error\n");
+
+               serio_interrupt(psif->io, val, io_flags);
+
+               retval = IRQ_HANDLED;
+       }
+
+       return retval;
+}
+
+static int psif_write(struct serio *io, unsigned char val)
+{
+       struct psif *psif = io->port_data;
+       unsigned long flags;
+       int timeout = 10;
+       int retval = 0;
+
+       spin_lock_irqsave(&psif->lock, flags);
+
+       while (!(psif_readl(psif, SR) & PSIF_BIT(TXEMPTY)) && timeout--)
+               msleep(10);
+
+       if (timeout >= 0) {
+               psif_writel(psif, THR, val);
+       } else {
+               dev_dbg(&psif->pdev->dev, "timeout writing to THR\n");
+               retval = -EBUSY;
+       }
+
+       spin_unlock_irqrestore(&psif->lock, flags);
+
+       return retval;
+}
+
+static int psif_open(struct serio *io)
+{
+       struct psif *psif = io->port_data;
+       int retval;
+
+       retval = clk_enable(psif->pclk);
+       if (retval)
+               goto out;
+
+       psif_writel(psif, CR, PSIF_BIT(CR_TXEN) | PSIF_BIT(CR_RXEN));
+       psif_writel(psif, IER, PSIF_BIT(RXRDY));
+
+       psif->open = 1;
+out:
+       return retval;
+}
+
+static void psif_close(struct serio *io)
+{
+       struct psif *psif = io->port_data;
+
+       psif->open = 0;
+
+       psif_writel(psif, IDR, ~0UL);
+       psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS));
+
+       clk_disable(psif->pclk);
+}
+
+static void psif_set_prescaler(struct psif *psif)
+{
+       unsigned long prscv;
+       unsigned long rate = clk_get_rate(psif->pclk);
+
+       /* PRSCV = Pulse length (100 us) * PSIF module frequency. */
+       prscv = 100 * (rate / 1000000UL);
+
+       if (prscv > ((1<<PSIF_PSR_PRSCV_SIZE) - 1)) {
+               prscv = (1<<PSIF_PSR_PRSCV_SIZE) - 1;
+               dev_dbg(&psif->pdev->dev, "pclk too fast, "
+                               "prescaler set to max\n");
+       }
+
+       clk_enable(psif->pclk);
+       psif_writel(psif, PSR, prscv);
+       clk_disable(psif->pclk);
+}
+
+static int __init psif_probe(struct platform_device *pdev)
+{
+       struct resource *regs;
+       struct psif *psif;
+       struct serio *io;
+       struct clk *pclk;
+       int irq;
+       int ret;
+
+       psif = kzalloc(sizeof(struct psif), GFP_KERNEL);
+       if (!psif) {
+               dev_dbg(&pdev->dev, "out of memory\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+       psif->pdev = pdev;
+
+       io = kzalloc(sizeof(struct serio), GFP_KERNEL);
+       if (!io) {
+               dev_dbg(&pdev->dev, "out of memory\n");
+               ret = -ENOMEM;
+               goto out_free_psif;
+       }
+       psif->io = io;
+
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!regs) {
+               dev_dbg(&pdev->dev, "no mmio resources defined\n");
+               ret = -ENOMEM;
+               goto out_free_io;
+       }
+
+       psif->regs = ioremap(regs->start, regs->end - regs->start + 1);
+       if (!psif->regs) {
+               ret = -ENOMEM;
+               dev_dbg(&pdev->dev, "could not map I/O memory\n");
+               goto out_free_io;
+       }
+
+       pclk = clk_get(&pdev->dev, "pclk");
+       if (IS_ERR(pclk)) {
+               dev_dbg(&pdev->dev, "could not get peripheral clock\n");
+               ret = PTR_ERR(pclk);
+               goto out_iounmap;
+       }
+       psif->pclk = pclk;
+
+       /* Reset the PSIF to enter at a known state. */
+       ret = clk_enable(pclk);
+       if (ret) {
+               dev_dbg(&pdev->dev, "could not enable pclk\n");
+               goto out_put_clk;
+       }
+       psif_writel(psif, CR, PSIF_BIT(CR_SWRST));
+       clk_disable(pclk);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_dbg(&pdev->dev, "could not get irq\n");
+               ret = -ENXIO;
+               goto out_put_clk;
+       }
+       ret = request_irq(irq, psif_interrupt, IRQF_SHARED, "at32psif", psif);
+       if (ret) {
+               dev_dbg(&pdev->dev, "could not request irq %d\n", irq);
+               goto out_put_clk;
+       }
+       psif->irq = irq;
+
+       io->id.type     = SERIO_8042;
+       io->write       = psif_write;
+       io->open        = psif_open;
+       io->close       = psif_close;
+       snprintf(io->name, sizeof(io->name), "AVR32 PS/2 port%d", pdev->id);
+       snprintf(io->phys, sizeof(io->phys), "at32psif/serio%d", pdev->id);
+       io->port_data   = psif;
+       io->dev.parent  = &pdev->dev;
+
+       psif_set_prescaler(psif);
+
+       spin_lock_init(&psif->lock);
+       serio_register_port(psif->io);
+       platform_set_drvdata(pdev, psif);
+
+       dev_info(&pdev->dev, "Atmel AVR32 PSIF PS/2 driver on 0x%08x irq %d\n",
+                       (int)psif->regs, psif->irq);
+
+       return 0;
+
+out_put_clk:
+       clk_put(psif->pclk);
+out_iounmap:
+       iounmap(psif->regs);
+out_free_io:
+       kfree(io);
+out_free_psif:
+       kfree(psif);
+out:
+       return ret;
+}
+
+static int __exit psif_remove(struct platform_device *pdev)
+{
+       struct psif *psif = platform_get_drvdata(pdev);
+
+       psif_writel(psif, IDR, ~0UL);
+       psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS));
+
+       serio_unregister_port(psif->io);
+       iounmap(psif->regs);
+       free_irq(psif->irq, psif);
+       clk_put(psif->pclk);
+       kfree(psif);
+
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int psif_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct psif *psif = platform_get_drvdata(pdev);
+
+       if (psif->open) {
+               psif_writel(psif, CR, PSIF_BIT(CR_RXDIS) | PSIF_BIT(CR_TXDIS));
+               clk_disable(psif->pclk);
+       }
+
+       return 0;
+}
+
+static int psif_resume(struct platform_device *pdev)
+{
+       struct psif *psif = platform_get_drvdata(pdev);
+
+       if (psif->open) {
+               clk_enable(psif->pclk);
+               psif_set_prescaler(psif);
+               psif_writel(psif, CR, PSIF_BIT(CR_RXEN) | PSIF_BIT(CR_TXEN));
+       }
+
+       return 0;
+}
+#else
+#define psif_suspend   NULL
+#define psif_resume    NULL
+#endif
+
+static struct platform_driver psif_driver = {
+       .remove         = __exit_p(psif_remove),
+       .driver         = {
+               .name   = "atmel_psif",
+       },
+       .suspend        = psif_suspend,
+       .resume         = psif_resume,
+};
+
+static int __init psif_init(void)
+{
+       return platform_driver_probe(&psif_driver, psif_probe);
+}
+
+static void __exit psif_exit(void)
+{
+       platform_driver_unregister(&psif_driver);
+}
+
+module_init(psif_init);
+module_exit(psif_exit);
+
+MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>");
+MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver");
+MODULE_LICENSE("GPL");
index 60931aceb8282f42e217f1dd9eb2c451b2e55479..5ece9f56babc50ff1d0018e0dccec9832a19444a 100644 (file)
@@ -370,10 +370,10 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *
        if (pnp_irq_valid(dev,0))
                i8042_pnp_kbd_irq = pnp_irq(dev, 0);
 
-       strncpy(i8042_pnp_kbd_name, did->id, sizeof(i8042_pnp_kbd_name));
+       strlcpy(i8042_pnp_kbd_name, did->id, sizeof(i8042_pnp_kbd_name));
        if (strlen(pnp_dev_name(dev))) {
-               strncat(i8042_pnp_kbd_name, ":", sizeof(i8042_pnp_kbd_name));
-               strncat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
+               strlcat(i8042_pnp_kbd_name, ":", sizeof(i8042_pnp_kbd_name));
+               strlcat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
        }
 
        i8042_pnp_kbd_devices++;
@@ -391,10 +391,10 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *
        if (pnp_irq_valid(dev, 0))
                i8042_pnp_aux_irq = pnp_irq(dev, 0);
 
-       strncpy(i8042_pnp_aux_name, did->id, sizeof(i8042_pnp_aux_name));
+       strlcpy(i8042_pnp_aux_name, did->id, sizeof(i8042_pnp_aux_name));
        if (strlen(pnp_dev_name(dev))) {
-               strncat(i8042_pnp_aux_name, ":", sizeof(i8042_pnp_aux_name));
-               strncat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
+               strlcat(i8042_pnp_aux_name, ":", sizeof(i8042_pnp_aux_name));
+               strlcat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
        }
 
        i8042_pnp_aux_devices++;
index 49f84315cb32953ff7cee9066635800a9940a8b8..34c59d9c6205b47cb06f7fbfd77d7efe0e0bcf5a 100644 (file)
@@ -45,6 +45,7 @@
 MODULE_AUTHOR("Vojtech Pavlik, Russell King");
 MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:kart");
 
 static int rpckbd_write(struct serio *port, unsigned char val)
 {
@@ -140,6 +141,7 @@ static struct platform_driver rpckbd_driver = {
        .remove         = __devexit_p(rpckbd_remove),
        .driver         = {
                .name   = "kart",
+               .owner  = THIS_MODULE,
        },
 };
 
index d371c0bdc0bdbad09fd9e56e87f2526e5218f0ca..effb49ea24aa4c6ec337e14cfa4336e4fd153345 100644 (file)
@@ -25,14 +25,14 @@ config TABLET_USB_ACECAD
          module will be called acecad.
 
 config TABLET_USB_AIPTEK
-       tristate "Aiptek 6000U/8000U tablet support (USB)"
+       tristate "Aiptek 6000U/8000U and Genius G_PEN tablet support (USB)"
        depends on USB_ARCH_HAS_HCD
        select USB
        help
-         Say Y here if you want to use the USB version of the Aiptek 6000U
-         or Aiptek 8000U tablet.  Make sure to say Y to "Mouse support"
-         (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
-         (CONFIG_INPUT_EVDEV) as well.
+         Say Y here if you want to use the USB version of the Aiptek 6000U,
+         Aiptek 8000U or Genius G-PEN 560 tablet.  Make sure to say Y to
+         "Mouse support" (CONFIG_INPUT_MOUSEDEV) and/or "Event interface
+         support" (CONFIG_INPUT_EVDEV) as well.
 
          To compile this driver as a module, choose M here: the
          module will be called aiptek.
index 94683f58c9e18ec5b933d7721ab3b07467ae9a1c..1d759f6f807670479171b21bdc20da2d17a46072 100644 (file)
  */
 
 #define USB_VENDOR_ID_AIPTEK                           0x08ca
+#define USB_VENDOR_ID_KYE                              0x0458
 #define USB_REQ_GET_REPORT                             0x01
 #define USB_REQ_SET_REPORT                             0x09
 
@@ -832,6 +833,7 @@ static const struct usb_device_id aiptek_ids[] = {
        {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x22)},
        {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x23)},
        {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x24)},
+       {USB_DEVICE(USB_VENDOR_ID_KYE, 0x5003)},
        {}
 };
 
index acf9830698cb7ab3cadd94c077270bd49d12cff1..706619d06f71e6c596acb8419866ecca0146feb9 100644 (file)
@@ -101,8 +101,11 @@ struct wacom {
        dma_addr_t data_dma;
        struct input_dev *dev;
        struct usb_device *usbdev;
+       struct usb_interface *intf;
        struct urb *irq;
        struct wacom_wac * wacom_wac;
+       struct mutex lock;
+       int open:1;
        char phys[32];
 };
 
index 41caaef8e2d72c3a8e098086f9f0edbe44be48c8..71cc0c140790462f29b2e1513c38806bfa65d090 100644 (file)
@@ -70,6 +70,7 @@ static void wacom_sys_irq(struct urb *urb)
                input_sync(get_input_dev(&wcombo));
 
  exit:
+       usb_mark_last_busy(wacom->usbdev);
        retval = usb_submit_urb (urb, GFP_ATOMIC);
        if (retval)
                err ("%s - usb_submit_urb failed with result %d",
@@ -124,10 +125,25 @@ static int wacom_open(struct input_dev *dev)
 {
        struct wacom *wacom = input_get_drvdata(dev);
 
+       mutex_lock(&wacom->lock);
+
        wacom->irq->dev = wacom->usbdev;
-       if (usb_submit_urb(wacom->irq, GFP_KERNEL))
+
+       if (usb_autopm_get_interface(wacom->intf) < 0) {
+               mutex_unlock(&wacom->lock);
                return -EIO;
+       }
+
+       if (usb_submit_urb(wacom->irq, GFP_KERNEL)) {
+               usb_autopm_put_interface(wacom->intf);
+               mutex_unlock(&wacom->lock);
+               return -EIO;
+       }
+
+       wacom->open = 1;
+       wacom->intf->needs_remote_wakeup = 1;
 
+       mutex_unlock(&wacom->lock);
        return 0;
 }
 
@@ -135,7 +151,11 @@ static void wacom_close(struct input_dev *dev)
 {
        struct wacom *wacom = input_get_drvdata(dev);
 
+       mutex_lock(&wacom->lock);
        usb_kill_urb(wacom->irq);
+       wacom->open = 0;
+       wacom->intf->needs_remote_wakeup = 0;
+       mutex_unlock(&wacom->lock);
 }
 
 void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
@@ -243,6 +263,8 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
 
        wacom->usbdev = dev;
        wacom->dev = input_dev;
+       wacom->intf = intf;
+       mutex_init(&wacom->lock);
        usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
        strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
 
@@ -304,23 +326,57 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
 
 static void wacom_disconnect(struct usb_interface *intf)
 {
-       struct wacom *wacom = usb_get_intfdata (intf);
+       struct wacom *wacom = usb_get_intfdata(intf);
 
        usb_set_intfdata(intf, NULL);
-       if (wacom) {
-               usb_kill_urb(wacom->irq);
-               input_unregister_device(wacom->dev);
-               usb_free_urb(wacom->irq);
-               usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma);
-               kfree(wacom->wacom_wac);
-               kfree(wacom);
-       }
+
+       usb_kill_urb(wacom->irq);
+       input_unregister_device(wacom->dev);
+       usb_free_urb(wacom->irq);
+       usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma);
+       kfree(wacom->wacom_wac);
+       kfree(wacom);
+}
+
+static int wacom_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct wacom *wacom = usb_get_intfdata(intf);
+
+       mutex_lock(&wacom->lock);
+       usb_kill_urb(wacom->irq);
+       mutex_unlock(&wacom->lock);
+
+       return 0;
+}
+
+static int wacom_resume(struct usb_interface *intf)
+{
+       struct wacom *wacom = usb_get_intfdata(intf);
+       int rv;
+
+       mutex_lock(&wacom->lock);
+       if (wacom->open)
+               rv = usb_submit_urb(wacom->irq, GFP_NOIO);
+       else
+               rv = 0;
+       mutex_unlock(&wacom->lock);
+
+       return rv;
+}
+
+static int wacom_reset_resume(struct usb_interface *intf)
+{
+       return wacom_resume(intf);
 }
 
 static struct usb_driver wacom_driver = {
        .name =         "wacom",
        .probe =        wacom_probe,
        .disconnect =   wacom_disconnect,
+       .suspend =      wacom_suspend,
+       .resume =       wacom_resume,
+       .reset_resume = wacom_reset_resume,
+       .supports_autosuspend = 1,
 };
 
 static int __init wacom_init(void)
index ffe33842143f1178eff883568e51b19fc1eca136..192513e1f04cdc71529eeae8d75663e4866ab39b 100644 (file)
@@ -649,6 +649,7 @@ static struct wacom_features wacom_features[] = {
        { "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 63, INTUOS3 },
        { "Wacom Intuos3 4x6",   10, 31496, 19685, 1023, 63, INTUOS3S },
        { "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 63, CINTIQ },
+       { "Wacom Cintiq 20WSX",  10, 86680, 54180, 1023, 63, WACOM_BEE },
        { "Wacom Cintiq 12WX",   10, 53020, 33440, 1023, 63, WACOM_BEE },
        { "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS },
        { }
@@ -702,6 +703,7 @@ static struct usb_device_id wacom_ids[] = {
        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) },
        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) },
        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) },
        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) },
        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
        { }
index 90e8e92dfe4792ca662e60bb94cdf30c2ee62c0d..565ec711c2eefa6e5dc0f75dc4be5d1f6569a962 100644 (file)
@@ -185,6 +185,59 @@ config TOUCHSCREEN_UCB1400
          To compile this driver as a module, choose M here: the
          module will be called ucb1400_ts.
 
+config TOUCHSCREEN_WM97XX
+       tristate "Support for WM97xx AC97 touchscreen controllers"
+       depends on AC97_BUS
+       help
+         Say Y here if you have a Wolfson Microelectronics WM97xx
+         touchscreen connected to your system. Note that this option
+         only enables core driver, you will also need to select
+         support for appropriate chip below.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called wm97xx-ts.
+
+config TOUCHSCREEN_WM9705
+       bool "WM9705 Touchscreen interface support"
+       depends on TOUCHSCREEN_WM97XX
+       help
+         Say Y here if you have a Wolfson Microelectronics WM9705
+         touchscreen controller connected to your system.
+
+         If unsure, say N.
+
+config TOUCHSCREEN_WM9712
+       bool "WM9712 Touchscreen interface support"
+       depends on TOUCHSCREEN_WM97XX
+       help
+         Say Y here if you have a Wolfson Microelectronics WM9712
+         touchscreen controller connected to your system.
+
+         If unsure, say N.
+
+config TOUCHSCREEN_WM9713
+       bool "WM9713 Touchscreen interface support"
+       depends on TOUCHSCREEN_WM97XX
+       help
+         Say Y here if you have a Wolfson Microelectronics WM9713 touchscreen
+         controller connected to your system.
+
+         If unsure, say N.
+
+config TOUCHSCREEN_WM97XX_MAINSTONE
+       tristate "WM97xx Mainstone accelerated touch"
+       depends on TOUCHSCREEN_WM97XX && ARCH_PXA
+       help
+         Say Y here for support for streaming mode with WM97xx touchscreens
+         on Mainstone systems.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called mainstone-wm97xx.
+
 config TOUCHSCREEN_USB_COMPOSITE
        tristate "USB Touchscreen Driver"
        depends on USB_ARCH_HAS_HCD
index 35d4097df35a64ddbe988376340f51c27199acf8..3c096d75651d4eb2756e302f7d865c117da85078 100644 (file)
@@ -4,6 +4,8 @@
 
 # Each configuration option enables a list of files.
 
+wm97xx-ts-y := wm97xx-core.o
+
 obj-$(CONFIG_TOUCHSCREEN_ADS7846)      += ads7846.o
 obj-$(CONFIG_TOUCHSCREEN_BITSY)                += h3600_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_CORGI)                += corgi_ts.o
@@ -19,3 +21,8 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)    += penmount.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)   += touchright.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)     += touchwin.o
 obj-$(CONFIG_TOUCHSCREEN_UCB1400)      += ucb1400_ts.o
+obj-$(CONFIG_TOUCHSCREEN_WM97XX)       += wm97xx-ts.o
+wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
+wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
+wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
+obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE)     += mainstone-wm97xx.o
index 39573b91c8de4be826ff4b2a44a3c5f6f71c36c4..907a45fe9d40f5a828bd002ecd8d05d1562d353a 100644 (file)
@@ -80,6 +80,7 @@ struct ads7846 {
 #endif
 
        u16                     model;
+       u16                     vref_mv;
        u16                     vref_delay_usecs;
        u16                     x_plate_ohms;
        u16                     pressure_max;
@@ -177,9 +178,6 @@ struct ads7846 {
  * The range is GND..vREF. The ads7843 and ads7835 must use external vREF;
  * ads7846 lets that pin be unconnected, to use internal vREF.
  */
-static unsigned vREF_mV;
-module_param(vREF_mV, uint, 0);
-MODULE_PARM_DESC(vREF_mV, "external vREF voltage, in milliVolts");
 
 struct ser_req {
        u8                      ref_on;
@@ -206,7 +204,6 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
        struct ads7846          *ts = dev_get_drvdata(dev);
        struct ser_req          *req = kzalloc(sizeof *req, GFP_KERNEL);
        int                     status;
-       int                     uninitialized_var(sample);
        int                     use_internal;
 
        if (!req)
@@ -263,13 +260,13 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
 
        if (status == 0) {
                /* on-wire is a must-ignore bit, a BE12 value, then padding */
-               sample = be16_to_cpu(req->sample);
-               sample = sample >> 3;
-               sample &= 0x0fff;
+               status = be16_to_cpu(req->sample);
+               status = status >> 3;
+               status &= 0x0fff;
        }
 
        kfree(req);
-       return status ? status : sample;
+       return status;
 }
 
 #if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE)
@@ -310,7 +307,7 @@ static inline unsigned vaux_adjust(struct ads7846 *ts, ssize_t v)
        unsigned retval = v;
 
        /* external resistors may scale vAUX into 0..vREF */
-       retval *= vREF_mV;
+       retval *= ts->vref_mv;
        retval = retval >> 12;
        return retval;
 }
@@ -368,14 +365,14 @@ static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts)
        /* hwmon sensors need a reference voltage */
        switch (ts->model) {
        case 7846:
-               if (!vREF_mV) {
+               if (!ts->vref_mv) {
                        dev_dbg(&spi->dev, "assuming 2.5V internal vREF\n");
-                       vREF_mV = 2500;
+                       ts->vref_mv = 2500;
                }
                break;
        case 7845:
        case 7843:
-               if (!vREF_mV) {
+               if (!ts->vref_mv) {
                        dev_warn(&spi->dev,
                                "external vREF for ADS%d not specified\n",
                                ts->model);
@@ -868,6 +865,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
 
        ts->spi = spi;
        ts->input = input_dev;
+       ts->vref_mv = pdata->vref_mv;
 
        hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        ts->timer.function = ads7846_timer;
index a22576779acdc3c7e79c4148ca3cf89c358e0261..4e9d8eece2e003f8674d90a8f6ac0caaa447934f 100644 (file)
@@ -362,6 +362,7 @@ static struct platform_driver corgits_driver = {
        .resume         = corgits_resume,
        .driver         = {
                .name   = "corgi-ts",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -381,3 +382,4 @@ module_exit(corgits_exit);
 MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
 MODULE_DESCRIPTION("Corgi TouchScreen Driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:corgi-ts");
index 42a1c9a1940ece796c099c1cc24a77f3baddc637..742242111bf1b20b5c57ea3ba2b3ec6c99d7c37c 100644 (file)
@@ -160,11 +160,15 @@ static int __devexit jornada720_ts_remove(struct platform_device *pdev)
        return 0;
 }
 
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:jornada_ts");
+
 static struct platform_driver jornada720_ts_driver = {
        .probe          = jornada720_ts_probe,
        .remove         = __devexit_p(jornada720_ts_remove),
        .driver         = {
                .name   = "jornada_ts",
+               .owner  = THIS_MODULE,
        },
 };
 
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c
new file mode 100644 (file)
index 0000000..a79f029
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ * mainstone-wm97xx.c  --  Mainstone Continuous Touch screen driver for
+ *                         Wolfson WM97xx AC97 Codecs.
+ *
+ * Copyright 2004, 2007 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Parts Copyright : Ian Molton <spyro@f2s.com>
+ *                   Andrew Zabolotny <zap@homelink.ru>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ * Notes:
+ *     This is a wm97xx extended touch driver to capture touch
+ *     data in a continuous manner on the Intel XScale archictecture
+ *
+ *  Features:
+ *       - codecs supported:- WM9705, WM9712, WM9713
+ *       - processors supported:- Intel XScale PXA25x, PXA26x, PXA27x
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/wm97xx.h>
+#include <linux/io.h>
+#include <asm/arch/pxa-regs.h>
+
+#define VERSION                "0.13"
+
+struct continuous {
+       u16 id;    /* codec id */
+       u8 code;   /* continuous code */
+       u8 reads;  /* number of coord reads per read cycle */
+       u32 speed; /* number of coords per second */
+};
+
+#define WM_READS(sp) ((sp / HZ) + 1)
+
+static const struct continuous cinfo[] = {
+       {WM9705_ID2, 0, WM_READS(94), 94},
+       {WM9705_ID2, 1, WM_READS(188), 188},
+       {WM9705_ID2, 2, WM_READS(375), 375},
+       {WM9705_ID2, 3, WM_READS(750), 750},
+       {WM9712_ID2, 0, WM_READS(94), 94},
+       {WM9712_ID2, 1, WM_READS(188), 188},
+       {WM9712_ID2, 2, WM_READS(375), 375},
+       {WM9712_ID2, 3, WM_READS(750), 750},
+       {WM9713_ID2, 0, WM_READS(94), 94},
+       {WM9713_ID2, 1, WM_READS(120), 120},
+       {WM9713_ID2, 2, WM_READS(154), 154},
+       {WM9713_ID2, 3, WM_READS(188), 188},
+};
+
+/* continuous speed index */
+static int sp_idx;
+static u16 last, tries;
+
+/*
+ * Pen sampling frequency (Hz) in continuous mode.
+ */
+static int cont_rate = 200;
+module_param(cont_rate, int, 0);
+MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
+
+/*
+ * Pen down detection.
+ *
+ * This driver can either poll or use an interrupt to indicate a pen down
+ * event. If the irq request fails then it will fall back to polling mode.
+ */
+static int pen_int;
+module_param(pen_int, int, 0);
+MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)");
+
+/*
+ * Pressure readback.
+ *
+ * Set to 1 to read back pen down pressure
+ */
+static int pressure;
+module_param(pressure, int, 0);
+MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
+
+/*
+ * AC97 touch data slot.
+ *
+ * Touch screen readback data ac97 slot
+ */
+static int ac97_touch_slot = 5;
+module_param(ac97_touch_slot, int, 0);
+MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
+
+
+/* flush AC97 slot 5 FIFO on pxa machines */
+#ifdef CONFIG_PXA27x
+static void wm97xx_acc_pen_up(struct wm97xx *wm)
+{
+       schedule_timeout_uninterruptible(1);
+
+       while (MISR & (1 << 2))
+               MODR;
+}
+#else
+static void wm97xx_acc_pen_up(struct wm97xx *wm)
+{
+       int count = 16;
+       schedule_timeout_uninterruptible(1);
+
+       while (count < 16) {
+               MODR;
+               count--;
+       }
+}
+#endif
+
+static int wm97xx_acc_pen_down(struct wm97xx *wm)
+{
+       u16 x, y, p = 0x100 | WM97XX_ADCSEL_PRES;
+       int reads = 0;
+
+       /* When the AC97 queue has been drained we need to allow time
+        * to buffer up samples otherwise we end up spinning polling
+        * for samples.  The controller can't have a suitably low
+        * threashold set to use the notifications it gives.
+        */
+       schedule_timeout_uninterruptible(1);
+
+       if (tries > 5) {
+               tries = 0;
+               return RC_PENUP;
+       }
+
+       x = MODR;
+       if (x == last) {
+               tries++;
+               return RC_AGAIN;
+       }
+       last = x;
+       do {
+               if (reads)
+                       x = MODR;
+               y = MODR;
+               if (pressure)
+                       p = MODR;
+
+               /* are samples valid */
+               if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X ||
+                   (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y ||
+                   (p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES)
+                       goto up;
+
+               /* coordinate is good */
+               tries = 0;
+               input_report_abs(wm->input_dev, ABS_X, x & 0xfff);
+               input_report_abs(wm->input_dev, ABS_Y, y & 0xfff);
+               input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff);
+               input_sync(wm->input_dev);
+               reads++;
+       } while (reads < cinfo[sp_idx].reads);
+up:
+       return RC_PENDOWN | RC_AGAIN;
+}
+
+static int wm97xx_acc_startup(struct wm97xx *wm)
+{
+       int idx = 0;
+
+       /* check we have a codec */
+       if (wm->ac97 == NULL)
+               return -ENODEV;
+
+       /* Go you big red fire engine */
+       for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
+               if (wm->id != cinfo[idx].id)
+                       continue;
+               sp_idx = idx;
+               if (cont_rate <= cinfo[idx].speed)
+                       break;
+       }
+       wm->acc_rate = cinfo[sp_idx].code;
+       wm->acc_slot = ac97_touch_slot;
+       dev_info(wm->dev,
+                "mainstone accelerated touchscreen driver, %d samples/sec\n",
+                cinfo[sp_idx].speed);
+
+       /* codec specific irq config */
+       if (pen_int) {
+               switch (wm->id) {
+               case WM9705_ID2:
+                       wm->pen_irq = IRQ_GPIO(4);
+                       set_irq_type(IRQ_GPIO(4), IRQT_BOTHEDGE);
+                       break;
+               case WM9712_ID2:
+               case WM9713_ID2:
+                       /* enable pen down interrupt */
+                       /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */
+                       wm->pen_irq = MAINSTONE_AC97_IRQ;
+                       wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
+                                          WM97XX_GPIO_POL_HIGH,
+                                          WM97XX_GPIO_STICKY,
+                                          WM97XX_GPIO_WAKE);
+                       wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT,
+                                          WM97XX_GPIO_POL_HIGH,
+                                          WM97XX_GPIO_NOTSTICKY,
+                                          WM97XX_GPIO_NOWAKE);
+                       break;
+               default:
+                       dev_err(wm->dev,
+                               "pen down irq not supported on this device\n");
+                       pen_int = 0;
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static void wm97xx_acc_shutdown(struct wm97xx *wm)
+{
+       /* codec specific deconfig */
+       if (pen_int) {
+               switch (wm->id & 0xffff) {
+               case WM9705_ID2:
+                       wm->pen_irq = 0;
+                       break;
+               case WM9712_ID2:
+               case WM9713_ID2:
+                       /* disable interrupt */
+                       wm->pen_irq = 0;
+                       break;
+               }
+       }
+}
+
+static void wm97xx_irq_enable(struct wm97xx *wm, int enable)
+{
+       if (enable)
+               enable_irq(wm->pen_irq);
+       else
+               disable_irq(wm->pen_irq);
+}
+
+static struct wm97xx_mach_ops mainstone_mach_ops = {
+       .acc_enabled = 1,
+       .acc_pen_up = wm97xx_acc_pen_up,
+       .acc_pen_down = wm97xx_acc_pen_down,
+       .acc_startup = wm97xx_acc_startup,
+       .acc_shutdown = wm97xx_acc_shutdown,
+       .irq_enable = wm97xx_irq_enable,
+       .irq_gpio = WM97XX_GPIO_2,
+};
+
+static int mainstone_wm97xx_probe(struct platform_device *pdev)
+{
+       struct wm97xx *wm = platform_get_drvdata(pdev);
+
+       return wm97xx_register_mach_ops(wm, &mainstone_mach_ops);
+}
+
+static int mainstone_wm97xx_remove(struct platform_device *pdev)
+{
+       struct wm97xx *wm = platform_get_drvdata(pdev);
+
+       wm97xx_unregister_mach_ops(wm);
+       return 0;
+}
+
+static struct platform_driver mainstone_wm97xx_driver = {
+       .probe = mainstone_wm97xx_probe,
+       .remove = mainstone_wm97xx_remove,
+       .driver = {
+               .name = "wm97xx-touch",
+       },
+};
+
+static int __init mainstone_wm97xx_init(void)
+{
+       return platform_driver_register(&mainstone_wm97xx_driver);
+}
+
+static void __exit mainstone_wm97xx_exit(void)
+{
+       platform_driver_unregister(&mainstone_wm97xx_driver);
+}
+
+module_init(mainstone_wm97xx_init);
+module_exit(mainstone_wm97xx_exit);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
+MODULE_DESCRIPTION("wm97xx continuous touch driver for mainstone");
+MODULE_LICENSE("GPL");
index 607f9933aa1fd6d91f423fd62e821b17dc243b1d..bce018e45bce4781cb7b61519485502ff8c22171 100644 (file)
@@ -427,10 +427,6 @@ static int ucb1400_detect_irq(struct ucb1400 *ucb)
        unsigned long mask, timeout;
 
        mask = probe_irq_on();
-       if (!mask) {
-               probe_irq_off(mask);
-               return -EBUSY;
-       }
 
        /* Enable the ADC interrupt. */
        ucb1400_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC);
index 63f9664a066f8465398f4526ca07ee4fbbbf4684..3a0a8ca570767000569ebab0befa31cec6d3b3c1 100644 (file)
@@ -396,9 +396,12 @@ static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
 {
        struct usb_device *dev = usbtouch->udev;
-       int ret;
-       unsigned char buf[2];
+       int ret = -ENOMEM;
+       unsigned char *buf;
 
+       buf = kmalloc(2, GFP_KERNEL);
+       if (!buf)
+               goto err_nobuf;
        /* reset */
        buf[0] = buf[1] = 0xFF;
        ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
@@ -406,9 +409,11 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
                              USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                              0, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
        if (ret < 0)
-               return ret;
-       if (buf[0] != 0x06 || buf[1] != 0x00)
-               return -ENODEV;
+               goto err_out;
+       if (buf[0] != 0x06 || buf[1] != 0x00) {
+               ret = -ENODEV;
+               goto err_out;
+       }
 
        /* set coordinate output rate */
        buf[0] = buf[1] = 0xFF;
@@ -417,20 +422,22 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
                              USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                              TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
        if (ret < 0)
-               return ret;
+               goto err_out;
        if ((buf[0] != 0x06 || buf[1] != 0x00) &&
-           (buf[0] != 0x15 || buf[1] != 0x01))
-               return -ENODEV;
+           (buf[0] != 0x15 || buf[1] != 0x01)) {
+               ret = -ENODEV;
+               goto err_out;
+       }
 
        /* start sending data */
        ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
                              TSC10_CMD_DATA1,
                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                              0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
-       if (ret < 0)
-               return ret;
-
-       return 0;
+err_out:
+       kfree(buf);
+err_nobuf:
+       return ret;
 }
 
 
diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c
new file mode 100644 (file)
index 0000000..978e1a1
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * wm9705.c  --  Codec driver for Wolfson WM9705 AC97 Codec.
+ *
+ * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Parts Copyright : Ian Molton <spyro@f2s.com>
+ *                   Andrew Zabolotny <zap@homelink.ru>
+ *                   Russell King <rmk@arm.linux.org.uk>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/wm97xx.h>
+
+#define TS_NAME                        "wm97xx"
+#define WM9705_VERSION         "1.00"
+#define DEFAULT_PRESSURE       0xb0c0
+
+/*
+ * Module parameters
+ */
+
+/*
+ * Set current used for pressure measurement.
+ *
+ * Set pil = 2 to use 400uA
+ *     pil = 1 to use 200uA and
+ *     pil = 0 to disable pressure measurement.
+ *
+ * This is used to increase the range of values returned by the adc
+ * when measureing touchpanel pressure.
+ */
+static int pil;
+module_param(pil, int, 0);
+MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
+
+/*
+ * Set threshold for pressure measurement.
+ *
+ * Pen down pressure below threshold is ignored.
+ */
+static int pressure = DEFAULT_PRESSURE & 0xfff;
+module_param(pressure, int, 0);
+MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
+
+/*
+ * Set adc sample delay.
+ *
+ * For accurate touchpanel measurements, some settling time may be
+ * required between the switch matrix applying a voltage across the
+ * touchpanel plate and the ADC sampling the signal.
+ *
+ * This delay can be set by setting delay = n, where n is the array
+ * position of the delay in the array delay_table below.
+ * Long delays > 1ms are supported for completeness, but are not
+ * recommended.
+ */
+static int delay = 4;
+module_param(delay, int, 0);
+MODULE_PARM_DESC(delay, "Set adc sample delay.");
+
+/*
+ * Pen detect comparator threshold.
+ *
+ * 0 to Vmid in 15 steps, 0 = use zero power comparator with Vmid threshold
+ * i.e. 1 =  Vmid/15 threshold
+ *      15 =  Vmid/1 threshold
+ *
+ * Adjust this value if you are having problems with pen detect not
+ * detecting any down events.
+ */
+static int pdd = 8;
+module_param(pdd, int, 0);
+MODULE_PARM_DESC(pdd, "Set pen detect comparator threshold");
+
+/*
+ * Set adc mask function.
+ *
+ * Sources of glitch noise, such as signals driving an LCD display, may feed
+ * through to the touch screen plates and affect measurement accuracy. In
+ * order to minimise this, a signal may be applied to the MASK pin to delay or
+ * synchronise the sampling.
+ *
+ * 0 = No delay or sync
+ * 1 = High on pin stops conversions
+ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
+ * 3 = Edge triggered, edge on pin starts conversion after delay param
+ */
+static int mask;
+module_param(mask, int, 0);
+MODULE_PARM_DESC(mask, "Set adc mask function.");
+
+/*
+ * ADC sample delay times in uS
+ */
+static const int delay_table[] = {
+       21,    /* 1 AC97 Link frames */
+       42,    /* 2                  */
+       84,    /* 4                  */
+       167,   /* 8                  */
+       333,   /* 16                 */
+       667,   /* 32                 */
+       1000,  /* 48                 */
+       1333,  /* 64                 */
+       2000,  /* 96                 */
+       2667,  /* 128                */
+       3333,  /* 160                */
+       4000,  /* 192                */
+       4667,  /* 224                */
+       5333,  /* 256                */
+       6000,  /* 288                */
+       0      /* No delay, switch matrix always on */
+};
+
+/*
+ * Delay after issuing a POLL command.
+ *
+ * The delay is 3 AC97 link frames + the touchpanel settling delay
+ */
+static inline void poll_delay(int d)
+{
+       udelay(3 * AC97_LINK_FRAME + delay_table[d]);
+}
+
+/*
+ * set up the physical settings of the WM9705
+ */
+static void wm9705_phy_init(struct wm97xx *wm)
+{
+       u16 dig1 = 0, dig2 = WM97XX_RPR;
+
+       /*
+       * mute VIDEO and AUX as they share X and Y touchscreen
+       * inputs on the WM9705
+       */
+       wm97xx_reg_write(wm, AC97_AUX, 0x8000);
+       wm97xx_reg_write(wm, AC97_VIDEO, 0x8000);
+
+       /* touchpanel pressure current*/
+       if (pil == 2) {
+               dig2 |= WM9705_PIL;
+               dev_dbg(wm->dev,
+                       "setting pressure measurement current to 400uA.");
+       } else if (pil)
+               dev_dbg(wm->dev,
+                       "setting pressure measurement current to 200uA.");
+       if (!pil)
+               pressure = 0;
+
+       /* polling mode sample settling delay */
+       if (delay != 4) {
+               if (delay < 0 || delay > 15) {
+                       dev_dbg(wm->dev, "supplied delay out of range.");
+                       delay = 4;
+               }
+       }
+       dig1 &= 0xff0f;
+       dig1 |= WM97XX_DELAY(delay);
+       dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.",
+               delay_table[delay]);
+
+       /* WM9705 pdd */
+       dig2 |= (pdd & 0x000f);
+       dev_dbg(wm->dev, "setting pdd to Vmid/%d", 1 - (pdd & 0x000f));
+
+       /* mask */
+       dig2 |= ((mask & 0x3) << 4);
+
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
+}
+
+static void wm9705_dig_enable(struct wm97xx *wm, int enable)
+{
+       if (enable) {
+               wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
+                                wm->dig[2] | WM97XX_PRP_DET_DIG);
+               wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
+       } else
+               wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
+                                wm->dig[2] & ~WM97XX_PRP_DET_DIG);
+}
+
+static void wm9705_aux_prepare(struct wm97xx *wm)
+{
+       memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
+}
+
+static void wm9705_dig_restore(struct wm97xx *wm)
+{
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
+}
+
+static inline int is_pden(struct wm97xx *wm)
+{
+       return wm->dig[2] & WM9705_PDEN;
+}
+
+/*
+ * Read a sample from the WM9705 adc in polling mode.
+ */
+static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
+{
+       int timeout = 5 * delay;
+
+       if (!wm->pen_probably_down) {
+               u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+               if (!(data & WM97XX_PEN_DOWN))
+                       return RC_PENUP;
+               wm->pen_probably_down = 1;
+       }
+
+       /* set up digitiser */
+       if (adcsel & 0x8000)
+               adcsel = ((adcsel & 0x7fff) + 3) << 12;
+
+       if (wm->mach_ops && wm->mach_ops->pre_sample)
+               wm->mach_ops->pre_sample(adcsel);
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
+                        adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
+
+       /* wait 3 AC97 time slots + delay for conversion */
+       poll_delay(delay);
+
+       /* wait for POLL to go low */
+       while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
+              && timeout) {
+               udelay(AC97_LINK_FRAME);
+               timeout--;
+       }
+
+       if (timeout == 0) {
+               /* If PDEN is set, we can get a timeout when pen goes up */
+               if (is_pden(wm))
+                       wm->pen_probably_down = 0;
+               else
+                       dev_dbg(wm->dev, "adc sample timeout");
+               return RC_PENUP;
+       }
+
+       *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+       if (wm->mach_ops && wm->mach_ops->post_sample)
+               wm->mach_ops->post_sample(adcsel);
+
+       /* check we have correct sample */
+       if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
+               dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
+               *sample & WM97XX_ADCSEL_MASK);
+               return RC_PENUP;
+       }
+
+       if (!(*sample & WM97XX_PEN_DOWN)) {
+               wm->pen_probably_down = 0;
+               return RC_PENUP;
+       }
+
+       return RC_VALID;
+}
+
+/*
+ * Sample the WM9705 touchscreen in polling mode
+ */
+static int wm9705_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
+{
+       int rc;
+
+       rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X, &data->x);
+       if (rc != RC_VALID)
+               return rc;
+       rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y);
+       if (rc != RC_VALID)
+               return rc;
+       if (pil) {
+               rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p);
+               if (rc != RC_VALID)
+                       return rc;
+       } else
+               data->p = DEFAULT_PRESSURE;
+
+       return RC_VALID;
+}
+
+/*
+ * Enable WM9705 continuous mode, i.e. touch data is streamed across
+ * an AC97 slot
+ */
+static int wm9705_acc_enable(struct wm97xx *wm, int enable)
+{
+       u16 dig1, dig2;
+       int ret = 0;
+
+       dig1 = wm->dig[1];
+       dig2 = wm->dig[2];
+
+       if (enable) {
+               /* continous mode */
+               if (wm->mach_ops->acc_startup &&
+                   (ret = wm->mach_ops->acc_startup(wm)) < 0)
+                       return ret;
+               dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
+                         WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
+               dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
+                       WM97XX_DELAY(delay) |
+                       WM97XX_SLT(wm->acc_slot) |
+                       WM97XX_RATE(wm->acc_rate);
+               if (pil)
+                       dig1 |= WM97XX_ADCSEL_PRES;
+               dig2 |= WM9705_PDEN;
+       } else {
+               dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
+               dig2 &= ~WM9705_PDEN;
+               if (wm->mach_ops->acc_shutdown)
+                       wm->mach_ops->acc_shutdown(wm);
+       }
+
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
+
+       return ret;
+}
+
+struct wm97xx_codec_drv wm9705_codec = {
+       .id = WM9705_ID2,
+       .name = "wm9705",
+       .poll_sample = wm9705_poll_sample,
+       .poll_touch = wm9705_poll_touch,
+       .acc_enable = wm9705_acc_enable,
+       .phy_init = wm9705_phy_init,
+       .dig_enable = wm9705_dig_enable,
+       .dig_restore = wm9705_dig_restore,
+       .aux_prepare = wm9705_aux_prepare,
+};
+EXPORT_SYMBOL_GPL(wm9705_codec);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
+MODULE_DESCRIPTION("WM9705 Touch Screen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c
new file mode 100644 (file)
index 0000000..0b6e4cf
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+ * wm9712.c  --  Codec driver for Wolfson WM9712 AC97 Codecs.
+ *
+ * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Parts Copyright : Ian Molton <spyro@f2s.com>
+ *                   Andrew Zabolotny <zap@homelink.ru>
+ *                   Russell King <rmk@arm.linux.org.uk>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/wm97xx.h>
+
+#define TS_NAME                        "wm97xx"
+#define WM9712_VERSION         "1.00"
+#define DEFAULT_PRESSURE       0xb0c0
+
+/*
+ * Module parameters
+ */
+
+/*
+ * Set internal pull up for pen detect.
+ *
+ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
+ * i.e. pull up resistance = 64k Ohms / rpu.
+ *
+ * Adjust this value if you are having problems with pen detect not
+ * detecting any down event.
+ */
+static int rpu = 8;
+module_param(rpu, int, 0);
+MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
+
+/*
+ * Set current used for pressure measurement.
+ *
+ * Set pil = 2 to use 400uA
+ *     pil = 1 to use 200uA and
+ *     pil = 0 to disable pressure measurement.
+ *
+ * This is used to increase the range of values returned by the adc
+ * when measureing touchpanel pressure.
+ */
+static int pil;
+module_param(pil, int, 0);
+MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
+
+/*
+ * Set threshold for pressure measurement.
+ *
+ * Pen down pressure below threshold is ignored.
+ */
+static int pressure = DEFAULT_PRESSURE & 0xfff;
+module_param(pressure, int, 0);
+MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
+
+/*
+ * Set adc sample delay.
+ *
+ * For accurate touchpanel measurements, some settling time may be
+ * required between the switch matrix applying a voltage across the
+ * touchpanel plate and the ADC sampling the signal.
+ *
+ * This delay can be set by setting delay = n, where n is the array
+ * position of the delay in the array delay_table below.
+ * Long delays > 1ms are supported for completeness, but are not
+ * recommended.
+ */
+static int delay = 3;
+module_param(delay, int, 0);
+MODULE_PARM_DESC(delay, "Set adc sample delay.");
+
+/*
+ * Set five_wire = 1 to use a 5 wire touchscreen.
+ *
+ * NOTE: Five wire mode does not allow for readback of pressure.
+ */
+static int five_wire;
+module_param(five_wire, int, 0);
+MODULE_PARM_DESC(five_wire, "Set to '1' to use 5-wire touchscreen.");
+
+/*
+ * Set adc mask function.
+ *
+ * Sources of glitch noise, such as signals driving an LCD display, may feed
+ * through to the touch screen plates and affect measurement accuracy. In
+ * order to minimise this, a signal may be applied to the MASK pin to delay or
+ * synchronise the sampling.
+ *
+ * 0 = No delay or sync
+ * 1 = High on pin stops conversions
+ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
+ * 3 = Edge triggered, edge on pin starts conversion after delay param
+ */
+static int mask;
+module_param(mask, int, 0);
+MODULE_PARM_DESC(mask, "Set adc mask function.");
+
+/*
+ * Coordinate Polling Enable.
+ *
+ * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
+ * for every poll.
+ */
+static int coord;
+module_param(coord, int, 0);
+MODULE_PARM_DESC(coord, "Polling coordinate mode");
+
+/*
+ * ADC sample delay times in uS
+ */
+static const int delay_table[] = {
+       21,    /* 1 AC97 Link frames */
+       42,    /* 2 */
+       84,    /* 4 */
+       167,   /* 8 */
+       333,   /* 16 */
+       667,   /* 32 */
+       1000,  /* 48 */
+       1333,  /* 64 */
+       2000,  /* 96 */
+       2667,  /* 128 */
+       3333,  /* 160 */
+       4000,  /* 192 */
+       4667,  /* 224 */
+       5333,  /* 256 */
+       6000,  /* 288 */
+       0      /* No delay, switch matrix always on */
+};
+
+/*
+ * Delay after issuing a POLL command.
+ *
+ * The delay is 3 AC97 link frames + the touchpanel settling delay
+ */
+static inline void poll_delay(int d)
+{
+       udelay(3 * AC97_LINK_FRAME + delay_table[d]);
+}
+
+/*
+ * set up the physical settings of the WM9712
+ */
+static void wm9712_phy_init(struct wm97xx *wm)
+{
+       u16 dig1 = 0;
+       u16 dig2 = WM97XX_RPR | WM9712_RPU(1);
+
+       /* WM9712 rpu */
+       if (rpu) {
+               dig2 &= 0xffc0;
+               dig2 |= WM9712_RPU(rpu);
+               dev_dbg(wm->dev, "setting pen detect pull-up to %d Ohms",
+                       64000 / rpu);
+       }
+
+       /* touchpanel pressure current*/
+       if (pil == 2) {
+               dig2 |= WM9712_PIL;
+               dev_dbg(wm->dev,
+                       "setting pressure measurement current to 400uA.");
+       } else if (pil)
+               dev_dbg(wm->dev,
+                       "setting pressure measurement current to 200uA.");
+       if (!pil)
+               pressure = 0;
+
+       /* WM9712 five wire */
+       if (five_wire) {
+               dig2 |= WM9712_45W;
+               dev_dbg(wm->dev, "setting 5-wire touchscreen mode.");
+       }
+
+       /* polling mode sample settling delay */
+       if (delay < 0 || delay > 15) {
+               dev_dbg(wm->dev, "supplied delay out of range.");
+               delay = 4;
+       }
+       dig1 &= 0xff0f;
+       dig1 |= WM97XX_DELAY(delay);
+       dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.",
+               delay_table[delay]);
+
+       /* mask */
+       dig2 |= ((mask & 0x3) << 6);
+       if (mask) {
+               u16 reg;
+               /* Set GPIO4 as Mask Pin*/
+               reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
+               wm97xx_reg_write(wm, AC97_MISC_AFE, reg | WM97XX_GPIO_4);
+               reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
+               wm97xx_reg_write(wm, AC97_GPIO_CFG, reg | WM97XX_GPIO_4);
+       }
+
+       /* wait - coord mode */
+       if (coord)
+               dig2 |= WM9712_WAIT;
+
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
+}
+
+static void wm9712_dig_enable(struct wm97xx *wm, int enable)
+{
+       u16 dig2 = wm->dig[2];
+
+       if (enable) {
+               wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
+                                dig2 | WM97XX_PRP_DET_DIG);
+               wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
+       } else
+               wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
+                                dig2 & ~WM97XX_PRP_DET_DIG);
+}
+
+static void wm9712_aux_prepare(struct wm97xx *wm)
+{
+       memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
+}
+
+static void wm9712_dig_restore(struct wm97xx *wm)
+{
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
+}
+
+static inline int is_pden(struct wm97xx *wm)
+{
+       return wm->dig[2] & WM9712_PDEN;
+}
+
+/*
+ * Read a sample from the WM9712 adc in polling mode.
+ */
+static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
+{
+       int timeout = 5 * delay;
+
+       if (!wm->pen_probably_down) {
+               u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+               if (!(data & WM97XX_PEN_DOWN))
+                       return RC_PENUP;
+               wm->pen_probably_down = 1;
+       }
+
+       /* set up digitiser */
+       if (adcsel & 0x8000)
+               adcsel = ((adcsel & 0x7fff) + 3) << 12;
+
+       if (wm->mach_ops && wm->mach_ops->pre_sample)
+               wm->mach_ops->pre_sample(adcsel);
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
+                        adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
+
+       /* wait 3 AC97 time slots + delay for conversion */
+       poll_delay(delay);
+
+       /* wait for POLL to go low */
+       while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
+              && timeout) {
+               udelay(AC97_LINK_FRAME);
+               timeout--;
+       }
+
+       if (timeout <= 0) {
+               /* If PDEN is set, we can get a timeout when pen goes up */
+               if (is_pden(wm))
+                       wm->pen_probably_down = 0;
+               else
+                       dev_dbg(wm->dev, "adc sample timeout");
+               return RC_PENUP;
+       }
+
+       *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+       if (wm->mach_ops && wm->mach_ops->post_sample)
+               wm->mach_ops->post_sample(adcsel);
+
+       /* check we have correct sample */
+       if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
+               dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
+               *sample & WM97XX_ADCSEL_MASK);
+               return RC_PENUP;
+       }
+
+       if (!(*sample & WM97XX_PEN_DOWN)) {
+               wm->pen_probably_down = 0;
+               return RC_PENUP;
+       }
+
+       return RC_VALID;
+}
+
+/*
+ * Read a coord from the WM9712 adc in polling mode.
+ */
+static int wm9712_poll_coord(struct wm97xx *wm, struct wm97xx_data *data)
+{
+       int timeout = 5 * delay;
+
+       if (!wm->pen_probably_down) {
+               u16 data_rd = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+               if (!(data_rd & WM97XX_PEN_DOWN))
+                       return RC_PENUP;
+               wm->pen_probably_down = 1;
+       }
+
+       /* set up digitiser */
+       if (wm->mach_ops && wm->mach_ops->pre_sample)
+               wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
+
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
+               WM97XX_COO | WM97XX_POLL | WM97XX_DELAY(delay));
+
+       /* wait 3 AC97 time slots + delay for conversion and read x */
+       poll_delay(delay);
+       data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+       /* wait for POLL to go low */
+       while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
+              && timeout) {
+               udelay(AC97_LINK_FRAME);
+               timeout--;
+       }
+
+       if (timeout <= 0) {
+               /* If PDEN is set, we can get a timeout when pen goes up */
+               if (is_pden(wm))
+                       wm->pen_probably_down = 0;
+               else
+                       dev_dbg(wm->dev, "adc sample timeout");
+               return RC_PENUP;
+       }
+
+       /* read back y data */
+       data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+       if (pil)
+               data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+       else
+               data->p = DEFAULT_PRESSURE;
+
+       if (wm->mach_ops && wm->mach_ops->post_sample)
+               wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
+
+       /* check we have correct sample */
+       if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
+               goto err;
+       if (pil && !(data->p & WM97XX_ADCSEL_PRES))
+               goto err;
+
+       if (!(data->x & WM97XX_PEN_DOWN) || !(data->y & WM97XX_PEN_DOWN)) {
+               wm->pen_probably_down = 0;
+               return RC_PENUP;
+       }
+       return RC_VALID;
+err:
+       return 0;
+}
+
+/*
+ * Sample the WM9712 touchscreen in polling mode
+ */
+static int wm9712_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
+{
+       int rc;
+
+       if (coord) {
+               rc = wm9712_poll_coord(wm, data);
+               if (rc != RC_VALID)
+                       return rc;
+       } else {
+               rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X, &data->x);
+               if (rc != RC_VALID)
+                       return rc;
+
+               rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y);
+               if (rc != RC_VALID)
+                       return rc;
+
+               if (pil && !five_wire) {
+                       rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES,
+                                               &data->p);
+                       if (rc != RC_VALID)
+                               return rc;
+               } else
+                       data->p = DEFAULT_PRESSURE;
+       }
+       return RC_VALID;
+}
+
+/*
+ * Enable WM9712 continuous mode, i.e. touch data is streamed across
+ * an AC97 slot
+ */
+static int wm9712_acc_enable(struct wm97xx *wm, int enable)
+{
+       u16 dig1, dig2;
+       int ret = 0;
+
+       dig1 = wm->dig[1];
+       dig2 = wm->dig[2];
+
+       if (enable) {
+               /* continous mode */
+               if (wm->mach_ops->acc_startup) {
+                       ret = wm->mach_ops->acc_startup(wm);
+                       if (ret < 0)
+                               return ret;
+               }
+               dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
+                       WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
+               dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
+                       WM97XX_DELAY(delay) |
+                       WM97XX_SLT(wm->acc_slot) |
+                       WM97XX_RATE(wm->acc_rate);
+               if (pil)
+                       dig1 |= WM97XX_ADCSEL_PRES;
+               dig2 |= WM9712_PDEN;
+       } else {
+               dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
+               dig2 &= ~WM9712_PDEN;
+               if (wm->mach_ops->acc_shutdown)
+                       wm->mach_ops->acc_shutdown(wm);
+       }
+
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
+       wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
+
+       return 0;
+}
+
+struct wm97xx_codec_drv wm9712_codec = {
+       .id = WM9712_ID2,
+       .name = "wm9712",
+       .poll_sample = wm9712_poll_sample,
+       .poll_touch = wm9712_poll_touch,
+       .acc_enable = wm9712_acc_enable,
+       .phy_init = wm9712_phy_init,
+       .dig_enable = wm9712_dig_enable,
+       .dig_restore = wm9712_dig_restore,
+       .aux_prepare = wm9712_aux_prepare,
+};
+EXPORT_SYMBOL_GPL(wm9712_codec);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
+MODULE_DESCRIPTION("WM9712 Touch Screen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c
new file mode 100644 (file)
index 0000000..01278bd
--- /dev/null
@@ -0,0 +1,460 @@
+/*
+ * wm9713.c  --  Codec touch driver for Wolfson WM9713 AC97 Codec.
+ *
+ * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Parts Copyright : Ian Molton <spyro@f2s.com>
+ *                   Andrew Zabolotny <zap@homelink.ru>
+ *                   Russell King <rmk@arm.linux.org.uk>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/wm97xx.h>
+
+#define TS_NAME                        "wm97xx"
+#define WM9713_VERSION         "1.00"
+#define DEFAULT_PRESSURE       0xb0c0
+
+/*
+ * Module parameters
+ */
+
+/*
+ * Set internal pull up for pen detect.
+ *
+ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
+ * i.e. pull up resistance = 64k Ohms / rpu.
+ *
+ * Adjust this value if you are having problems with pen detect not
+ * detecting any down event.
+ */
+static int rpu = 8;
+module_param(rpu, int, 0);
+MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
+
+/*
+ * Set current used for pressure measurement.
+ *
+ * Set pil = 2 to use 400uA
+ *     pil = 1 to use 200uA and
+ *     pil = 0 to disable pressure measurement.
+ *
+ * This is used to increase the range of values returned by the adc
+ * when measureing touchpanel pressure.
+ */
+static int pil;
+module_param(pil, int, 0);
+MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
+
+/*
+ * Set threshold for pressure measurement.
+ *
+ * Pen down pressure below threshold is ignored.
+ */
+static int pressure = DEFAULT_PRESSURE & 0xfff;
+module_param(pressure, int, 0);
+MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
+
+/*
+ * Set adc sample delay.
+ *
+ * For accurate touchpanel measurements, some settling time may be
+ * required between the switch matrix applying a voltage across the
+ * touchpanel plate and the ADC sampling the signal.
+ *
+ * This delay can be set by setting delay = n, where n is the array
+ * position of the delay in the array delay_table below.
+ * Long delays > 1ms are supported for completeness, but are not
+ * recommended.
+ */
+static int delay = 4;
+module_param(delay, int, 0);
+MODULE_PARM_DESC(delay, "Set adc sample delay.");
+
+/*
+ * Set adc mask function.
+ *
+ * Sources of glitch noise, such as signals driving an LCD display, may feed
+ * through to the touch screen plates and affect measurement accuracy. In
+ * order to minimise this, a signal may be applied to the MASK pin to delay or
+ * synchronise the sampling.
+ *
+ * 0 = No delay or sync
+ * 1 = High on pin stops conversions
+ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
+ * 3 = Edge triggered, edge on pin starts conversion after delay param
+ */
+static int mask;
+module_param(mask, int, 0);
+MODULE_PARM_DESC(mask, "Set adc mask function.");
+
+/*
+ * Coordinate Polling Enable.
+ *
+ * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
+ * for every poll.
+ */
+static int coord;
+module_param(coord, int, 0);
+MODULE_PARM_DESC(coord, "Polling coordinate mode");
+
+/*
+ * ADC sample delay times in uS
+ */
+static const int delay_table[] = {
+       21,    /* 1 AC97 Link frames */
+       42,    /* 2 */
+       84,    /* 4 */
+       167,   /* 8 */
+       333,   /* 16 */
+       667,   /* 32 */
+       1000,  /* 48 */
+       1333,  /* 64 */
+       2000,  /* 96 */
+       2667,  /* 128 */
+       3333,  /* 160 */
+       4000,  /* 192 */
+       4667,  /* 224 */
+       5333,  /* 256 */
+       6000,  /* 288 */
+       0      /* No delay, switch matrix always on */
+};
+
+/*
+ * Delay after issuing a POLL command.
+ *
+ * The delay is 3 AC97 link frames + the touchpanel settling delay
+ */
+static inline void poll_delay(int d)
+{
+       udelay(3 * AC97_LINK_FRAME + delay_table[d]);
+}
+
+/*
+ * set up the physical settings of the WM9713
+ */
+static void wm9713_phy_init(struct wm97xx *wm)
+{
+       u16 dig1 = 0, dig2, dig3;
+
+       /* default values */
+       dig2 = WM97XX_DELAY(4) | WM97XX_SLT(5);
+       dig3 = WM9712_RPU(1);
+
+       /* rpu */
+       if (rpu) {
+               dig3 &= 0xffc0;
+               dig3 |= WM9712_RPU(rpu);
+               dev_info(wm->dev, "setting pen detect pull-up to %d Ohms\n",
+                        64000 / rpu);
+       }
+
+       /* touchpanel pressure */
+       if (pil == 2) {
+               dig3 |= WM9712_PIL;
+               dev_info(wm->dev,
+                        "setting pressure measurement current to 400uA.");
+       } else if (pil)
+               dev_info(wm->dev,
+                        "setting pressure measurement current to 200uA.");
+       if (!pil)
+               pressure = 0;
+
+       /* sample settling delay */
+       if (delay < 0 || delay > 15) {
+               dev_info(wm->dev, "supplied delay out of range.");
+               delay = 4;
+               dev_info(wm->dev, "setting adc sample delay to %d u Secs.",
+                        delay_table[delay]);
+       }
+       dig2 &= 0xff0f;
+       dig2 |= WM97XX_DELAY(delay);
+
+       /* mask */
+       dig3 |= ((mask & 0x3) << 4);
+       if (coord)
+               dig3 |= WM9713_WAIT;
+
+       wm->misc = wm97xx_reg_read(wm, 0x5a);
+
+       wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
+       wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
+       wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
+       wm97xx_reg_write(wm, AC97_GPIO_STICKY, 0x0);
+}
+
+static void wm9713_dig_enable(struct wm97xx *wm, int enable)
+{
+       u16 val;
+
+       if (enable) {
+               val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
+               wm97xx_reg_write(wm, AC97_EXTENDED_MID, val & 0x7fff);
+               wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] |
+                                WM97XX_PRP_DET_DIG);
+               wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
+       } else {
+               wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] &
+                                       ~WM97XX_PRP_DET_DIG);
+               val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
+               wm97xx_reg_write(wm, AC97_EXTENDED_MID, val | 0x8000);
+       }
+}
+
+static void wm9713_dig_restore(struct wm97xx *wm)
+{
+       wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig_save[0]);
+       wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig_save[1]);
+       wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig_save[2]);
+}
+
+static void wm9713_aux_prepare(struct wm97xx *wm)
+{
+       memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
+       wm97xx_reg_write(wm, AC97_WM9713_DIG1, 0);
+       wm97xx_reg_write(wm, AC97_WM9713_DIG2, 0);
+       wm97xx_reg_write(wm, AC97_WM9713_DIG3, WM97XX_PRP_DET_DIG);
+}
+
+static inline int is_pden(struct wm97xx *wm)
+{
+       return wm->dig[2] & WM9713_PDEN;
+}
+
+/*
+ * Read a sample from the WM9713 adc in polling mode.
+ */
+static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
+{
+       u16 dig1;
+       int timeout = 5 * delay;
+
+       if (!wm->pen_probably_down) {
+               u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+               if (!(data & WM97XX_PEN_DOWN))
+                       return RC_PENUP;
+               wm->pen_probably_down = 1;
+       }
+
+       /* set up digitiser */
+       if (adcsel & 0x8000)
+               adcsel = 1 << ((adcsel & 0x7fff) + 3);
+
+       dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
+       dig1 &= ~WM9713_ADCSEL_MASK;
+
+       if (wm->mach_ops && wm->mach_ops->pre_sample)
+               wm->mach_ops->pre_sample(adcsel);
+       wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | adcsel | WM9713_POLL);
+
+       /* wait 3 AC97 time slots + delay for conversion */
+       poll_delay(delay);
+
+       /* wait for POLL to go low */
+       while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL) &&
+               timeout) {
+               udelay(AC97_LINK_FRAME);
+               timeout--;
+       }
+
+       if (timeout <= 0) {
+               /* If PDEN is set, we can get a timeout when pen goes up */
+               if (is_pden(wm))
+                       wm->pen_probably_down = 0;
+               else
+                       dev_dbg(wm->dev, "adc sample timeout");
+               return RC_PENUP;
+       }
+
+       *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+       if (wm->mach_ops && wm->mach_ops->post_sample)
+               wm->mach_ops->post_sample(adcsel);
+
+       /* check we have correct sample */
+       if ((*sample & WM97XX_ADCSRC_MASK) != ffs(adcsel >> 1) << 12) {
+               dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
+                       *sample & WM97XX_ADCSRC_MASK);
+               return RC_PENUP;
+       }
+
+       if (!(*sample & WM97XX_PEN_DOWN)) {
+               wm->pen_probably_down = 0;
+               return RC_PENUP;
+       }
+
+       return RC_VALID;
+}
+
+/*
+ * Read a coordinate from the WM9713 adc in polling mode.
+ */
+static int wm9713_poll_coord(struct wm97xx *wm, struct wm97xx_data *data)
+{
+       u16 dig1;
+       int timeout = 5 * delay;
+
+       if (!wm->pen_probably_down) {
+               u16 val = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+               if (!(val & WM97XX_PEN_DOWN))
+                       return RC_PENUP;
+               wm->pen_probably_down = 1;
+       }
+
+       /* set up digitiser */
+       dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
+       dig1 &= ~WM9713_ADCSEL_MASK;
+       if (pil)
+               dig1 |= WM9713_ADCSEL_PRES;
+
+       if (wm->mach_ops && wm->mach_ops->pre_sample)
+               wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
+       wm97xx_reg_write(wm, AC97_WM9713_DIG1,
+                        dig1 | WM9713_POLL | WM9713_COO);
+
+       /* wait 3 AC97 time slots + delay for conversion */
+       poll_delay(delay);
+       data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+       /* wait for POLL to go low */
+       while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL)
+              && timeout) {
+               udelay(AC97_LINK_FRAME);
+               timeout--;
+       }
+
+       if (timeout <= 0) {
+               /* If PDEN is set, we can get a timeout when pen goes up */
+               if (is_pden(wm))
+                       wm->pen_probably_down = 0;
+               else
+                       dev_dbg(wm->dev, "adc sample timeout");
+               return RC_PENUP;
+       }
+
+       /* read back data */
+       data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+       if (pil)
+               data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+       else
+               data->p = DEFAULT_PRESSURE;
+
+       if (wm->mach_ops && wm->mach_ops->post_sample)
+               wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
+
+       /* check we have correct sample */
+       if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
+               goto err;
+       if (pil && !(data->p & WM97XX_ADCSEL_PRES))
+               goto err;
+
+       if (!(data->x & WM97XX_PEN_DOWN) || !(data->y & WM97XX_PEN_DOWN)) {
+               wm->pen_probably_down = 0;
+               return RC_PENUP;
+       }
+       return RC_VALID;
+err:
+       return 0;
+}
+
+/*
+ * Sample the WM9713 touchscreen in polling mode
+ */
+static int wm9713_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
+{
+       int rc;
+
+       if (coord) {
+               rc = wm9713_poll_coord(wm, data);
+               if (rc != RC_VALID)
+                       return rc;
+       } else {
+               rc = wm9713_poll_sample(wm, WM9713_ADCSEL_X, &data->x);
+               if (rc != RC_VALID)
+                       return rc;
+               rc = wm9713_poll_sample(wm, WM9713_ADCSEL_Y, &data->y);
+               if (rc != RC_VALID)
+                       return rc;
+               if (pil) {
+                       rc = wm9713_poll_sample(wm, WM9713_ADCSEL_PRES,
+                                               &data->p);
+                       if (rc != RC_VALID)
+                               return rc;
+               } else
+                       data->p = DEFAULT_PRESSURE;
+       }
+       return RC_VALID;
+}
+
+/*
+ * Enable WM9713 continuous mode, i.e. touch data is streamed across
+ * an AC97 slot
+ */
+static int wm9713_acc_enable(struct wm97xx *wm, int enable)
+{
+       u16 dig1, dig2, dig3;
+       int ret = 0;
+
+       dig1 = wm->dig[0];
+       dig2 = wm->dig[1];
+       dig3 = wm->dig[2];
+
+       if (enable) {
+               /* continous mode */
+               if (wm->mach_ops->acc_startup &&
+                       (ret = wm->mach_ops->acc_startup(wm)) < 0)
+                       return ret;
+
+               dig1 &= ~WM9713_ADCSEL_MASK;
+               dig1 |= WM9713_CTC | WM9713_COO | WM9713_ADCSEL_X |
+                       WM9713_ADCSEL_Y;
+               if (pil)
+                       dig1 |= WM9713_ADCSEL_PRES;
+               dig2 &= ~(WM97XX_DELAY_MASK | WM97XX_SLT_MASK  |
+                       WM97XX_CM_RATE_MASK);
+               dig2 |= WM97XX_SLEN | WM97XX_DELAY(delay) |
+               WM97XX_SLT(wm->acc_slot) | WM97XX_RATE(wm->acc_rate);
+               dig3 |= WM9713_PDEN;
+       } else {
+               dig1 &= ~(WM9713_CTC | WM9713_COO);
+               dig2 &= ~WM97XX_SLEN;
+               dig3 &= ~WM9713_PDEN;
+               if (wm->mach_ops->acc_shutdown)
+                       wm->mach_ops->acc_shutdown(wm);
+       }
+
+       wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
+       wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
+       wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
+
+       return ret;
+}
+
+struct wm97xx_codec_drv wm9713_codec = {
+       .id = WM9713_ID2,
+       .name = "wm9713",
+       .poll_sample = wm9713_poll_sample,
+       .poll_touch = wm9713_poll_touch,
+       .acc_enable = wm9713_acc_enable,
+       .phy_init = wm9713_phy_init,
+       .dig_enable = wm9713_dig_enable,
+       .dig_restore = wm9713_dig_restore,
+       .aux_prepare = wm9713_aux_prepare,
+};
+EXPORT_SYMBOL_GPL(wm9713_codec);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
+MODULE_DESCRIPTION("WM9713 Touch Screen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
new file mode 100644 (file)
index 0000000..e9c7ea4
--- /dev/null
@@ -0,0 +1,829 @@
+/*
+ * wm97xx-core.c  --  Touch screen driver core for Wolfson WM9705, WM9712
+ *                    and WM9713 AC97 Codecs.
+ *
+ * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Parts Copyright : Ian Molton <spyro@f2s.com>
+ *                   Andrew Zabolotny <zap@homelink.ru>
+ *                   Russell King <rmk@arm.linux.org.uk>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ * Notes:
+ *
+ *  Features:
+ *       - supports WM9705, WM9712, WM9713
+ *       - polling mode
+ *       - continuous mode (arch-dependent)
+ *       - adjustable rpu/dpp settings
+ *       - adjustable pressure current
+ *       - adjustable sample settle delay
+ *       - 4 and 5 wire touchscreens (5 wire is WM9712 only)
+ *       - pen down detection
+ *       - battery monitor
+ *       - sample AUX adcs
+ *       - power management
+ *       - codec GPIO
+ *       - codec event notification
+ * Todo
+ *       - Support for async sampling control for noisy LCDs.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/workqueue.h>
+#include <linux/wm97xx.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#define TS_NAME                        "wm97xx"
+#define WM_CORE_VERSION                "1.00"
+#define DEFAULT_PRESSURE       0xb0c0
+
+
+/*
+ * Touchscreen absolute values
+ *
+ * These parameters are used to help the input layer discard out of
+ * range readings and reduce jitter etc.
+ *
+ *   o min, max:- indicate the min and max values your touch screen returns
+ *   o fuzz:- use a higher number to reduce jitter
+ *
+ * The default values correspond to Mainstone II in QVGA mode
+ *
+ * Please read
+ * Documentation/input/input-programming.txt for more details.
+ */
+
+static int abs_x[3] = {350, 3900, 5};
+module_param_array(abs_x, int, NULL, 0);
+MODULE_PARM_DESC(abs_x, "Touchscreen absolute X min, max, fuzz");
+
+static int abs_y[3] = {320, 3750, 40};
+module_param_array(abs_y, int, NULL, 0);
+MODULE_PARM_DESC(abs_y, "Touchscreen absolute Y min, max, fuzz");
+
+static int abs_p[3] = {0, 150, 4};
+module_param_array(abs_p, int, NULL, 0);
+MODULE_PARM_DESC(abs_p, "Touchscreen absolute Pressure min, max, fuzz");
+
+/*
+ * wm97xx IO access, all IO locking done by AC97 layer
+ */
+int wm97xx_reg_read(struct wm97xx *wm, u16 reg)
+{
+       if (wm->ac97)
+               return wm->ac97->bus->ops->read(wm->ac97, reg);
+       else
+               return -1;
+}
+EXPORT_SYMBOL_GPL(wm97xx_reg_read);
+
+void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val)
+{
+       /* cache digitiser registers */
+       if (reg >= AC97_WM9713_DIG1 && reg <= AC97_WM9713_DIG3)
+               wm->dig[(reg - AC97_WM9713_DIG1) >> 1] = val;
+
+       /* cache gpio regs */
+       if (reg >= AC97_GPIO_CFG && reg <= AC97_MISC_AFE)
+               wm->gpio[(reg - AC97_GPIO_CFG) >> 1] = val;
+
+       /* wm9713 irq reg */
+       if (reg == 0x5a)
+               wm->misc = val;
+
+       if (wm->ac97)
+               wm->ac97->bus->ops->write(wm->ac97, reg, val);
+}
+EXPORT_SYMBOL_GPL(wm97xx_reg_write);
+
+/**
+ * wm97xx_read_aux_adc - Read the aux adc.
+ * @wm: wm97xx device.
+ * @adcsel: codec ADC to be read
+ *
+ * Reads the selected AUX ADC.
+ */
+
+int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel)
+{
+       int power_adc = 0, auxval;
+       u16 power = 0;
+
+       /* get codec */
+       mutex_lock(&wm->codec_mutex);
+
+       /* When the touchscreen is not in use, we may have to power up
+        * the AUX ADC before we can use sample the AUX inputs->
+        */
+       if (wm->id == WM9713_ID2 &&
+           (power = wm97xx_reg_read(wm, AC97_EXTENDED_MID)) & 0x8000) {
+               power_adc = 1;
+               wm97xx_reg_write(wm, AC97_EXTENDED_MID, power & 0x7fff);
+       }
+
+       /* Prepare the codec for AUX reading */
+       wm->codec->aux_prepare(wm);
+
+       /* Turn polling mode on to read AUX ADC */
+       wm->pen_probably_down = 1;
+       wm->codec->poll_sample(wm, adcsel, &auxval);
+
+       if (power_adc)
+               wm97xx_reg_write(wm, AC97_EXTENDED_MID, power | 0x8000);
+
+       wm->codec->dig_restore(wm);
+
+       wm->pen_probably_down = 0;
+
+       mutex_unlock(&wm->codec_mutex);
+       return auxval & 0xfff;
+}
+EXPORT_SYMBOL_GPL(wm97xx_read_aux_adc);
+
+/**
+ * wm97xx_get_gpio - Get the status of a codec GPIO.
+ * @wm: wm97xx device.
+ * @gpio: gpio
+ *
+ * Get the status of a codec GPIO pin
+ */
+
+enum wm97xx_gpio_status wm97xx_get_gpio(struct wm97xx *wm, u32 gpio)
+{
+       u16 status;
+       enum wm97xx_gpio_status ret;
+
+       mutex_lock(&wm->codec_mutex);
+       status = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
+
+       if (status & gpio)
+               ret = WM97XX_GPIO_HIGH;
+       else
+               ret = WM97XX_GPIO_LOW;
+
+       mutex_unlock(&wm->codec_mutex);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm97xx_get_gpio);
+
+/**
+ * wm97xx_set_gpio - Set the status of a codec GPIO.
+ * @wm: wm97xx device.
+ * @gpio: gpio
+ *
+ *
+ * Set the status of a codec GPIO pin
+ */
+
+void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio,
+                               enum wm97xx_gpio_status status)
+{
+       u16 reg;
+
+       mutex_lock(&wm->codec_mutex);
+       reg = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
+
+       if (status & WM97XX_GPIO_HIGH)
+               reg |= gpio;
+       else
+               reg &= ~gpio;
+
+       if (wm->id == WM9712_ID2)
+               wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1);
+       else
+               wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg);
+       mutex_unlock(&wm->codec_mutex);
+}
+EXPORT_SYMBOL_GPL(wm97xx_set_gpio);
+
+/*
+ * Codec GPIO pin configuration, this sets pin direction, polarity,
+ * stickyness and wake up.
+ */
+void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio, enum wm97xx_gpio_dir dir,
+                  enum wm97xx_gpio_pol pol, enum wm97xx_gpio_sticky sticky,
+                  enum wm97xx_gpio_wake wake)
+{
+       u16 reg;
+
+       mutex_lock(&wm->codec_mutex);
+       reg = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
+
+       if (pol == WM97XX_GPIO_POL_HIGH)
+               reg |= gpio;
+       else
+               reg &= ~gpio;
+
+       wm97xx_reg_write(wm, AC97_GPIO_POLARITY, reg);
+       reg = wm97xx_reg_read(wm, AC97_GPIO_STICKY);
+
+       if (sticky == WM97XX_GPIO_STICKY)
+               reg |= gpio;
+       else
+               reg &= ~gpio;
+
+       wm97xx_reg_write(wm, AC97_GPIO_STICKY, reg);
+       reg = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP);
+
+       if (wake == WM97XX_GPIO_WAKE)
+               reg |= gpio;
+       else
+               reg &= ~gpio;
+
+       wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, reg);
+       reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
+
+       if (dir == WM97XX_GPIO_IN)
+               reg |= gpio;
+       else
+               reg &= ~gpio;
+
+       wm97xx_reg_write(wm, AC97_GPIO_CFG, reg);
+       mutex_unlock(&wm->codec_mutex);
+}
+EXPORT_SYMBOL_GPL(wm97xx_config_gpio);
+
+/*
+ * Configure the WM97XX_PRP value to use while system is suspended.
+ * If a value other than 0 is set then WM97xx pen detection will be
+ * left enabled in the configured mode while the system is in suspend,
+ * the device has users and suspend has not been disabled via the
+ * wakeup sysfs entries.
+ *
+ * @wm:   WM97xx device to configure
+ * @mode: WM97XX_PRP value to configure while suspended
+ */
+void wm97xx_set_suspend_mode(struct wm97xx *wm, u16 mode)
+{
+       wm->suspend_mode = mode;
+       device_init_wakeup(&wm->input_dev->dev, mode != 0);
+}
+EXPORT_SYMBOL_GPL(wm97xx_set_suspend_mode);
+
+/*
+ * Handle a pen down interrupt.
+ */
+static void wm97xx_pen_irq_worker(struct work_struct *work)
+{
+       struct wm97xx *wm = container_of(work, struct wm97xx, pen_event_work);
+       int pen_was_down = wm->pen_is_down;
+
+       /* do we need to enable the touch panel reader */
+       if (wm->id == WM9705_ID2) {
+               if (wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD) &
+                                       WM97XX_PEN_DOWN)
+                       wm->pen_is_down = 1;
+               else
+                       wm->pen_is_down = 0;
+       } else {
+               u16 status, pol;
+               mutex_lock(&wm->codec_mutex);
+               status = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
+               pol = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
+
+               if (WM97XX_GPIO_13 & pol & status) {
+                       wm->pen_is_down = 1;
+                       wm97xx_reg_write(wm, AC97_GPIO_POLARITY, pol &
+                                               ~WM97XX_GPIO_13);
+               } else {
+                       wm->pen_is_down = 0;
+                       wm97xx_reg_write(wm, AC97_GPIO_POLARITY, pol |
+                                        WM97XX_GPIO_13);
+               }
+
+               if (wm->id == WM9712_ID2)
+                       wm97xx_reg_write(wm, AC97_GPIO_STATUS, (status &
+                                               ~WM97XX_GPIO_13) << 1);
+               else
+                       wm97xx_reg_write(wm, AC97_GPIO_STATUS, status &
+                                               ~WM97XX_GPIO_13);
+               mutex_unlock(&wm->codec_mutex);
+       }
+
+       /* If the system is not using continuous mode or it provides a
+        * pen down operation then we need to schedule polls while the
+        * pen is down.  Otherwise the machine driver is responsible
+        * for scheduling reads.
+        */
+       if (!wm->mach_ops->acc_enabled || wm->mach_ops->acc_pen_down) {
+               if (wm->pen_is_down && !pen_was_down) {
+                       /* Data is not availiable immediately on pen down */
+                       queue_delayed_work(wm->ts_workq, &wm->ts_reader, 1);
+               }
+
+               /* Let ts_reader report the pen up for debounce. */
+               if (!wm->pen_is_down && pen_was_down)
+                       wm->pen_is_down = 1;
+       }
+
+       if (!wm->pen_is_down && wm->mach_ops->acc_enabled)
+               wm->mach_ops->acc_pen_up(wm);
+
+       wm->mach_ops->irq_enable(wm, 1);
+}
+
+/*
+ * Codec PENDOWN irq handler
+ *
+ * We have to disable the codec interrupt in the handler because it
+ * can take upto 1ms to clear the interrupt source. We schedule a task
+ * in a work queue to do the actual interaction with the chip.  The
+ * interrupt is then enabled again in the slow handler when the source
+ * has been cleared.
+ */
+static irqreturn_t wm97xx_pen_interrupt(int irq, void *dev_id)
+{
+       struct wm97xx *wm = dev_id;
+
+       if (!work_pending(&wm->pen_event_work)) {
+               wm->mach_ops->irq_enable(wm, 0);
+               queue_work(wm->ts_workq, &wm->pen_event_work);
+       }
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * initialise pen IRQ handler and workqueue
+ */
+static int wm97xx_init_pen_irq(struct wm97xx *wm)
+{
+       u16 reg;
+
+       /* If an interrupt is supplied an IRQ enable operation must also be
+        * provided. */
+       BUG_ON(!wm->mach_ops->irq_enable);
+
+       if (request_irq(wm->pen_irq, wm97xx_pen_interrupt,
+                       IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+                       "wm97xx-pen", wm)) {
+               dev_err(wm->dev,
+                       "Failed to register pen down interrupt, polling");
+               wm->pen_irq = 0;
+               return -EINVAL;
+       }
+
+       /* Configure GPIO as interrupt source on WM971x */
+       if (wm->id != WM9705_ID2) {
+               BUG_ON(!wm->mach_ops->irq_gpio);
+               reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
+               wm97xx_reg_write(wm, AC97_MISC_AFE,
+                               reg & ~(wm->mach_ops->irq_gpio));
+               reg = wm97xx_reg_read(wm, 0x5a);
+               wm97xx_reg_write(wm, 0x5a, reg & ~0x0001);
+       }
+
+       return 0;
+}
+
+static int wm97xx_read_samples(struct wm97xx *wm)
+{
+       struct wm97xx_data data;
+       int rc;
+
+       mutex_lock(&wm->codec_mutex);
+
+       if (wm->mach_ops && wm->mach_ops->acc_enabled)
+               rc = wm->mach_ops->acc_pen_down(wm);
+       else
+               rc = wm->codec->poll_touch(wm, &data);
+
+       if (rc & RC_PENUP) {
+               if (wm->pen_is_down) {
+                       wm->pen_is_down = 0;
+                       dev_dbg(wm->dev, "pen up\n");
+                       input_report_abs(wm->input_dev, ABS_PRESSURE, 0);
+                       input_sync(wm->input_dev);
+               } else if (!(rc & RC_AGAIN)) {
+                       /* We need high frequency updates only while
+                       * pen is down, the user never will be able to
+                       * touch screen faster than a few times per
+                       * second... On the other hand, when the user
+                       * is actively working with the touchscreen we
+                       * don't want to lose the quick response. So we
+                       * will slowly increase sleep time after the
+                       * pen is up and quicky restore it to ~one task
+                       * switch when pen is down again.
+                       */
+                       if (wm->ts_reader_interval < HZ / 10)
+                               wm->ts_reader_interval++;
+               }
+
+       } else if (rc & RC_VALID) {
+               dev_dbg(wm->dev,
+                       "pen down: x=%x:%d, y=%x:%d, pressure=%x:%d\n",
+                       data.x >> 12, data.x & 0xfff, data.y >> 12,
+                       data.y & 0xfff, data.p >> 12, data.p & 0xfff);
+               input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff);
+               input_report_abs(wm->input_dev, ABS_Y, data.y & 0xfff);
+               input_report_abs(wm->input_dev, ABS_PRESSURE, data.p & 0xfff);
+               input_sync(wm->input_dev);
+               wm->pen_is_down = 1;
+               wm->ts_reader_interval = wm->ts_reader_min_interval;
+       } else if (rc & RC_PENDOWN) {
+               dev_dbg(wm->dev, "pen down\n");
+               wm->pen_is_down = 1;
+               wm->ts_reader_interval = wm->ts_reader_min_interval;
+       }
+
+       mutex_unlock(&wm->codec_mutex);
+       return rc;
+}
+
+/*
+* The touchscreen sample reader.
+*/
+static void wm97xx_ts_reader(struct work_struct *work)
+{
+       int rc;
+       struct wm97xx *wm = container_of(work, struct wm97xx, ts_reader.work);
+
+       BUG_ON(!wm->codec);
+
+       do {
+               rc = wm97xx_read_samples(wm);
+       } while (rc & RC_AGAIN);
+
+       if (wm->pen_is_down || !wm->pen_irq)
+               queue_delayed_work(wm->ts_workq, &wm->ts_reader,
+                                  wm->ts_reader_interval);
+}
+
+/**
+ * wm97xx_ts_input_open - Open the touch screen input device.
+ * @idev:      Input device to be opened.
+ *
+ * Called by the input sub system to open a wm97xx touchscreen device.
+ * Starts the touchscreen thread and touch digitiser.
+ */
+static int wm97xx_ts_input_open(struct input_dev *idev)
+{
+       struct wm97xx *wm = input_get_drvdata(idev);
+
+       wm->ts_workq = create_singlethread_workqueue("kwm97xx");
+       if (wm->ts_workq == NULL) {
+               dev_err(wm->dev,
+                       "Failed to create workqueue\n");
+               return -EINVAL;
+       }
+
+       /* start digitiser */
+       if (wm->mach_ops && wm->mach_ops->acc_enabled)
+               wm->codec->acc_enable(wm, 1);
+       wm->codec->dig_enable(wm, 1);
+
+       INIT_DELAYED_WORK(&wm->ts_reader, wm97xx_ts_reader);
+       INIT_WORK(&wm->pen_event_work, wm97xx_pen_irq_worker);
+
+       wm->ts_reader_min_interval = HZ >= 100 ? HZ / 100 : 1;
+       if (wm->ts_reader_min_interval < 1)
+               wm->ts_reader_min_interval = 1;
+       wm->ts_reader_interval = wm->ts_reader_min_interval;
+
+       wm->pen_is_down = 0;
+       if (wm->pen_irq)
+               wm97xx_init_pen_irq(wm);
+       else
+               dev_err(wm->dev, "No IRQ specified\n");
+
+       /* If we either don't have an interrupt for pen down events or
+        * failed to acquire it then we need to poll.
+        */
+       if (wm->pen_irq == 0)
+               queue_delayed_work(wm->ts_workq, &wm->ts_reader,
+                                  wm->ts_reader_interval);
+
+       return 0;
+}
+
+/**
+ * wm97xx_ts_input_close - Close the touch screen input device.
+ * @idev:      Input device to be closed.
+ *
+ * Called by the input sub system to close a wm97xx touchscreen
+ * device.  Kills the touchscreen thread and stops the touch
+ * digitiser.
+ */
+
+static void wm97xx_ts_input_close(struct input_dev *idev)
+{
+       struct wm97xx *wm = input_get_drvdata(idev);
+       u16 reg;
+
+       if (wm->pen_irq) {
+               /* Return the interrupt to GPIO usage (disabling it) */
+               if (wm->id != WM9705_ID2) {
+                       BUG_ON(!wm->mach_ops->irq_gpio);
+                       reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
+                       wm97xx_reg_write(wm, AC97_MISC_AFE,
+                                        reg | wm->mach_ops->irq_gpio);
+               }
+
+               free_irq(wm->pen_irq, wm);
+       }
+
+       wm->pen_is_down = 0;
+
+       /* Balance out interrupt disables/enables */
+       if (cancel_work_sync(&wm->pen_event_work))
+               wm->mach_ops->irq_enable(wm, 1);
+
+       /* ts_reader rearms itself so we need to explicitly stop it
+        * before we destroy the workqueue.
+        */
+       cancel_delayed_work_sync(&wm->ts_reader);
+
+       destroy_workqueue(wm->ts_workq);
+
+       /* stop digitiser */
+       wm->codec->dig_enable(wm, 0);
+       if (wm->mach_ops && wm->mach_ops->acc_enabled)
+               wm->codec->acc_enable(wm, 0);
+}
+
+static int wm97xx_probe(struct device *dev)
+{
+       struct wm97xx *wm;
+       int ret = 0, id = 0;
+
+       wm = kzalloc(sizeof(struct wm97xx), GFP_KERNEL);
+       if (!wm)
+               return -ENOMEM;
+       mutex_init(&wm->codec_mutex);
+
+       wm->dev = dev;
+       dev->driver_data = wm;
+       wm->ac97 = to_ac97_t(dev);
+
+       /* check that we have a supported codec */
+       id = wm97xx_reg_read(wm, AC97_VENDOR_ID1);
+       if (id != WM97XX_ID1) {
+               dev_err(dev, "Device with vendor %04x is not a wm97xx\n", id);
+               ret = -ENODEV;
+               goto alloc_err;
+       }
+
+       wm->id = wm97xx_reg_read(wm, AC97_VENDOR_ID2);
+
+       dev_info(wm->dev, "detected a wm97%02x codec\n", wm->id & 0xff);
+
+       switch (wm->id & 0xff) {
+#ifdef CONFIG_TOUCHSCREEN_WM9705
+       case 0x05:
+               wm->codec = &wm9705_codec;
+               break;
+#endif
+#ifdef CONFIG_TOUCHSCREEN_WM9712
+       case 0x12:
+               wm->codec = &wm9712_codec;
+               break;
+#endif
+#ifdef CONFIG_TOUCHSCREEN_WM9713
+       case 0x13:
+               wm->codec = &wm9713_codec;
+               break;
+#endif
+       default:
+               dev_err(wm->dev, "Support for wm97%02x not compiled in.\n",
+                       wm->id & 0xff);
+               ret = -ENODEV;
+               goto alloc_err;
+       }
+
+       wm->input_dev = input_allocate_device();
+       if (wm->input_dev == NULL) {
+               ret = -ENOMEM;
+               goto alloc_err;
+       }
+
+       /* set up touch configuration */
+       wm->input_dev->name = "wm97xx touchscreen";
+       wm->input_dev->open = wm97xx_ts_input_open;
+       wm->input_dev->close = wm97xx_ts_input_close;
+       set_bit(EV_ABS, wm->input_dev->evbit);
+       set_bit(ABS_X, wm->input_dev->absbit);
+       set_bit(ABS_Y, wm->input_dev->absbit);
+       set_bit(ABS_PRESSURE, wm->input_dev->absbit);
+       input_set_abs_params(wm->input_dev, ABS_X, abs_x[0], abs_x[1],
+                            abs_x[2], 0);
+       input_set_abs_params(wm->input_dev, ABS_Y, abs_y[0], abs_y[1],
+                            abs_y[2], 0);
+       input_set_abs_params(wm->input_dev, ABS_PRESSURE, abs_p[0], abs_p[1],
+                            abs_p[2], 0);
+       input_set_drvdata(wm->input_dev, wm);
+       wm->input_dev->dev.parent = dev;
+       ret = input_register_device(wm->input_dev);
+       if (ret < 0)
+               goto dev_alloc_err;
+
+       /* set up physical characteristics */
+       wm->codec->phy_init(wm);
+
+       /* load gpio cache */
+       wm->gpio[0] = wm97xx_reg_read(wm, AC97_GPIO_CFG);
+       wm->gpio[1] = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
+       wm->gpio[2] = wm97xx_reg_read(wm, AC97_GPIO_STICKY);
+       wm->gpio[3] = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP);
+       wm->gpio[4] = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
+       wm->gpio[5] = wm97xx_reg_read(wm, AC97_MISC_AFE);
+
+       /* register our battery device */
+       wm->battery_dev = platform_device_alloc("wm97xx-battery", -1);
+       if (!wm->battery_dev) {
+               ret = -ENOMEM;
+               goto batt_err;
+       }
+       platform_set_drvdata(wm->battery_dev, wm);
+       wm->battery_dev->dev.parent = dev;
+       ret = platform_device_add(wm->battery_dev);
+       if (ret < 0)
+               goto batt_reg_err;
+
+       /* register our extended touch device (for machine specific
+        * extensions) */
+       wm->touch_dev = platform_device_alloc("wm97xx-touch", -1);
+       if (!wm->touch_dev) {
+               ret = -ENOMEM;
+               goto touch_err;
+       }
+       platform_set_drvdata(wm->touch_dev, wm);
+       wm->touch_dev->dev.parent = dev;
+       ret = platform_device_add(wm->touch_dev);
+       if (ret < 0)
+               goto touch_reg_err;
+
+       return ret;
+
+ touch_reg_err:
+       platform_device_put(wm->touch_dev);
+ touch_err:
+       platform_device_unregister(wm->battery_dev);
+       wm->battery_dev = NULL;
+ batt_reg_err:
+       platform_device_put(wm->battery_dev);
+ batt_err:
+       input_unregister_device(wm->input_dev);
+       wm->input_dev = NULL;
+ dev_alloc_err:
+       input_free_device(wm->input_dev);
+ alloc_err:
+       kfree(wm);
+
+       return ret;
+}
+
+static int wm97xx_remove(struct device *dev)
+{
+       struct wm97xx *wm = dev_get_drvdata(dev);
+
+       platform_device_unregister(wm->battery_dev);
+       platform_device_unregister(wm->touch_dev);
+       input_unregister_device(wm->input_dev);
+       kfree(wm);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int wm97xx_suspend(struct device *dev, pm_message_t state)
+{
+       struct wm97xx *wm = dev_get_drvdata(dev);
+       u16 reg;
+       int suspend_mode;
+
+       if (device_may_wakeup(&wm->input_dev->dev))
+               suspend_mode = wm->suspend_mode;
+       else
+               suspend_mode = 0;
+
+       if (wm->input_dev->users)
+               cancel_delayed_work_sync(&wm->ts_reader);
+
+       /* Power down the digitiser (bypassing the cache for resume) */
+       reg = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER2);
+       reg &= ~WM97XX_PRP_DET_DIG;
+       if (wm->input_dev->users)
+               reg |= suspend_mode;
+       wm->ac97->bus->ops->write(wm->ac97, AC97_WM97XX_DIGITISER2, reg);
+
+       /* WM9713 has an additional power bit - turn it off if there
+        * are no users or if suspend mode is zero. */
+       if (wm->id == WM9713_ID2 &&
+           (!wm->input_dev->users || !suspend_mode)) {
+               reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) | 0x8000;
+               wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
+       }
+
+       return 0;
+}
+
+static int wm97xx_resume(struct device *dev)
+{
+       struct wm97xx *wm = dev_get_drvdata(dev);
+
+       /* restore digitiser and gpios */
+       if (wm->id == WM9713_ID2) {
+               wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig[0]);
+               wm97xx_reg_write(wm, 0x5a, wm->misc);
+               if (wm->input_dev->users) {
+                       u16 reg;
+                       reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) & 0x7fff;
+                       wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
+               }
+       }
+
+       wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig[1]);
+       wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2]);
+
+       wm97xx_reg_write(wm, AC97_GPIO_CFG, wm->gpio[0]);
+       wm97xx_reg_write(wm, AC97_GPIO_POLARITY, wm->gpio[1]);
+       wm97xx_reg_write(wm, AC97_GPIO_STICKY, wm->gpio[2]);
+       wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, wm->gpio[3]);
+       wm97xx_reg_write(wm, AC97_GPIO_STATUS, wm->gpio[4]);
+       wm97xx_reg_write(wm, AC97_MISC_AFE, wm->gpio[5]);
+
+       if (wm->input_dev->users && !wm->pen_irq) {
+               wm->ts_reader_interval = wm->ts_reader_min_interval;
+               queue_delayed_work(wm->ts_workq, &wm->ts_reader,
+                                  wm->ts_reader_interval);
+       }
+
+       return 0;
+}
+
+#else
+#define wm97xx_suspend         NULL
+#define wm97xx_resume          NULL
+#endif
+
+/*
+ * Machine specific operations
+ */
+int wm97xx_register_mach_ops(struct wm97xx *wm,
+                            struct wm97xx_mach_ops *mach_ops)
+{
+       mutex_lock(&wm->codec_mutex);
+       if (wm->mach_ops) {
+               mutex_unlock(&wm->codec_mutex);
+               return -EINVAL;
+       }
+       wm->mach_ops = mach_ops;
+       mutex_unlock(&wm->codec_mutex);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm97xx_register_mach_ops);
+
+void wm97xx_unregister_mach_ops(struct wm97xx *wm)
+{
+       mutex_lock(&wm->codec_mutex);
+       wm->mach_ops = NULL;
+       mutex_unlock(&wm->codec_mutex);
+}
+EXPORT_SYMBOL_GPL(wm97xx_unregister_mach_ops);
+
+static struct device_driver wm97xx_driver = {
+       .name =         "ac97",
+       .bus =          &ac97_bus_type,
+       .owner =        THIS_MODULE,
+       .probe =        wm97xx_probe,
+       .remove =       wm97xx_remove,
+       .suspend =      wm97xx_suspend,
+       .resume =       wm97xx_resume,
+};
+
+static int __init wm97xx_init(void)
+{
+       return driver_register(&wm97xx_driver);
+}
+
+static void __exit wm97xx_exit(void)
+{
+       driver_unregister(&wm97xx_driver);
+}
+
+module_init(wm97xx_init);
+module_exit(wm97xx_exit);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
+MODULE_DESCRIPTION("WM97xx Core - Touch Screen / AUX ADC / GPIO Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c
new file mode 100644 (file)
index 0000000..0f47f46
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ * Xen para-virtual input device
+ *
+ * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
+ * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
+ *
+ *  Based on linux/drivers/input/mouse/sermouse.c
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+/*
+ * TODO:
+ *
+ * Switch to grant tables together with xen-fbfront.c.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <asm/xen/hypervisor.h>
+#include <xen/events.h>
+#include <xen/page.h>
+#include <xen/interface/io/fbif.h>
+#include <xen/interface/io/kbdif.h>
+#include <xen/xenbus.h>
+
+struct xenkbd_info {
+       struct input_dev *kbd;
+       struct input_dev *ptr;
+       struct xenkbd_page *page;
+       int irq;
+       struct xenbus_device *xbdev;
+       char phys[32];
+};
+
+static int xenkbd_remove(struct xenbus_device *);
+static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
+static void xenkbd_disconnect_backend(struct xenkbd_info *);
+
+/*
+ * Note: if you need to send out events, see xenfb_do_update() for how
+ * to do that.
+ */
+
+static irqreturn_t input_handler(int rq, void *dev_id)
+{
+       struct xenkbd_info *info = dev_id;
+       struct xenkbd_page *page = info->page;
+       __u32 cons, prod;
+
+       prod = page->in_prod;
+       if (prod == page->in_cons)
+               return IRQ_HANDLED;
+       rmb();                  /* ensure we see ring contents up to prod */
+       for (cons = page->in_cons; cons != prod; cons++) {
+               union xenkbd_in_event *event;
+               struct input_dev *dev;
+               event = &XENKBD_IN_RING_REF(page, cons);
+
+               dev = info->ptr;
+               switch (event->type) {
+               case XENKBD_TYPE_MOTION:
+                       input_report_rel(dev, REL_X, event->motion.rel_x);
+                       input_report_rel(dev, REL_Y, event->motion.rel_y);
+                       break;
+               case XENKBD_TYPE_KEY:
+                       dev = NULL;
+                       if (test_bit(event->key.keycode, info->kbd->keybit))
+                               dev = info->kbd;
+                       if (test_bit(event->key.keycode, info->ptr->keybit))
+                               dev = info->ptr;
+                       if (dev)
+                               input_report_key(dev, event->key.keycode,
+                                                event->key.pressed);
+                       else
+                               printk(KERN_WARNING
+                                      "xenkbd: unhandled keycode 0x%x\n",
+                                      event->key.keycode);
+                       break;
+               case XENKBD_TYPE_POS:
+                       input_report_abs(dev, ABS_X, event->pos.abs_x);
+                       input_report_abs(dev, ABS_Y, event->pos.abs_y);
+                       break;
+               }
+               if (dev)
+                       input_sync(dev);
+       }
+       mb();                   /* ensure we got ring contents */
+       page->in_cons = cons;
+       notify_remote_via_irq(info->irq);
+
+       return IRQ_HANDLED;
+}
+
+static int __devinit xenkbd_probe(struct xenbus_device *dev,
+                                 const struct xenbus_device_id *id)
+{
+       int ret, i;
+       struct xenkbd_info *info;
+       struct input_dev *kbd, *ptr;
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info) {
+               xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
+               return -ENOMEM;
+       }
+       dev->dev.driver_data = info;
+       info->xbdev = dev;
+       info->irq = -1;
+       snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
+
+       info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+       if (!info->page)
+               goto error_nomem;
+
+       /* keyboard */
+       kbd = input_allocate_device();
+       if (!kbd)
+               goto error_nomem;
+       kbd->name = "Xen Virtual Keyboard";
+       kbd->phys = info->phys;
+       kbd->id.bustype = BUS_PCI;
+       kbd->id.vendor = 0x5853;
+       kbd->id.product = 0xffff;
+       kbd->evbit[0] = BIT(EV_KEY);
+       for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
+               set_bit(i, kbd->keybit);
+       for (i = KEY_OK; i < KEY_MAX; i++)
+               set_bit(i, kbd->keybit);
+
+       ret = input_register_device(kbd);
+       if (ret) {
+               input_free_device(kbd);
+               xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
+               goto error;
+       }
+       info->kbd = kbd;
+
+       /* pointing device */
+       ptr = input_allocate_device();
+       if (!ptr)
+               goto error_nomem;
+       ptr->name = "Xen Virtual Pointer";
+       ptr->phys = info->phys;
+       ptr->id.bustype = BUS_PCI;
+       ptr->id.vendor = 0x5853;
+       ptr->id.product = 0xfffe;
+       ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
+       for (i = BTN_LEFT; i <= BTN_TASK; i++)
+               set_bit(i, ptr->keybit);
+       ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+       input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
+       input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
+
+       ret = input_register_device(ptr);
+       if (ret) {
+               input_free_device(ptr);
+               xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
+               goto error;
+       }
+       info->ptr = ptr;
+
+       ret = xenkbd_connect_backend(dev, info);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+
+ error_nomem:
+       ret = -ENOMEM;
+       xenbus_dev_fatal(dev, ret, "allocating device memory");
+ error:
+       xenkbd_remove(dev);
+       return ret;
+}
+
+static int xenkbd_resume(struct xenbus_device *dev)
+{
+       struct xenkbd_info *info = dev->dev.driver_data;
+
+       xenkbd_disconnect_backend(info);
+       memset(info->page, 0, PAGE_SIZE);
+       return xenkbd_connect_backend(dev, info);
+}
+
+static int xenkbd_remove(struct xenbus_device *dev)
+{
+       struct xenkbd_info *info = dev->dev.driver_data;
+
+       xenkbd_disconnect_backend(info);
+       if (info->kbd)
+               input_unregister_device(info->kbd);
+       if (info->ptr)
+               input_unregister_device(info->ptr);
+       free_page((unsigned long)info->page);
+       kfree(info);
+       return 0;
+}
+
+static int xenkbd_connect_backend(struct xenbus_device *dev,
+                                 struct xenkbd_info *info)
+{
+       int ret, evtchn;
+       struct xenbus_transaction xbt;
+
+       ret = xenbus_alloc_evtchn(dev, &evtchn);
+       if (ret)
+               return ret;
+       ret = bind_evtchn_to_irqhandler(evtchn, input_handler,
+                                       0, dev->devicetype, info);
+       if (ret < 0) {
+               xenbus_free_evtchn(dev, evtchn);
+               xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
+               return ret;
+       }
+       info->irq = ret;
+
+ again:
+       ret = xenbus_transaction_start(&xbt);
+       if (ret) {
+               xenbus_dev_fatal(dev, ret, "starting transaction");
+               return ret;
+       }
+       ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
+                           virt_to_mfn(info->page));
+       if (ret)
+               goto error_xenbus;
+       ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
+                           evtchn);
+       if (ret)
+               goto error_xenbus;
+       ret = xenbus_transaction_end(xbt, 0);
+       if (ret) {
+               if (ret == -EAGAIN)
+                       goto again;
+               xenbus_dev_fatal(dev, ret, "completing transaction");
+               return ret;
+       }
+
+       xenbus_switch_state(dev, XenbusStateInitialised);
+       return 0;
+
+ error_xenbus:
+       xenbus_transaction_end(xbt, 1);
+       xenbus_dev_fatal(dev, ret, "writing xenstore");
+       return ret;
+}
+
+static void xenkbd_disconnect_backend(struct xenkbd_info *info)
+{
+       if (info->irq >= 0)
+               unbind_from_irqhandler(info->irq, info);
+       info->irq = -1;
+}
+
+static void xenkbd_backend_changed(struct xenbus_device *dev,
+                                  enum xenbus_state backend_state)
+{
+       struct xenkbd_info *info = dev->dev.driver_data;
+       int ret, val;
+
+       switch (backend_state) {
+       case XenbusStateInitialising:
+       case XenbusStateInitialised:
+       case XenbusStateUnknown:
+       case XenbusStateClosed:
+               break;
+
+       case XenbusStateInitWait:
+InitWait:
+               ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+                                  "feature-abs-pointer", "%d", &val);
+               if (ret < 0)
+                       val = 0;
+               if (val) {
+                       ret = xenbus_printf(XBT_NIL, info->xbdev->nodename,
+                                           "request-abs-pointer", "1");
+                       if (ret)
+                               printk(KERN_WARNING
+                                      "xenkbd: can't request abs-pointer");
+               }
+               xenbus_switch_state(dev, XenbusStateConnected);
+               break;
+
+       case XenbusStateConnected:
+               /*
+                * Work around xenbus race condition: If backend goes
+                * through InitWait to Connected fast enough, we can
+                * get Connected twice here.
+                */
+               if (dev->state != XenbusStateConnected)
+                       goto InitWait; /* no InitWait seen yet, fudge it */
+               break;
+
+       case XenbusStateClosing:
+               xenbus_frontend_closed(dev);
+               break;
+       }
+}
+
+static struct xenbus_device_id xenkbd_ids[] = {
+       { "vkbd" },
+       { "" }
+};
+
+static struct xenbus_driver xenkbd = {
+       .name = "vkbd",
+       .owner = THIS_MODULE,
+       .ids = xenkbd_ids,
+       .probe = xenkbd_probe,
+       .remove = xenkbd_remove,
+       .resume = xenkbd_resume,
+       .otherend_changed = xenkbd_backend_changed,
+};
+
+static int __init xenkbd_init(void)
+{
+       if (!is_running_on_xen())
+               return -ENODEV;
+
+       /* Nothing to do if running in dom0. */
+       if (is_initial_xendomain())
+               return -ENODEV;
+
+       return xenbus_register_frontend(&xenkbd);
+}
+
+static void __exit xenkbd_cleanup(void)
+{
+       xenbus_unregister_driver(&xenkbd);
+}
+
+module_init(xenkbd_init);
+module_exit(xenkbd_cleanup);
+
+MODULE_LICENSE("GPL");
index eb97c4113d786d25d5106bbf71a78e7581ea3391..86a369bc57d6d91c9137da6940904d6172cf9f90 100644 (file)
@@ -65,6 +65,12 @@ config LEDS_NET48XX
          This option enables support for the Soekris net4801 and net4826 error
          LED.
 
+config LEDS_FSG
+       tristate "LED Support for the Freecom FSG-3"
+       depends on LEDS_CLASS && MACH_FSG
+       help
+         This option enables support for the LEDs on the Freecom FSG-3.
+
 config LEDS_WRAP
        tristate "LED Support for the WRAP series LEDs"
        depends on LEDS_CLASS && SCx200_GPIO
@@ -127,6 +133,7 @@ config LEDS_CLEVO_MAIL
 
          This module can drive the mail LED for the following notebooks:
 
+               Clevo D400P
                Clevo D410J
                Clevo D410V
                Clevo D400V/D470V (not tested, but might work)
@@ -134,6 +141,9 @@ config LEDS_CLEVO_MAIL
                Clevo M5x0N (not tested, but might work)
                Positivo Mobile (Clevo M5x0V)
 
+         If your model is not listed here you can try the "nodetect"
+         module paramter.
+
          To compile this driver as a module, choose M here: the
          module will be called leds-clevo-mail.
 
@@ -173,4 +183,11 @@ config LEDS_TRIGGER_HEARTBEAT
          load average.
          If unsure, say Y.
 
+config LEDS_TRIGGER_DEFAULT_ON
+       tristate "LED Default ON Trigger"
+       depends on LEDS_TRIGGERS
+       help
+         This allows LEDs to be initialised in the ON state.
+         If unsure, say Y.
+
 endif # NEW_LEDS
index e54f42da21a225e3f4e689952d7f25280e0340fc..973d626f5f4a98d582b02eeeb9113728ba605cf3 100644 (file)
@@ -20,8 +20,10 @@ obj-$(CONFIG_LEDS_GPIO)                      += leds-gpio.o
 obj-$(CONFIG_LEDS_CM_X270)              += leds-cm-x270.o
 obj-$(CONFIG_LEDS_CLEVO_MAIL)          += leds-clevo-mail.o
 obj-$(CONFIG_LEDS_HP6XX)               += leds-hp6xx.o
+obj-$(CONFIG_LEDS_FSG)                 += leds-fsg.o
 
 # LED Triggers
 obj-$(CONFIG_LEDS_TRIGGER_TIMER)       += ledtrig-timer.o
 obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK)    += ledtrig-ide-disk.o
 obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT)   += ledtrig-heartbeat.o
+obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)  += ledtrig-default-on.o
index 63aad90247c49483554c6af4d59cd6b57b1669f2..ac05a928f7642a54a51a0627e6ca7dc904511d09 100644 (file)
 
 static struct class *leds_class;
 
+static void led_update_brightness(struct led_classdev *led_cdev)
+{
+       if (led_cdev->brightness_get)
+               led_cdev->brightness = led_cdev->brightness_get(led_cdev);
+}
+
 static ssize_t led_brightness_show(struct device *dev, 
                struct device_attribute *attr, char *buf)
 {
@@ -31,6 +37,7 @@ static ssize_t led_brightness_show(struct device *dev,
        ssize_t ret = 0;
 
        /* no lock needed for this */
+       led_update_brightness(led_cdev);
        sprintf(buf, "%u\n", led_cdev->brightness);
        ret = strlen(buf) + 1;
 
@@ -51,6 +58,9 @@ static ssize_t led_brightness_store(struct device *dev,
 
        if (count == size) {
                ret = count;
+
+               if (state == LED_OFF)
+                       led_trigger_remove(led_cdev);
                led_set_brightness(led_cdev, state);
        }
 
@@ -110,6 +120,8 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
        list_add_tail(&led_cdev->node, &leds_list);
        up_write(&leds_list_lock);
 
+       led_update_brightness(led_cdev);
+
 #ifdef CONFIG_LEDS_TRIGGERS
        init_rwsem(&led_cdev->trigger_lock);
 
index 5d1ca10524b6933bc216fb282815ac6f348cc9d0..016d19f5486f2bd7cf9ea93df863f7d5c8a8cd1a 100644 (file)
@@ -19,7 +19,7 @@
 #include "leds.h"
 
 DECLARE_RWSEM(leds_list_lock);
-LIST_HEAD(leds_list);
+EXPORT_SYMBOL_GPL(leds_list_lock);
 
+LIST_HEAD(leds_list);
 EXPORT_SYMBOL_GPL(leds_list);
-EXPORT_SYMBOL_GPL(leds_list_lock);
index 13c9026d68af0af90e246824df1429496afe6814..0f242b3f09b6b7018354952e7a01bae8b37d6071 100644 (file)
@@ -29,6 +29,8 @@
 static DECLARE_RWSEM(triggers_list_lock);
 static LIST_HEAD(trigger_list);
 
+ /* Used by LED Class */
+
 ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
                const char *buf, size_t count)
 {
@@ -45,9 +47,7 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
                trigger_name[len - 1] = '\0';
 
        if (!strcmp(trigger_name, "none")) {
-               down_write(&led_cdev->trigger_lock);
-               led_trigger_set(led_cdev, NULL);
-               up_write(&led_cdev->trigger_lock);
+               led_trigger_remove(led_cdev);
                return count;
        }
 
@@ -66,7 +66,7 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
 
        return -EINVAL;
 }
-
+EXPORT_SYMBOL_GPL(led_trigger_store);
 
 ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
                char *buf)
@@ -96,24 +96,7 @@ ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
        len += sprintf(len+buf, "\n");
        return len;
 }
-
-void led_trigger_event(struct led_trigger *trigger,
-                       enum led_brightness brightness)
-{
-       struct list_head *entry;
-
-       if (!trigger)
-               return;
-
-       read_lock(&trigger->leddev_list_lock);
-       list_for_each(entry, &trigger->led_cdevs) {
-               struct led_classdev *led_cdev;
-
-               led_cdev = list_entry(entry, struct led_classdev, trig_list);
-               led_set_brightness(led_cdev, brightness);
-       }
-       read_unlock(&trigger->leddev_list_lock);
-}
+EXPORT_SYMBOL_GPL(led_trigger_show);
 
 /* Caller must ensure led_cdev->trigger_lock held */
 void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
@@ -124,7 +107,8 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
        if (led_cdev->trigger) {
                write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags);
                list_del(&led_cdev->trig_list);
-               write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags);
+               write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock,
+                       flags);
                if (led_cdev->trigger->deactivate)
                        led_cdev->trigger->deactivate(led_cdev);
                led_set_brightness(led_cdev, LED_OFF);
@@ -138,6 +122,15 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
        }
        led_cdev->trigger = trigger;
 }
+EXPORT_SYMBOL_GPL(led_trigger_set);
+
+void led_trigger_remove(struct led_classdev *led_cdev)
+{
+       down_write(&led_cdev->trigger_lock);
+       led_trigger_set(led_cdev, NULL);
+       up_write(&led_cdev->trigger_lock);
+}
+EXPORT_SYMBOL_GPL(led_trigger_remove);
 
 void led_trigger_set_default(struct led_classdev *led_cdev)
 {
@@ -155,6 +148,9 @@ void led_trigger_set_default(struct led_classdev *led_cdev)
        up_write(&led_cdev->trigger_lock);
        up_read(&triggers_list_lock);
 }
+EXPORT_SYMBOL_GPL(led_trigger_set_default);
+
+/* LED Trigger Interface */
 
 int led_trigger_register(struct led_trigger *trigger)
 {
@@ -181,26 +177,7 @@ int led_trigger_register(struct led_trigger *trigger)
 
        return 0;
 }
-
-void led_trigger_register_simple(const char *name, struct led_trigger **tp)
-{
-       struct led_trigger *trigger;
-       int err;
-
-       trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
-
-       if (trigger) {
-               trigger->name = name;
-               err = led_trigger_register(trigger);
-               if (err < 0)
-                       printk(KERN_WARNING "LED trigger %s failed to register"
-                               " (%d)\n", name, err);
-       } else
-               printk(KERN_WARNING "LED trigger %s failed to register"
-                       " (no memory)\n", name);
-
-       *tp = trigger;
-}
+EXPORT_SYMBOL_GPL(led_trigger_register);
 
 void led_trigger_unregister(struct led_trigger *trigger)
 {
@@ -221,6 +198,49 @@ void led_trigger_unregister(struct led_trigger *trigger)
        }
        up_read(&leds_list_lock);
 }
+EXPORT_SYMBOL_GPL(led_trigger_unregister);
+
+/* Simple LED Tigger Interface */
+
+void led_trigger_event(struct led_trigger *trigger,
+                       enum led_brightness brightness)
+{
+       struct list_head *entry;
+
+       if (!trigger)
+               return;
+
+       read_lock(&trigger->leddev_list_lock);
+       list_for_each(entry, &trigger->led_cdevs) {
+               struct led_classdev *led_cdev;
+
+               led_cdev = list_entry(entry, struct led_classdev, trig_list);
+               led_set_brightness(led_cdev, brightness);
+       }
+       read_unlock(&trigger->leddev_list_lock);
+}
+EXPORT_SYMBOL_GPL(led_trigger_event);
+
+void led_trigger_register_simple(const char *name, struct led_trigger **tp)
+{
+       struct led_trigger *trigger;
+       int err;
+
+       trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+
+       if (trigger) {
+               trigger->name = name;
+               err = led_trigger_register(trigger);
+               if (err < 0)
+                       printk(KERN_WARNING "LED trigger %s failed to register"
+                               " (%d)\n", name, err);
+       } else
+               printk(KERN_WARNING "LED trigger %s failed to register"
+                       " (no memory)\n", name);
+
+       *tp = trigger;
+}
+EXPORT_SYMBOL_GPL(led_trigger_register_simple);
 
 void led_trigger_unregister_simple(struct led_trigger *trigger)
 {
@@ -228,21 +248,7 @@ void led_trigger_unregister_simple(struct led_trigger *trigger)
                led_trigger_unregister(trigger);
        kfree(trigger);
 }
-
-/* Used by LED Class */
-EXPORT_SYMBOL_GPL(led_trigger_set);
-EXPORT_SYMBOL_GPL(led_trigger_set_default);
-EXPORT_SYMBOL_GPL(led_trigger_show);
-EXPORT_SYMBOL_GPL(led_trigger_store);
-
-/* LED Trigger Interface */
-EXPORT_SYMBOL_GPL(led_trigger_register);
-EXPORT_SYMBOL_GPL(led_trigger_unregister);
-
-/* Simple LED Tigger Interface */
-EXPORT_SYMBOL_GPL(led_trigger_register_simple);
 EXPORT_SYMBOL_GPL(led_trigger_unregister_simple);
-EXPORT_SYMBOL_GPL(led_trigger_event);
 
 MODULE_AUTHOR("Richard Purdie");
 MODULE_LICENSE("GPL");
index 5750b08b601fe21e713f6a402554e88078060e68..eb3415e88f43e217fb8faa87a00b9c082773ce0f 100644 (file)
@@ -14,7 +14,7 @@
 #define CLEVO_MAIL_LED_BLINK_1HZ       0x008A
 #define CLEVO_MAIL_LED_BLINK_0_5HZ     0x0083
 
-MODULE_AUTHOR("Márton Németh <nm127@freemail.hu>");
+MODULE_AUTHOR("Márton Németh <nm127@freemail.hu>");
 MODULE_DESCRIPTION("Clevo mail LED driver");
 MODULE_LICENSE("GPL");
 
@@ -67,6 +67,16 @@ static struct dmi_system_id __initdata mail_led_whitelist[] = {
                        DMI_MATCH(DMI_PRODUCT_VERSION, "VT6198")
                }
        },
+       {
+               .callback = clevo_mail_led_dmi_callback,
+               .ident = "Clevo D400P",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Clevo"),
+                       DMI_MATCH(DMI_BOARD_NAME, "D400P"),
+                       DMI_MATCH(DMI_BOARD_VERSION, "Rev.A"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "0106")
+               }
+       },
        {
                .callback = clevo_mail_led_dmi_callback,
                .ident = "Clevo D410V",
@@ -93,8 +103,8 @@ static void clevo_mail_led_set(struct led_classdev *led_cdev,
 }
 
 static int clevo_mail_led_blink(struct led_classdev *led_cdev,
-                               unsigned longdelay_on,
-                               unsigned longdelay_off)
+                               unsigned long *delay_on,
+                               unsigned long *delay_off)
 {
        int status = -EINVAL;
 
index 096881a11b1a2a074d530e647974ac3a77b39ea7..059aa2924b1cb21ba9fa36c7c3f4b441989e18b1 100644 (file)
@@ -18,7 +18,7 @@ static void __iomem *led_port;
 static u8 led_value;
 
 static void qube_front_led_set(struct led_classdev *led_cdev,
-                               enum led_brightness brightness)
+                              enum led_brightness brightness)
 {
        if (brightness)
                led_value = LED_FRONT_LEFT | LED_FRONT_RIGHT;
index 6ebfff341e6cf725c4b4ccc83a823425a9356c6a..ff0e8c3fbf9b79d61365d456d1d78f314390402e 100644 (file)
@@ -15,7 +15,7 @@
  *
  *  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
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 #include <linux/init.h>
 #include <linux/io.h>
@@ -33,7 +33,7 @@ static u8 led_value;
 static DEFINE_SPINLOCK(led_value_lock);
 
 static void raq_web_led_set(struct led_classdev *led_cdev,
-                            enum led_brightness brightness)
+                           enum led_brightness brightness)
 {
        unsigned long flags;
 
@@ -54,7 +54,7 @@ static struct led_classdev raq_web_led = {
 };
 
 static void raq_power_off_led_set(struct led_classdev *led_cdev,
-                                  enum led_brightness brightness)
+                                 enum led_brightness brightness)
 {
        unsigned long flags;
 
index 29e931f89f9cce65f25f422c87680b6347ad6b92..a709704b9f933c3af919f07d3fc54cffb0d68f22 100644 (file)
@@ -21,7 +21,8 @@
 #include <asm/arch/pxa-regs.h>
 #include <asm/hardware/scoop.h>
 
-static void corgiled_amber_set(struct led_classdev *led_cdev, enum led_brightness value)
+static void corgiled_amber_set(struct led_classdev *led_cdev,
+                              enum led_brightness value)
 {
        if (value)
                GPSR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
@@ -29,7 +30,8 @@ static void corgiled_amber_set(struct led_classdev *led_cdev, enum led_brightnes
                GPCR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
 }
 
-static void corgiled_green_set(struct led_classdev *led_cdev, enum led_brightness value)
+static void corgiled_green_set(struct led_classdev *led_cdev,
+                              enum led_brightness value)
 {
        if (value)
                set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
@@ -53,7 +55,8 @@ static struct led_classdev corgi_green_led = {
 static int corgiled_suspend(struct platform_device *dev, pm_message_t state)
 {
 #ifdef CONFIG_LEDS_TRIGGERS
-       if (corgi_amber_led.trigger && strcmp(corgi_amber_led.trigger->name, "sharpsl-charge"))
+       if (corgi_amber_led.trigger &&
+           strcmp(corgi_amber_led.trigger->name, "sharpsl-charge"))
 #endif
                led_classdev_suspend(&corgi_amber_led);
        led_classdev_suspend(&corgi_green_led);
@@ -110,7 +113,7 @@ static int __init corgiled_init(void)
 
 static void __exit corgiled_exit(void)
 {
-       platform_driver_unregister(&corgiled_driver);
+       platform_driver_unregister(&corgiled_driver);
 }
 
 module_init(corgiled_init);
diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c
new file mode 100644 (file)
index 0000000..a7421b8
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * LED Driver for the Freecom FSG-3
+ *
+ * Copyright (c) 2008 Rod Whitby <rod@whitby.id.au>
+ *
+ * Author: Rod Whitby <rod@whitby.id.au>
+ *
+ * Based on leds-spitz.c
+ * Copyright 2005-2006 Openedhand Ltd.
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <asm/arch/hardware.h>
+#include <asm/io.h>
+
+static short __iomem *latch_address;
+static unsigned short latch_value;
+
+
+static void fsg_led_wlan_set(struct led_classdev *led_cdev,
+                            enum led_brightness value)
+{
+       if (value) {
+               latch_value &= ~(1 << FSG_LED_WLAN_BIT);
+               *latch_address = latch_value;
+       } else {
+               latch_value |=  (1 << FSG_LED_WLAN_BIT);
+               *latch_address = latch_value;
+       }
+}
+
+static void fsg_led_wan_set(struct led_classdev *led_cdev,
+                           enum led_brightness value)
+{
+       if (value) {
+               latch_value &= ~(1 << FSG_LED_WAN_BIT);
+               *latch_address = latch_value;
+       } else {
+               latch_value |=  (1 << FSG_LED_WAN_BIT);
+               *latch_address = latch_value;
+       }
+}
+
+static void fsg_led_sata_set(struct led_classdev *led_cdev,
+                            enum led_brightness value)
+{
+       if (value) {
+               latch_value &= ~(1 << FSG_LED_SATA_BIT);
+               *latch_address = latch_value;
+       } else {
+               latch_value |=  (1 << FSG_LED_SATA_BIT);
+               *latch_address = latch_value;
+       }
+}
+
+static void fsg_led_usb_set(struct led_classdev *led_cdev,
+                           enum led_brightness value)
+{
+       if (value) {
+               latch_value &= ~(1 << FSG_LED_USB_BIT);
+               *latch_address = latch_value;
+       } else {
+               latch_value |=  (1 << FSG_LED_USB_BIT);
+               *latch_address = latch_value;
+       }
+}
+
+static void fsg_led_sync_set(struct led_classdev *led_cdev,
+                            enum led_brightness value)
+{
+       if (value) {
+               latch_value &= ~(1 << FSG_LED_SYNC_BIT);
+               *latch_address = latch_value;
+       } else {
+               latch_value |=  (1 << FSG_LED_SYNC_BIT);
+               *latch_address = latch_value;
+       }
+}
+
+static void fsg_led_ring_set(struct led_classdev *led_cdev,
+                            enum led_brightness value)
+{
+       if (value) {
+               latch_value &= ~(1 << FSG_LED_RING_BIT);
+               *latch_address = latch_value;
+       } else {
+               latch_value |=  (1 << FSG_LED_RING_BIT);
+               *latch_address = latch_value;
+       }
+}
+
+
+
+static struct led_classdev fsg_wlan_led = {
+       .name                   = "fsg:blue:wlan",
+       .brightness_set         = fsg_led_wlan_set,
+};
+
+static struct led_classdev fsg_wan_led = {
+       .name                   = "fsg:blue:wan",
+       .brightness_set         = fsg_led_wan_set,
+};
+
+static struct led_classdev fsg_sata_led = {
+       .name                   = "fsg:blue:sata",
+       .brightness_set         = fsg_led_sata_set,
+};
+
+static struct led_classdev fsg_usb_led = {
+       .name                   = "fsg:blue:usb",
+       .brightness_set         = fsg_led_usb_set,
+};
+
+static struct led_classdev fsg_sync_led = {
+       .name                   = "fsg:blue:sync",
+       .brightness_set         = fsg_led_sync_set,
+};
+
+static struct led_classdev fsg_ring_led = {
+       .name                   = "fsg:blue:ring",
+       .brightness_set         = fsg_led_ring_set,
+};
+
+
+
+#ifdef CONFIG_PM
+static int fsg_led_suspend(struct platform_device *dev, pm_message_t state)
+{
+       led_classdev_suspend(&fsg_wlan_led);
+       led_classdev_suspend(&fsg_wan_led);
+       led_classdev_suspend(&fsg_sata_led);
+       led_classdev_suspend(&fsg_usb_led);
+       led_classdev_suspend(&fsg_sync_led);
+       led_classdev_suspend(&fsg_ring_led);
+       return 0;
+}
+
+static int fsg_led_resume(struct platform_device *dev)
+{
+       led_classdev_resume(&fsg_wlan_led);
+       led_classdev_resume(&fsg_wan_led);
+       led_classdev_resume(&fsg_sata_led);
+       led_classdev_resume(&fsg_usb_led);
+       led_classdev_resume(&fsg_sync_led);
+       led_classdev_resume(&fsg_ring_led);
+       return 0;
+}
+#endif
+
+
+static int fsg_led_probe(struct platform_device *pdev)
+{
+       int ret;
+
+       ret = led_classdev_register(&pdev->dev, &fsg_wlan_led);
+       if (ret < 0)
+               goto failwlan;
+
+       ret = led_classdev_register(&pdev->dev, &fsg_wan_led);
+       if (ret < 0)
+               goto failwan;
+
+       ret = led_classdev_register(&pdev->dev, &fsg_sata_led);
+       if (ret < 0)
+               goto failsata;
+
+       ret = led_classdev_register(&pdev->dev, &fsg_usb_led);
+       if (ret < 0)
+               goto failusb;
+
+       ret = led_classdev_register(&pdev->dev, &fsg_sync_led);
+       if (ret < 0)
+               goto failsync;
+
+       ret = led_classdev_register(&pdev->dev, &fsg_ring_led);
+       if (ret < 0)
+               goto failring;
+
+       /* Map the LED chip select address space */
+       latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
+       if (!latch_address) {
+               ret = -ENOMEM;
+               goto failremap;
+       }
+
+       latch_value = 0xffff;
+       *latch_address = latch_value;
+
+       return ret;
+
+ failremap:
+       led_classdev_unregister(&fsg_ring_led);
+ failring:
+       led_classdev_unregister(&fsg_sync_led);
+ failsync:
+       led_classdev_unregister(&fsg_usb_led);
+ failusb:
+       led_classdev_unregister(&fsg_sata_led);
+ failsata:
+       led_classdev_unregister(&fsg_wan_led);
+ failwan:
+       led_classdev_unregister(&fsg_wlan_led);
+ failwlan:
+
+       return ret;
+}
+
+static int fsg_led_remove(struct platform_device *pdev)
+{
+       iounmap(latch_address);
+
+       led_classdev_unregister(&fsg_wlan_led);
+       led_classdev_unregister(&fsg_wan_led);
+       led_classdev_unregister(&fsg_sata_led);
+       led_classdev_unregister(&fsg_usb_led);
+       led_classdev_unregister(&fsg_sync_led);
+       led_classdev_unregister(&fsg_ring_led);
+
+       return 0;
+}
+
+
+static struct platform_driver fsg_led_driver = {
+       .probe          = fsg_led_probe,
+       .remove         = fsg_led_remove,
+#ifdef CONFIG_PM
+       .suspend        = fsg_led_suspend,
+       .resume         = fsg_led_resume,
+#endif
+       .driver         = {
+               .name           = "fsg-led",
+       },
+};
+
+
+static int __init fsg_led_init(void)
+{
+       return platform_driver_register(&fsg_led_driver);
+}
+
+static void __exit fsg_led_exit(void)
+{
+       platform_driver_unregister(&fsg_led_driver);
+}
+
+
+module_init(fsg_led_init);
+module_exit(fsg_led_exit);
+
+MODULE_AUTHOR("Rod Whitby <rod@whitby.id.au>");
+MODULE_DESCRIPTION("Freecom FSG-3 LED driver");
+MODULE_LICENSE("GPL");
index 1aae8b3321349e53802a280d402a36ff1e82d2c3..b13bd2950e956347b98bac9ed76e18efcabed612 100644 (file)
@@ -24,6 +24,8 @@ struct gpio_led_data {
        u8 new_level;
        u8 can_sleep;
        u8 active_low;
+       int (*platform_gpio_blink_set)(unsigned gpio,
+                       unsigned long *delay_on, unsigned long *delay_off);
 };
 
 static void gpio_led_work(struct work_struct *work)
@@ -60,6 +62,15 @@ static void gpio_led_set(struct led_classdev *led_cdev,
                gpio_set_value(led_dat->gpio, level);
 }
 
+static int gpio_blink_set(struct led_classdev *led_cdev,
+       unsigned long *delay_on, unsigned long *delay_off)
+{
+       struct gpio_led_data *led_dat =
+               container_of(led_cdev, struct gpio_led_data, cdev);
+
+       return led_dat->platform_gpio_blink_set(led_dat->gpio, delay_on, delay_off);
+}
+
 static int gpio_led_probe(struct platform_device *pdev)
 {
        struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
@@ -88,6 +99,10 @@ static int gpio_led_probe(struct platform_device *pdev)
                led_dat->gpio = cur_led->gpio;
                led_dat->can_sleep = gpio_cansleep(cur_led->gpio);
                led_dat->active_low = cur_led->active_low;
+               if (pdata->gpio_blink_set) {
+                       led_dat->platform_gpio_blink_set = pdata->gpio_blink_set;
+                       led_dat->cdev.blink_set = gpio_blink_set;
+               }
                led_dat->cdev.brightness_set = gpio_led_set;
                led_dat->cdev.brightness = LED_OFF;
 
index 6e51c9b610279f37f3a8842c739dc00c6c33a832..bcec42230389128cd03ce6294d13c8d018e288ab 100644 (file)
 void h1940_greenled_set(struct led_classdev *led_dev, enum led_brightness value)
 {
        switch (value) {
-               case LED_HALF:
-                       h1940_latch_control(0,H1940_LATCH_LED_FLASH);
-                       s3c2410_gpio_setpin(S3C2410_GPA7,1);
-                       break;
-               case LED_FULL:
-                       h1940_latch_control(0,H1940_LATCH_LED_GREEN);
-                       s3c2410_gpio_setpin(S3C2410_GPA7,1);
-                       break;
-               default:
-               case LED_OFF:
-                       h1940_latch_control(H1940_LATCH_LED_FLASH,0);
-                       h1940_latch_control(H1940_LATCH_LED_GREEN,0);
-                       s3c2410_gpio_setpin(S3C2410_GPA7,0);
-                       break;
+       case LED_HALF:
+               h1940_latch_control(0, H1940_LATCH_LED_FLASH);
+               s3c2410_gpio_setpin(S3C2410_GPA7, 1);
+               break;
+       case LED_FULL:
+               h1940_latch_control(0, H1940_LATCH_LED_GREEN);
+               s3c2410_gpio_setpin(S3C2410_GPA7, 1);
+               break;
+       default:
+       case LED_OFF:
+               h1940_latch_control(H1940_LATCH_LED_FLASH, 0);
+               h1940_latch_control(H1940_LATCH_LED_GREEN, 0);
+               s3c2410_gpio_setpin(S3C2410_GPA7, 0);
+               break;
        }
 }
 
@@ -55,20 +55,20 @@ static struct led_classdev h1940_greenled = {
 void h1940_redled_set(struct led_classdev *led_dev, enum led_brightness value)
 {
        switch (value) {
-               case LED_HALF:
-                       h1940_latch_control(0,H1940_LATCH_LED_FLASH);
-                       s3c2410_gpio_setpin(S3C2410_GPA1,1);
-                       break;
-               case LED_FULL:
-                       h1940_latch_control(0,H1940_LATCH_LED_RED);
-                       s3c2410_gpio_setpin(S3C2410_GPA1,1);
-                       break;
-               default:
-               case LED_OFF:
-                       h1940_latch_control(H1940_LATCH_LED_FLASH,0);
-                       h1940_latch_control(H1940_LATCH_LED_RED,0);
-                       s3c2410_gpio_setpin(S3C2410_GPA1,0);
-                       break;
+       case LED_HALF:
+               h1940_latch_control(0, H1940_LATCH_LED_FLASH);
+               s3c2410_gpio_setpin(S3C2410_GPA1, 1);
+               break;
+       case LED_FULL:
+               h1940_latch_control(0, H1940_LATCH_LED_RED);
+               s3c2410_gpio_setpin(S3C2410_GPA1, 1);
+               break;
+       default:
+       case LED_OFF:
+               h1940_latch_control(H1940_LATCH_LED_FLASH, 0);
+               h1940_latch_control(H1940_LATCH_LED_RED, 0);
+               s3c2410_gpio_setpin(S3C2410_GPA1, 0);
+               break;
        }
 }
 
@@ -86,11 +86,11 @@ void h1940_blueled_set(struct led_classdev *led_dev, enum led_brightness value)
 {
        if (value) {
                /* flashing Blue */
-               h1940_latch_control(0,H1940_LATCH_LED_FLASH);
-               s3c2410_gpio_setpin(S3C2410_GPA3,1);
+               h1940_latch_control(0, H1940_LATCH_LED_FLASH);
+               s3c2410_gpio_setpin(S3C2410_GPA3, 1);
        } else {
-               h1940_latch_control(H1940_LATCH_LED_FLASH,0);
-               s3c2410_gpio_setpin(S3C2410_GPA3,0);
+               h1940_latch_control(H1940_LATCH_LED_FLASH, 0);
+               s3c2410_gpio_setpin(S3C2410_GPA3, 0);
        }
 
 }
index 870f5a3789e8375269f9c13b92e1ca78d0e18cf5..844d5979c9045bfa6126eb8b4828706ac9f68655 100644 (file)
@@ -17,7 +17,8 @@
 #include <asm/hd64461.h>
 #include <asm/hp6xx.h>
 
-static void hp6xxled_green_set(struct led_classdev *led_cdev, enum led_brightness value)
+static void hp6xxled_green_set(struct led_classdev *led_cdev,
+                              enum led_brightness value)
 {
        u8 v8;
 
@@ -28,7 +29,8 @@ static void hp6xxled_green_set(struct led_classdev *led_cdev, enum led_brightnes
                outb(v8 | PKDR_LED_GREEN, PKDR);
 }
 
-static void hp6xxled_red_set(struct led_classdev *led_cdev, enum led_brightness value)
+static void hp6xxled_red_set(struct led_classdev *led_cdev,
+                            enum led_brightness value)
 {
        u16 v16;
 
index 0d10e119d8f5451005ea9e86fd73862cde36a495..d4f5021dccbf8a6b39652f76389014ad107388a7 100644 (file)
@@ -51,7 +51,7 @@ static void s3c24xx_led_set(struct led_classdev *led_cdev,
 
        if (pd->flags & S3C24XX_LEDF_TRISTATE)
                s3c2410_gpio_cfgpin(pd->gpio,
-                                   value ? S3C2410_GPIO_OUTPUT : S3C2410_GPIO_INPUT);
+                       value ? S3C2410_GPIO_OUTPUT : S3C2410_GPIO_INPUT);
 
 }
 
@@ -151,7 +151,7 @@ static int __init s3c24xx_led_init(void)
 
 static void __exit s3c24xx_led_exit(void)
 {
-       platform_driver_unregister(&s3c24xx_led_driver);
+       platform_driver_unregister(&s3c24xx_led_driver);
 }
 
 module_init(s3c24xx_led_init);
index 87007cc362c126ad0ae91dbe883e74928861975f..e75e8543bc5ae187198ad6f08d495541f2890098 100644 (file)
@@ -21,7 +21,8 @@
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/spitz.h>
 
-static void spitzled_amber_set(struct led_classdev *led_cdev, enum led_brightness value)
+static void spitzled_amber_set(struct led_classdev *led_cdev,
+                              enum led_brightness value)
 {
        if (value)
                set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
@@ -29,7 +30,8 @@ static void spitzled_amber_set(struct led_classdev *led_cdev, enum led_brightnes
                reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
 }
 
-static void spitzled_green_set(struct led_classdev *led_cdev, enum led_brightness value)
+static void spitzled_green_set(struct led_classdev *led_cdev,
+                              enum led_brightness value)
 {
        if (value)
                set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN);
@@ -53,7 +55,8 @@ static struct led_classdev spitz_green_led = {
 static int spitzled_suspend(struct platform_device *dev, pm_message_t state)
 {
 #ifdef CONFIG_LEDS_TRIGGERS
-       if (spitz_amber_led.trigger && strcmp(spitz_amber_led.trigger->name, "sharpsl-charge"))
+       if (spitz_amber_led.trigger &&
+           strcmp(spitz_amber_led.trigger->name, "sharpsl-charge"))
 #endif
                led_classdev_suspend(&spitz_amber_led);
        led_classdev_suspend(&spitz_green_led);
@@ -116,7 +119,7 @@ static int __init spitzled_init(void)
 
 static void __exit spitzled_exit(void)
 {
-       platform_driver_unregister(&spitzled_driver);
+       platform_driver_unregister(&spitzled_driver);
 }
 
 module_init(spitzled_init);
index 12b6fe93b1356b980241ef2f7dae3fd325c30090..5edbf52c4fa7e6834e9125855bd4c1801e2c2809 100644 (file)
@@ -27,6 +27,11 @@ static inline void led_set_brightness(struct led_classdev *led_cdev,
                led_cdev->brightness_set(led_cdev, value);
 }
 
+static inline int led_get_brightness(struct led_classdev *led_cdev)
+{
+       return led_cdev->brightness;
+}
+
 extern struct rw_semaphore leds_list_lock;
 extern struct list_head leds_list;
 
@@ -34,9 +39,11 @@ extern struct list_head leds_list;
 void led_trigger_set_default(struct led_classdev *led_cdev);
 void led_trigger_set(struct led_classdev *led_cdev,
                        struct led_trigger *trigger);
+void led_trigger_remove(struct led_classdev *led_cdev);
 #else
-#define led_trigger_set_default(x) do {} while(0)
-#define led_trigger_set(x, y) do {} while(0)
+#define led_trigger_set_default(x) do {} while (0)
+#define led_trigger_set(x, y) do {} while (0)
+#define led_trigger_remove(x) do {} while (0)
 #endif
 
 ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/leds/ledtrig-default-on.c b/drivers/leds/ledtrig-default-on.c
new file mode 100644 (file)
index 0000000..92995e4
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * LED Kernel Default ON Trigger
+ *
+ * Copyright 2008 Nick Forbes <nick.forbes@incepta.com>
+ *
+ * Based on Richard Purdie's ledtrig-timer.c.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+#include "leds.h"
+
+static void defon_trig_activate(struct led_classdev *led_cdev)
+{
+       led_set_brightness(led_cdev, LED_FULL);
+}
+
+static struct led_trigger defon_led_trigger = {
+       .name     = "default-on",
+       .activate = defon_trig_activate,
+};
+
+static int __init defon_trig_init(void)
+{
+       return led_trigger_register(&defon_led_trigger);
+}
+
+static void __exit defon_trig_exit(void)
+{
+       led_trigger_unregister(&defon_led_trigger);
+}
+
+module_init(defon_trig_init);
+module_exit(defon_trig_exit);
+
+MODULE_AUTHOR("Nick Forbes <nick.forbes@incepta.com>");
+MODULE_DESCRIPTION("Default-ON LED trigger");
+MODULE_LICENSE("GPL");
index 54b155c7026f94c72ddc527a949474599d7a3c29..883a577b1b97aaaa189a3d82fc461939ffa286da 100644 (file)
@@ -38,7 +38,7 @@ static void ledtrig_ide_timerfunc(unsigned long data)
        if (ide_lastactivity != ide_activity) {
                ide_lastactivity = ide_activity;
                led_trigger_event(ledtrig_ide, LED_FULL);
-               mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
+               mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
        } else {
                led_trigger_event(ledtrig_ide, LED_OFF);
        }
index 82c55d6e49023ff9fe2866a819a1c5ec7bad7949..5c99f4f0c69214f101a519c9c190d57aae64e317 100644 (file)
@@ -25,6 +25,9 @@
 #include "leds.h"
 
 struct timer_trig_data {
+       int brightness_on;              /* LED brightness during "on" period.
+                                        * (LED_OFF < brightness_on <= LED_FULL)
+                                        */
        unsigned long delay_on;         /* milliseconds on */
        unsigned long delay_off;        /* milliseconds off */
        struct timer_list timer;
@@ -34,17 +37,26 @@ static void led_timer_function(unsigned long data)
 {
        struct led_classdev *led_cdev = (struct led_classdev *) data;
        struct timer_trig_data *timer_data = led_cdev->trigger_data;
-       unsigned long brightness = LED_OFF;
-       unsigned long delay = timer_data->delay_off;
+       unsigned long brightness;
+       unsigned long delay;
 
        if (!timer_data->delay_on || !timer_data->delay_off) {
                led_set_brightness(led_cdev, LED_OFF);
                return;
        }
 
-       if (!led_cdev->brightness) {
-               brightness = LED_FULL;
+       brightness = led_get_brightness(led_cdev);
+       if (!brightness) {
+               /* Time to switch the LED on. */
+               brightness = timer_data->brightness_on;
                delay = timer_data->delay_on;
+       } else {
+               /* Store the current brightness value to be able
+                * to restore it when the delay_off period is over.
+                */
+               timer_data->brightness_on = brightness;
+               brightness = LED_OFF;
+               delay = timer_data->delay_off;
        }
 
        led_set_brightness(led_cdev, brightness);
@@ -52,7 +64,7 @@ static void led_timer_function(unsigned long data)
        mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay));
 }
 
-static ssize_t led_delay_on_show(struct device *dev, 
+static ssize_t led_delay_on_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
        struct led_classdev *led_cdev = dev_get_drvdata(dev);
@@ -63,7 +75,7 @@ static ssize_t led_delay_on_show(struct device *dev,
        return strlen(buf) + 1;
 }
 
-static ssize_t led_delay_on_store(struct device *dev, 
+static ssize_t led_delay_on_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t size)
 {
        struct led_classdev *led_cdev = dev_get_drvdata(dev);
@@ -87,7 +99,7 @@ static ssize_t led_delay_on_store(struct device *dev,
                        /* try to activate hardware acceleration, if any */
                        if (!led_cdev->blink_set ||
                            led_cdev->blink_set(led_cdev,
-                               &timer_data->delay_on, &timer_data->delay_off)) {
+                             &timer_data->delay_on, &timer_data->delay_off)) {
                                /* no hardware acceleration, blink via timer */
                                mod_timer(&timer_data->timer, jiffies + 1);
                        }
@@ -98,7 +110,7 @@ static ssize_t led_delay_on_store(struct device *dev,
        return ret;
 }
 
-static ssize_t led_delay_off_show(struct device *dev, 
+static ssize_t led_delay_off_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
        struct led_classdev *led_cdev = dev_get_drvdata(dev);
@@ -109,7 +121,7 @@ static ssize_t led_delay_off_show(struct device *dev,
        return strlen(buf) + 1;
 }
 
-static ssize_t led_delay_off_store(struct device *dev, 
+static ssize_t led_delay_off_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t size)
 {
        struct led_classdev *led_cdev = dev_get_drvdata(dev);
@@ -133,7 +145,7 @@ static ssize_t led_delay_off_store(struct device *dev,
                        /* try to activate hardware acceleration, if any */
                        if (!led_cdev->blink_set ||
                            led_cdev->blink_set(led_cdev,
-                               &timer_data->delay_on, &timer_data->delay_off)) {
+                             &timer_data->delay_on, &timer_data->delay_off)) {
                                /* no hardware acceleration, blink via timer */
                                mod_timer(&timer_data->timer, jiffies + 1);
                        }
@@ -156,6 +168,9 @@ static void timer_trig_activate(struct led_classdev *led_cdev)
        if (!timer_data)
                return;
 
+       timer_data->brightness_on = led_get_brightness(led_cdev);
+       if (timer_data->brightness_on == LED_OFF)
+               timer_data->brightness_on = LED_FULL;
        led_cdev->trigger_data = timer_data;
 
        init_timer(&timer_data->timer);
index 89302309da92d56f397096ad8412a4e7fa2ef1d4..cc9f27514aefe99a2e45da629e76050dab48a247 100644 (file)
@@ -103,6 +103,9 @@ int mac_hid_mouse_emulate_buttons(int caller, unsigned int keycode, int down)
        return 0;
 }
 
+static struct lock_class_key emumousebtn_event_class;
+static struct lock_class_key emumousebtn_mutex_class;
+
 static int emumousebtn_input_register(void)
 {
        int ret;
@@ -111,6 +114,9 @@ static int emumousebtn_input_register(void)
        if (!emumousebtn)
                return -ENOMEM;
 
+       lockdep_set_class(&emumousebtn->event_lock, &emumousebtn_event_class);
+       lockdep_set_class(&emumousebtn->mutex, &emumousebtn_mutex_class);
+
        emumousebtn->name = "Macintosh mouse button emulation";
        emumousebtn->id.bustype = BUS_ADB;
        emumousebtn->id.vendor = 0x0001;
index b3fbb45bc90acbdd586d790140dee5b063690476..73d695dc9e5059c950c99f8c08a0cd30a2141c39 100644 (file)
@@ -668,7 +668,7 @@ static struct platform_driver wf_pm112_driver = {
        .remove = __devexit_p(wf_pm112_remove),
        .driver = {
                .name = "windfarm",
-               .bus = &platform_bus_type,
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -711,3 +711,4 @@ module_exit(wf_pm112_exit);
 MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
 MODULE_DESCRIPTION("Thermal control for PowerMac11,2");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:windfarm");
index f24fa734046a253d30a7a198c325e6538cc91539..abbe206474f58ce2ff1de53e274d6df7158b92f4 100644 (file)
@@ -770,7 +770,7 @@ static struct platform_driver wf_smu_driver = {
         .remove = __devexit_p(wf_smu_remove),
        .driver = {
                .name = "windfarm",
-               .bus = &platform_bus_type,
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -810,4 +810,4 @@ module_exit(wf_smu_exit);
 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
 MODULE_DESCRIPTION("Thermal control logic for iMac G5");
 MODULE_LICENSE("GPL");
-
+MODULE_ALIAS("platform:windfarm");
index 26eee69ebe6deb7dbf1088bc5b9b3377a439379a..764c525b2117f0ac2420992063ac1efdcb512a21 100644 (file)
@@ -702,7 +702,7 @@ static struct platform_driver wf_smu_driver = {
         .remove = __devexit_p(wf_smu_remove),
        .driver = {
                .name = "windfarm",
-               .bus = &platform_bus_type,
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -742,3 +742,4 @@ MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
 MODULE_DESCRIPTION("Thermal control logic for PowerMac9,1");
 MODULE_LICENSE("GPL");
 
+MODULE_ALIAS("platform:windfarm");
index d9aa7edb87801ec0e7f36b7614f4a23f97827e5c..7be09eeea293c307c6213bc689840f5c1ac90c4d 100644 (file)
@@ -3,10 +3,10 @@
 #
 
 dm-mod-objs    := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
-                  dm-ioctl.o dm-io.o kcopyd.o
+                  dm-ioctl.o dm-io.o dm-kcopyd.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-mirror-objs := dm-raid1.o
 dm-rdac-objs   := dm-mpath-rdac.o
 dm-hp-sw-objs  := dm-mpath-hp-sw.o
 md-mod-objs     := md.o bitmap.o
@@ -39,7 +39,7 @@ obj-$(CONFIG_DM_MULTIPATH_EMC)        += dm-emc.o
 obj-$(CONFIG_DM_MULTIPATH_HP)  += dm-hp-sw.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_MIRROR)                += dm-mirror.o dm-log.o
 obj-$(CONFIG_DM_ZERO)          += dm-zero.o
 
 quiet_cmd_unroll = UNROLL  $@
index 5bbce29f143ac45f6d358a9b26217b3d30ee1ccd..41f408068a7c9c2329c61eb7e3eb47a82af6e280 100644 (file)
@@ -9,13 +9,13 @@
 
 #include "dm.h"
 #include "dm-snap.h"
-#include "dm-io.h"
-#include "kcopyd.h"
 
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
+#include <linux/dm-io.h>
+#include <linux/dm-kcopyd.h>
 
 #define DM_MSG_PREFIX "snapshots"
 #define DM_CHUNK_SIZE_DEFAULT_SECTORS 32       /* 16KB */
@@ -131,7 +131,7 @@ struct pstore {
 
 static unsigned sectors_to_pages(unsigned sectors)
 {
-       return sectors / (PAGE_SIZE >> 9);
+       return DIV_ROUND_UP(sectors, PAGE_SIZE >> 9);
 }
 
 static int alloc_area(struct pstore *ps)
@@ -159,7 +159,7 @@ static void free_area(struct pstore *ps)
 }
 
 struct mdata_req {
-       struct io_region *where;
+       struct dm_io_region *where;
        struct dm_io_request *io_req;
        struct work_struct work;
        int result;
@@ -177,7 +177,7 @@ static void do_metadata(struct work_struct *work)
  */
 static int chunk_io(struct pstore *ps, uint32_t chunk, int rw, int metadata)
 {
-       struct io_region where = {
+       struct dm_io_region where = {
                .bdev = ps->snap->cow->bdev,
                .sector = ps->snap->chunk_size * chunk,
                .count = ps->snap->chunk_size,
index 8f25f628ef16d5e680129656d3a1885c115a432d..4789c42d9a3ac503d53ba6ea77fe7fadbee21682 100644 (file)
@@ -5,13 +5,14 @@
  * This file is released under the GPL.
  */
 
-#include "dm-io.h"
+#include "dm.h"
 
 #include <linux/bio.h>
 #include <linux/mempool.h>
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/dm-io.h>
 
 struct dm_io_client {
        mempool_t *pool;
@@ -20,7 +21,7 @@ struct dm_io_client {
 
 /* FIXME: can we shrink this ? */
 struct io {
-       unsigned long error;
+       unsigned long error_bits;
        atomic_t count;
        struct task_struct *sleeper;
        struct dm_io_client *client;
@@ -107,14 +108,14 @@ static inline unsigned bio_get_region(struct bio *bio)
 static void dec_count(struct io *io, unsigned int region, int error)
 {
        if (error)
-               set_bit(region, &io->error);
+               set_bit(region, &io->error_bits);
 
        if (atomic_dec_and_test(&io->count)) {
                if (io->sleeper)
                        wake_up_process(io->sleeper);
 
                else {
-                       unsigned long r = io->error;
+                       unsigned long r = io->error_bits;
                        io_notify_fn fn = io->callback;
                        void *context = io->context;
 
@@ -271,7 +272,7 @@ static void km_dp_init(struct dpages *dp, void *data)
 /*-----------------------------------------------------------------
  * IO routines that accept a list of pages.
  *---------------------------------------------------------------*/
-static void do_region(int rw, unsigned int region, struct io_region *where,
+static void do_region(int rw, unsigned region, struct dm_io_region *where,
                      struct dpages *dp, struct io *io)
 {
        struct bio *bio;
@@ -320,7 +321,7 @@ static void do_region(int rw, unsigned int region, struct io_region *where,
 }
 
 static void dispatch_io(int rw, unsigned int num_regions,
-                       struct io_region *where, struct dpages *dp,
+                       struct dm_io_region *where, struct dpages *dp,
                        struct io *io, int sync)
 {
        int i;
@@ -347,17 +348,17 @@ static void dispatch_io(int rw, unsigned int num_regions,
 }
 
 static int sync_io(struct dm_io_client *client, unsigned int num_regions,
-                  struct io_region *where, int rw, struct dpages *dp,
+                  struct dm_io_region *where, int rw, struct dpages *dp,
                   unsigned long *error_bits)
 {
        struct io io;
 
-       if (num_regions > 1 && rw != WRITE) {
+       if (num_regions > 1 && (rw & RW_MASK) != WRITE) {
                WARN_ON(1);
                return -EIO;
        }
 
-       io.error = 0;
+       io.error_bits = 0;
        atomic_set(&io.count, 1); /* see dispatch_io() */
        io.sleeper = current;
        io.client = client;
@@ -378,25 +379,25 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
                return -EINTR;
 
        if (error_bits)
-               *error_bits = io.error;
+               *error_bits = io.error_bits;
 
-       return io.error ? -EIO : 0;
+       return io.error_bits ? -EIO : 0;
 }
 
 static int async_io(struct dm_io_client *client, unsigned int num_regions,
-                   struct io_region *where, int rw, struct dpages *dp,
+                   struct dm_io_region *where, int rw, struct dpages *dp,
                    io_notify_fn fn, void *context)
 {
        struct io *io;
 
-       if (num_regions > 1 && rw != WRITE) {
+       if (num_regions > 1 && (rw & RW_MASK) != WRITE) {
                WARN_ON(1);
                fn(1, context);
                return -EIO;
        }
 
        io = mempool_alloc(client->pool, GFP_NOIO);
-       io->error = 0;
+       io->error_bits = 0;
        atomic_set(&io->count, 1); /* see dispatch_io() */
        io->sleeper = NULL;
        io->client = client;
@@ -435,10 +436,15 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp)
 }
 
 /*
- * New collapsed (a)synchronous interface
+ * New collapsed (a)synchronous interface.
+ *
+ * If the IO is asynchronous (i.e. it has notify.fn), you must either unplug
+ * the queue with blk_unplug() some time later or set the BIO_RW_SYNC bit in
+ * io_req->bi_rw. If you fail to do one of these, the IO will be submitted to
+ * the disk after q->unplug_delay, which defaults to 3ms in blk-settings.c.
  */
 int dm_io(struct dm_io_request *io_req, unsigned num_regions,
-         struct io_region *where, unsigned long *sync_error_bits)
+         struct dm_io_region *where, unsigned long *sync_error_bits)
 {
        int r;
        struct dpages dp;
similarity index 71%
rename from drivers/md/kcopyd.c
rename to drivers/md/dm-kcopyd.c
index e76b52ade69027f467fe3f16cf1b10443f4711bc..996802b8a4522e50126365d070f21458f9b68be2 100644 (file)
@@ -9,9 +9,8 @@
  * completion notification.
  */
 
-#include <asm/types.h>
+#include <linux/types.h>
 #include <asm/atomic.h>
-
 #include <linux/blkdev.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/vmalloc.h>
 #include <linux/workqueue.h>
 #include <linux/mutex.h>
+#include <linux/dm-kcopyd.h>
 
-#include "kcopyd.h"
-
-static struct workqueue_struct *_kcopyd_wq;
-static struct work_struct _kcopyd_work;
-
-static void wake(void)
-{
-       queue_work(_kcopyd_wq, &_kcopyd_work);
-}
+#include "dm.h"
 
 /*-----------------------------------------------------------------
  * Each kcopyd client has its own little pool of preallocated
  * pages for kcopyd io.
  *---------------------------------------------------------------*/
-struct kcopyd_client {
-       struct list_head list;
-
+struct dm_kcopyd_client {
        spinlock_t lock;
        struct page_list *pages;
        unsigned int nr_pages;
@@ -50,8 +40,32 @@ struct kcopyd_client {
 
        wait_queue_head_t destroyq;
        atomic_t nr_jobs;
+
+       mempool_t *job_pool;
+
+       struct workqueue_struct *kcopyd_wq;
+       struct work_struct kcopyd_work;
+
+/*
+ * We maintain three lists of jobs:
+ *
+ * i)   jobs waiting for pages
+ * ii)  jobs that have pages, and are waiting for the io to be issued.
+ * iii) jobs that have completed.
+ *
+ * All three of these are protected by job_lock.
+ */
+       spinlock_t job_lock;
+       struct list_head complete_jobs;
+       struct list_head io_jobs;
+       struct list_head pages_jobs;
 };
 
+static void wake(struct dm_kcopyd_client *kc)
+{
+       queue_work(kc->kcopyd_wq, &kc->kcopyd_work);
+}
+
 static struct page_list *alloc_pl(void)
 {
        struct page_list *pl;
@@ -75,7 +89,7 @@ static void free_pl(struct page_list *pl)
        kfree(pl);
 }
 
-static int kcopyd_get_pages(struct kcopyd_client *kc,
+static int kcopyd_get_pages(struct dm_kcopyd_client *kc,
                            unsigned int nr, struct page_list **pages)
 {
        struct page_list *pl;
@@ -98,7 +112,7 @@ static int kcopyd_get_pages(struct kcopyd_client *kc,
        return 0;
 }
 
-static void kcopyd_put_pages(struct kcopyd_client *kc, struct page_list *pl)
+static void kcopyd_put_pages(struct dm_kcopyd_client *kc, struct page_list *pl)
 {
        struct page_list *cursor;
 
@@ -126,7 +140,7 @@ static void drop_pages(struct page_list *pl)
        }
 }
 
-static int client_alloc_pages(struct kcopyd_client *kc, unsigned int nr)
+static int client_alloc_pages(struct dm_kcopyd_client *kc, unsigned int nr)
 {
        unsigned int i;
        struct page_list *pl = NULL, *next;
@@ -147,7 +161,7 @@ static int client_alloc_pages(struct kcopyd_client *kc, unsigned int nr)
        return 0;
 }
 
-static void client_free_pages(struct kcopyd_client *kc)
+static void client_free_pages(struct dm_kcopyd_client *kc)
 {
        BUG_ON(kc->nr_free_pages != kc->nr_pages);
        drop_pages(kc->pages);
@@ -161,7 +175,7 @@ static void client_free_pages(struct kcopyd_client *kc)
  * ever having to do io (which could cause a deadlock).
  *---------------------------------------------------------------*/
 struct kcopyd_job {
-       struct kcopyd_client *kc;
+       struct dm_kcopyd_client *kc;
        struct list_head list;
        unsigned long flags;
 
@@ -175,13 +189,13 @@ struct kcopyd_job {
         * Either READ or WRITE
         */
        int rw;
-       struct io_region source;
+       struct dm_io_region source;
 
        /*
         * The destinations for the transfer.
         */
        unsigned int num_dests;
-       struct io_region dests[KCOPYD_MAX_REGIONS];
+       struct dm_io_region dests[DM_KCOPYD_MAX_REGIONS];
 
        sector_t offset;
        unsigned int nr_pages;
@@ -191,7 +205,7 @@ struct kcopyd_job {
         * Set this to ensure you are notified when the job has
         * completed.  'context' is for callback to use.
         */
-       kcopyd_notify_fn fn;
+       dm_kcopyd_notify_fn fn;
        void *context;
 
        /*
@@ -207,47 +221,19 @@ struct kcopyd_job {
 #define MIN_JOBS 512
 
 static struct kmem_cache *_job_cache;
-static mempool_t *_job_pool;
 
-/*
- * We maintain three lists of jobs:
- *
- * i)   jobs waiting for pages
- * ii)  jobs that have pages, and are waiting for the io to be issued.
- * iii) jobs that have completed.
- *
- * All three of these are protected by job_lock.
- */
-static DEFINE_SPINLOCK(_job_lock);
-
-static LIST_HEAD(_complete_jobs);
-static LIST_HEAD(_io_jobs);
-static LIST_HEAD(_pages_jobs);
-
-static int jobs_init(void)
+int __init dm_kcopyd_init(void)
 {
        _job_cache = KMEM_CACHE(kcopyd_job, 0);
        if (!_job_cache)
                return -ENOMEM;
 
-       _job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache);
-       if (!_job_pool) {
-               kmem_cache_destroy(_job_cache);
-               return -ENOMEM;
-       }
-
        return 0;
 }
 
-static void jobs_exit(void)
+void dm_kcopyd_exit(void)
 {
-       BUG_ON(!list_empty(&_complete_jobs));
-       BUG_ON(!list_empty(&_io_jobs));
-       BUG_ON(!list_empty(&_pages_jobs));
-
-       mempool_destroy(_job_pool);
        kmem_cache_destroy(_job_cache);
-       _job_pool = NULL;
        _job_cache = NULL;
 }
 
@@ -255,18 +241,19 @@ static void jobs_exit(void)
  * Functions to push and pop a job onto the head of a given job
  * list.
  */
-static struct kcopyd_job *pop(struct list_head *jobs)
+static struct kcopyd_job *pop(struct list_head *jobs,
+                             struct dm_kcopyd_client *kc)
 {
        struct kcopyd_job *job = NULL;
        unsigned long flags;
 
-       spin_lock_irqsave(&_job_lock, flags);
+       spin_lock_irqsave(&kc->job_lock, flags);
 
        if (!list_empty(jobs)) {
                job = list_entry(jobs->next, struct kcopyd_job, list);
                list_del(&job->list);
        }
-       spin_unlock_irqrestore(&_job_lock, flags);
+       spin_unlock_irqrestore(&kc->job_lock, flags);
 
        return job;
 }
@@ -274,10 +261,11 @@ static struct kcopyd_job *pop(struct list_head *jobs)
 static void push(struct list_head *jobs, struct kcopyd_job *job)
 {
        unsigned long flags;
+       struct dm_kcopyd_client *kc = job->kc;
 
-       spin_lock_irqsave(&_job_lock, flags);
+       spin_lock_irqsave(&kc->job_lock, flags);
        list_add_tail(&job->list, jobs);
-       spin_unlock_irqrestore(&_job_lock, flags);
+       spin_unlock_irqrestore(&kc->job_lock, flags);
 }
 
 /*
@@ -294,11 +282,11 @@ static int run_complete_job(struct kcopyd_job *job)
        void *context = job->context;
        int read_err = job->read_err;
        unsigned long write_err = job->write_err;
-       kcopyd_notify_fn fn = job->fn;
-       struct kcopyd_client *kc = job->kc;
+       dm_kcopyd_notify_fn fn = job->fn;
+       struct dm_kcopyd_client *kc = job->kc;
 
        kcopyd_put_pages(kc, job->pages);
-       mempool_free(job, _job_pool);
+       mempool_free(job, kc->job_pool);
        fn(read_err, write_err, context);
 
        if (atomic_dec_and_test(&kc->nr_jobs))
@@ -310,6 +298,7 @@ static int run_complete_job(struct kcopyd_job *job)
 static void complete_io(unsigned long error, void *context)
 {
        struct kcopyd_job *job = (struct kcopyd_job *) context;
+       struct dm_kcopyd_client *kc = job->kc;
 
        if (error) {
                if (job->rw == WRITE)
@@ -317,22 +306,22 @@ static void complete_io(unsigned long error, void *context)
                else
                        job->read_err = 1;
 
-               if (!test_bit(KCOPYD_IGNORE_ERROR, &job->flags)) {
-                       push(&_complete_jobs, job);
-                       wake();
+               if (!test_bit(DM_KCOPYD_IGNORE_ERROR, &job->flags)) {
+                       push(&kc->complete_jobs, job);
+                       wake(kc);
                        return;
                }
        }
 
        if (job->rw == WRITE)
-               push(&_complete_jobs, job);
+               push(&kc->complete_jobs, job);
 
        else {
                job->rw = WRITE;
-               push(&_io_jobs, job);
+               push(&kc->io_jobs, job);
        }
 
-       wake();
+       wake(kc);
 }
 
 /*
@@ -343,7 +332,7 @@ static int run_io_job(struct kcopyd_job *job)
 {
        int r;
        struct dm_io_request io_req = {
-               .bi_rw = job->rw,
+               .bi_rw = job->rw | (1 << BIO_RW_SYNC),
                .mem.type = DM_IO_PAGE_LIST,
                .mem.ptr.pl = job->pages,
                .mem.offset = job->offset,
@@ -369,7 +358,7 @@ static int run_pages_job(struct kcopyd_job *job)
        r = kcopyd_get_pages(job->kc, job->nr_pages, &job->pages);
        if (!r) {
                /* this job is ready for io */
-               push(&_io_jobs, job);
+               push(&job->kc->io_jobs, job);
                return 0;
        }
 
@@ -384,12 +373,13 @@ static int run_pages_job(struct kcopyd_job *job)
  * Run through a list for as long as possible.  Returns the count
  * of successful jobs.
  */
-static int process_jobs(struct list_head *jobs, int (*fn) (struct kcopyd_job *))
+static int process_jobs(struct list_head *jobs, struct dm_kcopyd_client *kc,
+                       int (*fn) (struct kcopyd_job *))
 {
        struct kcopyd_job *job;
        int r, count = 0;
 
-       while ((job = pop(jobs))) {
+       while ((job = pop(jobs, kc))) {
 
                r = fn(job);
 
@@ -399,7 +389,7 @@ static int process_jobs(struct list_head *jobs, int (*fn) (struct kcopyd_job *))
                                job->write_err = (unsigned long) -1L;
                        else
                                job->read_err = 1;
-                       push(&_complete_jobs, job);
+                       push(&kc->complete_jobs, job);
                        break;
                }
 
@@ -421,8 +411,11 @@ static int process_jobs(struct list_head *jobs, int (*fn) (struct kcopyd_job *))
 /*
  * kcopyd does this every time it's woken up.
  */
-static void do_work(struct work_struct *ignored)
+static void do_work(struct work_struct *work)
 {
+       struct dm_kcopyd_client *kc = container_of(work,
+                                       struct dm_kcopyd_client, kcopyd_work);
+
        /*
         * The order that these are called is *very* important.
         * complete jobs can free some pages for pages jobs.
@@ -430,9 +423,9 @@ static void do_work(struct work_struct *ignored)
         * list.  io jobs call wake when they complete and it all
         * starts again.
         */
-       process_jobs(&_complete_jobs, run_complete_job);
-       process_jobs(&_pages_jobs, run_pages_job);
-       process_jobs(&_io_jobs, run_io_job);
+       process_jobs(&kc->complete_jobs, kc, run_complete_job);
+       process_jobs(&kc->pages_jobs, kc, run_pages_job);
+       process_jobs(&kc->io_jobs, kc, run_io_job);
 }
 
 /*
@@ -442,9 +435,10 @@ static void do_work(struct work_struct *ignored)
  */
 static void dispatch_job(struct kcopyd_job *job)
 {
-       atomic_inc(&job->kc->nr_jobs);
-       push(&_pages_jobs, job);
-       wake();
+       struct dm_kcopyd_client *kc = job->kc;
+       atomic_inc(&kc->nr_jobs);
+       push(&kc->pages_jobs, job);
+       wake(kc);
 }
 
 #define SUB_JOB_SIZE 128
@@ -469,7 +463,7 @@ static void segment_complete(int read_err, unsigned long write_err,
         * Only dispatch more work if there hasn't been an error.
         */
        if ((!job->read_err && !job->write_err) ||
-           test_bit(KCOPYD_IGNORE_ERROR, &job->flags)) {
+           test_bit(DM_KCOPYD_IGNORE_ERROR, &job->flags)) {
                /* get the next chunk of work */
                progress = job->progress;
                count = job->source.count - progress;
@@ -484,7 +478,8 @@ static void segment_complete(int read_err, unsigned long write_err,
 
        if (count) {
                int i;
-               struct kcopyd_job *sub_job = mempool_alloc(_job_pool, GFP_NOIO);
+               struct kcopyd_job *sub_job = mempool_alloc(job->kc->job_pool,
+                                                          GFP_NOIO);
 
                *sub_job = *job;
                sub_job->source.sector += progress;
@@ -508,7 +503,7 @@ static void segment_complete(int read_err, unsigned long write_err,
                 * after we've completed.
                 */
                job->fn(read_err, write_err, job->context);
-               mempool_free(job, _job_pool);
+               mempool_free(job, job->kc->job_pool);
        }
 }
 
@@ -526,16 +521,16 @@ static void split_job(struct kcopyd_job *job)
                segment_complete(0, 0u, job);
 }
 
-int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
-               unsigned int num_dests, struct io_region *dests,
-               unsigned int flags, kcopyd_notify_fn fn, void *context)
+int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
+                  unsigned int num_dests, struct dm_io_region *dests,
+                  unsigned int flags, dm_kcopyd_notify_fn fn, void *context)
 {
        struct kcopyd_job *job;
 
        /*
         * Allocate a new job.
         */
-       job = mempool_alloc(_job_pool, GFP_NOIO);
+       job = mempool_alloc(kc->job_pool, GFP_NOIO);
 
        /*
         * set up for the read.
@@ -569,6 +564,7 @@ int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
 
        return 0;
 }
+EXPORT_SYMBOL(dm_kcopyd_copy);
 
 /*
  * Cancels a kcopyd job, eg. someone might be deactivating a
@@ -583,126 +579,76 @@ int kcopyd_cancel(struct kcopyd_job *job, int block)
 #endif  /*  0  */
 
 /*-----------------------------------------------------------------
- * Unit setup
+ * Client setup
  *---------------------------------------------------------------*/
-static DEFINE_MUTEX(_client_lock);
-static LIST_HEAD(_clients);
-
-static void client_add(struct kcopyd_client *kc)
+int dm_kcopyd_client_create(unsigned int nr_pages,
+                           struct dm_kcopyd_client **result)
 {
-       mutex_lock(&_client_lock);
-       list_add(&kc->list, &_clients);
-       mutex_unlock(&_client_lock);
-}
-
-static void client_del(struct kcopyd_client *kc)
-{
-       mutex_lock(&_client_lock);
-       list_del(&kc->list);
-       mutex_unlock(&_client_lock);
-}
-
-static DEFINE_MUTEX(kcopyd_init_lock);
-static int kcopyd_clients = 0;
+       int r = -ENOMEM;
+       struct dm_kcopyd_client *kc;
 
-static int kcopyd_init(void)
-{
-       int r;
-
-       mutex_lock(&kcopyd_init_lock);
-
-       if (kcopyd_clients) {
-               /* Already initialized. */
-               kcopyd_clients++;
-               mutex_unlock(&kcopyd_init_lock);
-               return 0;
-       }
-
-       r = jobs_init();
-       if (r) {
-               mutex_unlock(&kcopyd_init_lock);
-               return r;
-       }
-
-       _kcopyd_wq = create_singlethread_workqueue("kcopyd");
-       if (!_kcopyd_wq) {
-               jobs_exit();
-               mutex_unlock(&kcopyd_init_lock);
+       kc = kmalloc(sizeof(*kc), GFP_KERNEL);
+       if (!kc)
                return -ENOMEM;
-       }
-
-       kcopyd_clients++;
-       INIT_WORK(&_kcopyd_work, do_work);
-       mutex_unlock(&kcopyd_init_lock);
-       return 0;
-}
 
-static void kcopyd_exit(void)
-{
-       mutex_lock(&kcopyd_init_lock);
-       kcopyd_clients--;
-       if (!kcopyd_clients) {
-               jobs_exit();
-               destroy_workqueue(_kcopyd_wq);
-               _kcopyd_wq = NULL;
-       }
-       mutex_unlock(&kcopyd_init_lock);
-}
-
-int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result)
-{
-       int r = 0;
-       struct kcopyd_client *kc;
+       spin_lock_init(&kc->lock);
+       spin_lock_init(&kc->job_lock);
+       INIT_LIST_HEAD(&kc->complete_jobs);
+       INIT_LIST_HEAD(&kc->io_jobs);
+       INIT_LIST_HEAD(&kc->pages_jobs);
 
-       r = kcopyd_init();
-       if (r)
-               return r;
+       kc->job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache);
+       if (!kc->job_pool)
+               goto bad_slab;
 
-       kc = kmalloc(sizeof(*kc), GFP_KERNEL);
-       if (!kc) {
-               kcopyd_exit();
-               return -ENOMEM;
-       }
+       INIT_WORK(&kc->kcopyd_work, do_work);
+       kc->kcopyd_wq = create_singlethread_workqueue("kcopyd");
+       if (!kc->kcopyd_wq)
+               goto bad_workqueue;
 
-       spin_lock_init(&kc->lock);
        kc->pages = NULL;
        kc->nr_pages = kc->nr_free_pages = 0;
        r = client_alloc_pages(kc, nr_pages);
-       if (r) {
-               kfree(kc);
-               kcopyd_exit();
-               return r;
-       }
+       if (r)
+               goto bad_client_pages;
 
        kc->io_client = dm_io_client_create(nr_pages);
        if (IS_ERR(kc->io_client)) {
                r = PTR_ERR(kc->io_client);
-               client_free_pages(kc);
-               kfree(kc);
-               kcopyd_exit();
-               return r;
+               goto bad_io_client;
        }
 
        init_waitqueue_head(&kc->destroyq);
        atomic_set(&kc->nr_jobs, 0);
 
-       client_add(kc);
        *result = kc;
        return 0;
+
+bad_io_client:
+       client_free_pages(kc);
+bad_client_pages:
+       destroy_workqueue(kc->kcopyd_wq);
+bad_workqueue:
+       mempool_destroy(kc->job_pool);
+bad_slab:
+       kfree(kc);
+
+       return r;
 }
+EXPORT_SYMBOL(dm_kcopyd_client_create);
 
-void kcopyd_client_destroy(struct kcopyd_client *kc)
+void dm_kcopyd_client_destroy(struct dm_kcopyd_client *kc)
 {
        /* Wait for completion of all jobs submitted by this client. */
        wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs));
 
+       BUG_ON(!list_empty(&kc->complete_jobs));
+       BUG_ON(!list_empty(&kc->io_jobs));
+       BUG_ON(!list_empty(&kc->pages_jobs));
+       destroy_workqueue(kc->kcopyd_wq);
        dm_io_client_destroy(kc->io_client);
        client_free_pages(kc);
-       client_del(kc);
+       mempool_destroy(kc->job_pool);
        kfree(kc);
-       kcopyd_exit();
 }
-
-EXPORT_SYMBOL(kcopyd_client_create);
-EXPORT_SYMBOL(kcopyd_client_destroy);
-EXPORT_SYMBOL(kcopyd_copy);
+EXPORT_SYMBOL(dm_kcopyd_client_destroy);
index 2a74b2142f502a6e2ea944e39b598d90cbb96cac..67a6f31b7fc3e2d39a3dfbf6813d6b163eae6707 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2003 Sistina Software
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
  *
  * This file is released under the LGPL.
  */
@@ -8,64 +9,58 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/vmalloc.h>
+#include <linux/dm-io.h>
+#include <linux/dm-dirty-log.h>
 
-#include "dm-log.h"
-#include "dm-io.h"
+#include "dm.h"
 
-#define DM_MSG_PREFIX "mirror log"
+#define DM_MSG_PREFIX "dirty region log"
 
-static LIST_HEAD(_log_types);
-static DEFINE_SPINLOCK(_lock);
+struct dm_dirty_log_internal {
+       struct dm_dirty_log_type *type;
 
-int dm_register_dirty_log_type(struct dirty_log_type *type)
-{
-       spin_lock(&_lock);
-       type->use_count = 0;
-       list_add(&type->list, &_log_types);
-       spin_unlock(&_lock);
+       struct list_head list;
+       long use;
+};
 
-       return 0;
-}
+static LIST_HEAD(_log_types);
+static DEFINE_SPINLOCK(_lock);
 
-int dm_unregister_dirty_log_type(struct dirty_log_type *type)
+static struct dm_dirty_log_internal *__find_dirty_log_type(const char *name)
 {
-       spin_lock(&_lock);
-
-       if (type->use_count)
-               DMWARN("Attempt to unregister a log type that is still in use");
-       else
-               list_del(&type->list);
+       struct dm_dirty_log_internal *log_type;
 
-       spin_unlock(&_lock);
+       list_for_each_entry(log_type, &_log_types, list)
+               if (!strcmp(name, log_type->type->name))
+                       return log_type;
 
-       return 0;
+       return NULL;
 }
 
-static struct dirty_log_type *_get_type(const char *type_name)
+static struct dm_dirty_log_internal *_get_dirty_log_type(const char *name)
 {
-       struct dirty_log_type *type;
+       struct dm_dirty_log_internal *log_type;
 
        spin_lock(&_lock);
-       list_for_each_entry (type, &_log_types, list)
-               if (!strcmp(type_name, type->name)) {
-                       if (!type->use_count && !try_module_get(type->module)){
-                               spin_unlock(&_lock);
-                               return NULL;
-                       }
-                       type->use_count++;
-                       spin_unlock(&_lock);
-                       return type;
-               }
+
+       log_type = __find_dirty_log_type(name);
+       if (log_type) {
+               if (!log_type->use && !try_module_get(log_type->type->module))
+                       log_type = NULL;
+               else
+                       log_type->use++;
+       }
 
        spin_unlock(&_lock);
-       return NULL;
+
+       return log_type;
 }
 
 /*
  * get_type
  * @type_name
  *
- * Attempt to retrieve the dirty_log_type by name.  If not already
+ * Attempt to retrieve the dm_dirty_log_type by name.  If not already
  * available, attempt to load the appropriate module.
  *
  * Log modules are named "dm-log-" followed by the 'type_name'.
@@ -78,14 +73,17 @@ static struct dirty_log_type *_get_type(const char *type_name)
  *
  * Returns: dirty_log_type* on success, NULL on failure
  */
-static struct dirty_log_type *get_type(const char *type_name)
+static struct dm_dirty_log_type *get_type(const char *type_name)
 {
        char *p, *type_name_dup;
-       struct dirty_log_type *type;
+       struct dm_dirty_log_internal *log_type;
+
+       if (!type_name)
+               return NULL;
 
-       type = _get_type(type_name);
-       if (type)
-               return type;
+       log_type = _get_dirty_log_type(type_name);
+       if (log_type)
+               return log_type->type;
 
        type_name_dup = kstrdup(type_name, GFP_KERNEL);
        if (!type_name_dup) {
@@ -95,34 +93,106 @@ static struct dirty_log_type *get_type(const char *type_name)
        }
 
        while (request_module("dm-log-%s", type_name_dup) ||
-              !(type = _get_type(type_name))) {
+              !(log_type = _get_dirty_log_type(type_name))) {
                p = strrchr(type_name_dup, '-');
                if (!p)
                        break;
                p[0] = '\0';
        }
 
-       if (!type)
+       if (!log_type)
                DMWARN("Module for logging type \"%s\" not found.", type_name);
 
        kfree(type_name_dup);
 
-       return type;
+       return log_type ? log_type->type : NULL;
 }
 
-static void put_type(struct dirty_log_type *type)
+static void put_type(struct dm_dirty_log_type *type)
 {
+       struct dm_dirty_log_internal *log_type;
+
+       if (!type)
+               return;
+
        spin_lock(&_lock);
-       if (!--type->use_count)
+       log_type = __find_dirty_log_type(type->name);
+       if (!log_type)
+               goto out;
+
+       if (!--log_type->use)
                module_put(type->module);
+
+       BUG_ON(log_type->use < 0);
+
+out:
        spin_unlock(&_lock);
 }
 
-struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *ti,
-                                     unsigned int argc, char **argv)
+static struct dm_dirty_log_internal *_alloc_dirty_log_type(struct dm_dirty_log_type *type)
 {
-       struct dirty_log_type *type;
-       struct dirty_log *log;
+       struct dm_dirty_log_internal *log_type = kzalloc(sizeof(*log_type),
+                                                        GFP_KERNEL);
+
+       if (log_type)
+               log_type->type = type;
+
+       return log_type;
+}
+
+int dm_dirty_log_type_register(struct dm_dirty_log_type *type)
+{
+       struct dm_dirty_log_internal *log_type = _alloc_dirty_log_type(type);
+       int r = 0;
+
+       if (!log_type)
+               return -ENOMEM;
+
+       spin_lock(&_lock);
+       if (!__find_dirty_log_type(type->name))
+               list_add(&log_type->list, &_log_types);
+       else {
+               kfree(log_type);
+               r = -EEXIST;
+       }
+       spin_unlock(&_lock);
+
+       return r;
+}
+EXPORT_SYMBOL(dm_dirty_log_type_register);
+
+int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type)
+{
+       struct dm_dirty_log_internal *log_type;
+
+       spin_lock(&_lock);
+
+       log_type = __find_dirty_log_type(type->name);
+       if (!log_type) {
+               spin_unlock(&_lock);
+               return -EINVAL;
+       }
+
+       if (log_type->use) {
+               spin_unlock(&_lock);
+               return -ETXTBSY;
+       }
+
+       list_del(&log_type->list);
+
+       spin_unlock(&_lock);
+       kfree(log_type);
+
+       return 0;
+}
+EXPORT_SYMBOL(dm_dirty_log_type_unregister);
+
+struct dm_dirty_log *dm_dirty_log_create(const char *type_name,
+                                        struct dm_target *ti,
+                                        unsigned int argc, char **argv)
+{
+       struct dm_dirty_log_type *type;
+       struct dm_dirty_log *log;
 
        log = kmalloc(sizeof(*log), GFP_KERNEL);
        if (!log)
@@ -143,13 +213,15 @@ struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *t
 
        return log;
 }
+EXPORT_SYMBOL(dm_dirty_log_create);
 
-void dm_destroy_dirty_log(struct dirty_log *log)
+void dm_dirty_log_destroy(struct dm_dirty_log *log)
 {
        log->type->dtr(log);
        put_type(log->type);
        kfree(log);
 }
+EXPORT_SYMBOL(dm_dirty_log_destroy);
 
 /*-----------------------------------------------------------------
  * Persistent and core logs share a lot of their implementation.
@@ -207,7 +279,7 @@ struct log_c {
        struct dm_dev *log_dev;
        struct log_header header;
 
-       struct io_region header_location;
+       struct dm_io_region header_location;
        struct log_header *disk_header;
 };
 
@@ -215,7 +287,7 @@ struct log_c {
  * The touched member needs to be updated every time we access
  * one of the bitsets.
  */
-static  inline int log_test_bit(uint32_t *bs, unsigned bit)
+static inline int log_test_bit(uint32_t *bs, unsigned bit)
 {
        return ext2_test_bit(bit, (unsigned long *) bs) ? 1 : 0;
 }
@@ -302,7 +374,7 @@ static inline int write_header(struct log_c *log)
  * argv contains region_size followed optionally by [no]sync
  *--------------------------------------------------------------*/
 #define BYTE_SHIFT 3
-static int create_log_context(struct dirty_log *log, struct dm_target *ti,
+static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
                              unsigned int argc, char **argv,
                              struct dm_dev *dev)
 {
@@ -315,7 +387,7 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti,
        int r;
 
        if (argc < 1 || argc > 2) {
-               DMWARN("wrong number of arguments to mirror log");
+               DMWARN("wrong number of arguments to dirty region log");
                return -EINVAL;
        }
 
@@ -325,8 +397,8 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti,
                else if (!strcmp(argv[1], "nosync"))
                        sync = NOSYNC;
                else {
-                       DMWARN("unrecognised sync argument to mirror log: %s",
-                              argv[1]);
+                       DMWARN("unrecognised sync argument to "
+                              "dirty region log: %s", argv[1]);
                        return -EINVAL;
                }
        }
@@ -434,7 +506,7 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti,
        return 0;
 }
 
-static int core_ctr(struct dirty_log *log, struct dm_target *ti,
+static int core_ctr(struct dm_dirty_log *log, struct dm_target *ti,
                    unsigned int argc, char **argv)
 {
        return create_log_context(log, ti, argc, argv, NULL);
@@ -447,7 +519,7 @@ static void destroy_log_context(struct log_c *lc)
        kfree(lc);
 }
 
-static void core_dtr(struct dirty_log *log)
+static void core_dtr(struct dm_dirty_log *log)
 {
        struct log_c *lc = (struct log_c *) log->context;
 
@@ -460,14 +532,14 @@ static void core_dtr(struct dirty_log *log)
  *
  * argv contains log_device region_size followed optionally by [no]sync
  *--------------------------------------------------------------*/
-static int disk_ctr(struct dirty_log *log, struct dm_target *ti,
+static int disk_ctr(struct dm_dirty_log *log, struct dm_target *ti,
                    unsigned int argc, char **argv)
 {
        int r;
        struct dm_dev *dev;
 
        if (argc < 2 || argc > 3) {
-               DMWARN("wrong number of arguments to disk mirror log");
+               DMWARN("wrong number of arguments to disk dirty region log");
                return -EINVAL;
        }
 
@@ -485,7 +557,7 @@ static int disk_ctr(struct dirty_log *log, struct dm_target *ti,
        return 0;
 }
 
-static void disk_dtr(struct dirty_log *log)
+static void disk_dtr(struct dm_dirty_log *log)
 {
        struct log_c *lc = (struct log_c *) log->context;
 
@@ -514,7 +586,7 @@ static void fail_log_device(struct log_c *lc)
        dm_table_event(lc->ti->table);
 }
 
-static int disk_resume(struct dirty_log *log)
+static int disk_resume(struct dm_dirty_log *log)
 {
        int r;
        unsigned i;
@@ -524,7 +596,7 @@ static int disk_resume(struct dirty_log *log)
        /* read the disk header */
        r = read_header(lc);
        if (r) {
-               DMWARN("%s: Failed to read header on mirror log device",
+               DMWARN("%s: Failed to read header on dirty region log device",
                       lc->log_dev->name);
                fail_log_device(lc);
                /*
@@ -562,7 +634,7 @@ static int disk_resume(struct dirty_log *log)
        /* write the new header */
        r = write_header(lc);
        if (r) {
-               DMWARN("%s: Failed to write header on mirror log device",
+               DMWARN("%s: Failed to write header on dirty region log device",
                       lc->log_dev->name);
                fail_log_device(lc);
        }
@@ -570,38 +642,38 @@ static int disk_resume(struct dirty_log *log)
        return r;
 }
 
-static uint32_t core_get_region_size(struct dirty_log *log)
+static uint32_t core_get_region_size(struct dm_dirty_log *log)
 {
        struct log_c *lc = (struct log_c *) log->context;
        return lc->region_size;
 }
 
-static int core_resume(struct dirty_log *log)
+static int core_resume(struct dm_dirty_log *log)
 {
        struct log_c *lc = (struct log_c *) log->context;
        lc->sync_search = 0;
        return 0;
 }
 
-static int core_is_clean(struct dirty_log *log, region_t region)
+static int core_is_clean(struct dm_dirty_log *log, region_t region)
 {
        struct log_c *lc = (struct log_c *) log->context;
        return log_test_bit(lc->clean_bits, region);
 }
 
-static int core_in_sync(struct dirty_log *log, region_t region, int block)
+static int core_in_sync(struct dm_dirty_log *log, region_t region, int block)
 {
        struct log_c *lc = (struct log_c *) log->context;
        return log_test_bit(lc->sync_bits, region);
 }
 
-static int core_flush(struct dirty_log *log)
+static int core_flush(struct dm_dirty_log *log)
 {
        /* no op */
        return 0;
 }
 
-static int disk_flush(struct dirty_log *log)
+static int disk_flush(struct dm_dirty_log *log)
 {
        int r;
        struct log_c *lc = (struct log_c *) log->context;
@@ -619,19 +691,19 @@ static int disk_flush(struct dirty_log *log)
        return r;
 }
 
-static void core_mark_region(struct dirty_log *log, region_t region)
+static void core_mark_region(struct dm_dirty_log *log, region_t region)
 {
        struct log_c *lc = (struct log_c *) log->context;
        log_clear_bit(lc, lc->clean_bits, region);
 }
 
-static void core_clear_region(struct dirty_log *log, region_t region)
+static void core_clear_region(struct dm_dirty_log *log, region_t region)
 {
        struct log_c *lc = (struct log_c *) log->context;
        log_set_bit(lc, lc->clean_bits, region);
 }
 
-static int core_get_resync_work(struct dirty_log *log, region_t *region)
+static int core_get_resync_work(struct dm_dirty_log *log, region_t *region)
 {
        struct log_c *lc = (struct log_c *) log->context;
 
@@ -654,7 +726,7 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region)
        return 1;
 }
 
-static void core_set_region_sync(struct dirty_log *log, region_t region,
+static void core_set_region_sync(struct dm_dirty_log *log, region_t region,
                                 int in_sync)
 {
        struct log_c *lc = (struct log_c *) log->context;
@@ -669,7 +741,7 @@ static void core_set_region_sync(struct dirty_log *log, region_t region,
        }
 }
 
-static region_t core_get_sync_count(struct dirty_log *log)
+static region_t core_get_sync_count(struct dm_dirty_log *log)
 {
         struct log_c *lc = (struct log_c *) log->context;
 
@@ -680,7 +752,7 @@ static region_t core_get_sync_count(struct dirty_log *log)
        if (lc->sync != DEFAULTSYNC) \
                DMEMIT("%ssync ", lc->sync == NOSYNC ? "no" : "")
 
-static int core_status(struct dirty_log *log, status_type_t status,
+static int core_status(struct dm_dirty_log *log, status_type_t status,
                       char *result, unsigned int maxlen)
 {
        int sz = 0;
@@ -700,7 +772,7 @@ static int core_status(struct dirty_log *log, status_type_t status,
        return sz;
 }
 
-static int disk_status(struct dirty_log *log, status_type_t status,
+static int disk_status(struct dm_dirty_log *log, status_type_t status,
                       char *result, unsigned int maxlen)
 {
        int sz = 0;
@@ -722,7 +794,7 @@ static int disk_status(struct dirty_log *log, status_type_t status,
        return sz;
 }
 
-static struct dirty_log_type _core_type = {
+static struct dm_dirty_log_type _core_type = {
        .name = "core",
        .module = THIS_MODULE,
        .ctr = core_ctr,
@@ -740,7 +812,7 @@ static struct dirty_log_type _core_type = {
        .status = core_status,
 };
 
-static struct dirty_log_type _disk_type = {
+static struct dm_dirty_log_type _disk_type = {
        .name = "disk",
        .module = THIS_MODULE,
        .ctr = disk_ctr,
@@ -763,26 +835,28 @@ int __init dm_dirty_log_init(void)
 {
        int r;
 
-       r = dm_register_dirty_log_type(&_core_type);
+       r = dm_dirty_log_type_register(&_core_type);
        if (r)
                DMWARN("couldn't register core log");
 
-       r = dm_register_dirty_log_type(&_disk_type);
+       r = dm_dirty_log_type_register(&_disk_type);
        if (r) {
                DMWARN("couldn't register disk type");
-               dm_unregister_dirty_log_type(&_core_type);
+               dm_dirty_log_type_unregister(&_core_type);
        }
 
        return r;
 }
 
-void dm_dirty_log_exit(void)
+void __exit dm_dirty_log_exit(void)
 {
-       dm_unregister_dirty_log_type(&_disk_type);
-       dm_unregister_dirty_log_type(&_core_type);
+       dm_dirty_log_type_unregister(&_disk_type);
+       dm_dirty_log_type_unregister(&_core_type);
 }
 
-EXPORT_SYMBOL(dm_register_dirty_log_type);
-EXPORT_SYMBOL(dm_unregister_dirty_log_type);
-EXPORT_SYMBOL(dm_create_dirty_log);
-EXPORT_SYMBOL(dm_destroy_dirty_log);
+module_init(dm_dirty_log_init);
+module_exit(dm_dirty_log_exit);
+
+MODULE_DESCRIPTION(DM_NAME " dirty region log");
+MODULE_AUTHOR("Joe Thornber, Heinz Mauelshagen <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
index 762cb086bb7f6e864fca4998f407644e8add96cc..ff05fe89308313ab5792a6b3dc9146db3e585c6a 100644 (file)
@@ -7,9 +7,6 @@
 #include "dm.h"
 #include "dm-bio-list.h"
 #include "dm-bio-record.h"
-#include "dm-io.h"
-#include "dm-log.h"
-#include "kcopyd.h"
 
 #include <linux/ctype.h>
 #include <linux/init.h>
@@ -22,6 +19,9 @@
 #include <linux/workqueue.h>
 #include <linux/log2.h>
 #include <linux/hardirq.h>
+#include <linux/dm-io.h>
+#include <linux/dm-dirty-log.h>
+#include <linux/dm-kcopyd.h>
 
 #define DM_MSG_PREFIX "raid1"
 #define DM_IO_PAGES 64
@@ -74,7 +74,7 @@ struct region_hash {
        unsigned region_shift;
 
        /* holds persistent region state */
-       struct dirty_log *log;
+       struct dm_dirty_log *log;
 
        /* hash table */
        rwlock_t hash_lock;
@@ -133,7 +133,7 @@ struct mirror_set {
        struct dm_target *ti;
        struct list_head list;
        struct region_hash rh;
-       struct kcopyd_client *kcopyd_client;
+       struct dm_kcopyd_client *kcopyd_client;
        uint64_t features;
 
        spinlock_t lock;        /* protects the lists */
@@ -154,6 +154,9 @@ struct mirror_set {
 
        struct workqueue_struct *kmirrord_wq;
        struct work_struct kmirrord_work;
+       struct timer_list timer;
+       unsigned long timer_pending;
+
        struct work_struct trigger_event;
 
        unsigned int nr_mirrors;
@@ -178,13 +181,32 @@ static void wake(struct mirror_set *ms)
        queue_work(ms->kmirrord_wq, &ms->kmirrord_work);
 }
 
+static void delayed_wake_fn(unsigned long data)
+{
+       struct mirror_set *ms = (struct mirror_set *) data;
+
+       clear_bit(0, &ms->timer_pending);
+       wake(ms);
+}
+
+static void delayed_wake(struct mirror_set *ms)
+{
+       if (test_and_set_bit(0, &ms->timer_pending))
+               return;
+
+       ms->timer.expires = jiffies + HZ / 5;
+       ms->timer.data = (unsigned long) ms;
+       ms->timer.function = delayed_wake_fn;
+       add_timer(&ms->timer);
+}
+
 /* FIXME move this */
 static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw);
 
 #define MIN_REGIONS 64
 #define MAX_RECOVERY 1
 static int rh_init(struct region_hash *rh, struct mirror_set *ms,
-                  struct dirty_log *log, uint32_t region_size,
+                  struct dm_dirty_log *log, uint32_t region_size,
                   region_t nr_regions)
 {
        unsigned int nr_buckets, max_buckets;
@@ -249,7 +271,7 @@ static void rh_exit(struct region_hash *rh)
        }
 
        if (rh->log)
-               dm_destroy_dirty_log(rh->log);
+               dm_dirty_log_destroy(rh->log);
        if (rh->region_pool)
                mempool_destroy(rh->region_pool);
        vfree(rh->buckets);
@@ -405,24 +427,22 @@ static void rh_update_states(struct region_hash *rh)
        write_lock_irq(&rh->hash_lock);
        spin_lock(&rh->region_lock);
        if (!list_empty(&rh->clean_regions)) {
-               list_splice(&rh->clean_regions, &clean);
-               INIT_LIST_HEAD(&rh->clean_regions);
+               list_splice_init(&rh->clean_regions, &clean);
 
                list_for_each_entry(reg, &clean, list)
                        list_del(&reg->hash_list);
        }
 
        if (!list_empty(&rh->recovered_regions)) {
-               list_splice(&rh->recovered_regions, &recovered);
-               INIT_LIST_HEAD(&rh->recovered_regions);
+               list_splice_init(&rh->recovered_regions, &recovered);
 
                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_splice_init(&rh->failed_recovered_regions,
+                                &failed_recovered);
 
                list_for_each_entry(reg, &failed_recovered, list)
                        list_del(&reg->hash_list);
@@ -790,7 +810,7 @@ static int recover(struct mirror_set *ms, struct region *reg)
 {
        int r;
        unsigned int i;
-       struct io_region from, to[KCOPYD_MAX_REGIONS], *dest;
+       struct dm_io_region from, to[DM_KCOPYD_MAX_REGIONS], *dest;
        struct mirror *m;
        unsigned long flags = 0;
 
@@ -822,9 +842,9 @@ static int recover(struct mirror_set *ms, struct region *reg)
        }
 
        /* hand to kcopyd */
-       set_bit(KCOPYD_IGNORE_ERROR, &flags);
-       r = kcopyd_copy(ms->kcopyd_client, &from, ms->nr_mirrors - 1, to, flags,
-                       recovery_complete, reg);
+       set_bit(DM_KCOPYD_IGNORE_ERROR, &flags);
+       r = dm_kcopyd_copy(ms->kcopyd_client, &from, ms->nr_mirrors - 1, to,
+                          flags, recovery_complete, reg);
 
        return r;
 }
@@ -833,7 +853,7 @@ static void do_recovery(struct mirror_set *ms)
 {
        int r;
        struct region *reg;
-       struct dirty_log *log = ms->rh.log;
+       struct dm_dirty_log *log = ms->rh.log;
 
        /*
         * Start quiescing some regions.
@@ -909,7 +929,7 @@ static void map_bio(struct mirror *m, struct bio *bio)
        bio->bi_sector = map_sector(m, bio);
 }
 
-static void map_region(struct io_region *io, struct mirror *m,
+static void map_region(struct dm_io_region *io, struct mirror *m,
                       struct bio *bio)
 {
        io->bdev = m->dev->bdev;
@@ -951,7 +971,7 @@ static void read_callback(unsigned long error, void *context)
 /* Asynchronous read. */
 static void read_async_bio(struct mirror *m, struct bio *bio)
 {
-       struct io_region io;
+       struct dm_io_region io;
        struct dm_io_request io_req = {
                .bi_rw = READ,
                .mem.type = DM_IO_BVEC,
@@ -1019,7 +1039,7 @@ static void __bio_mark_nosync(struct mirror_set *ms,
 {
        unsigned long flags;
        struct region_hash *rh = &ms->rh;
-       struct dirty_log *log = ms->rh.log;
+       struct dm_dirty_log *log = ms->rh.log;
        struct region *reg;
        region_t region = bio_to_region(rh, bio);
        int recovering = 0;
@@ -1107,7 +1127,7 @@ out:
 static void do_write(struct mirror_set *ms, struct bio *bio)
 {
        unsigned int i;
-       struct io_region io[ms->nr_mirrors], *dest = io;
+       struct dm_io_region io[ms->nr_mirrors], *dest = io;
        struct mirror *m;
        struct dm_io_request io_req = {
                .bi_rw = WRITE,
@@ -1182,6 +1202,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
                spin_lock_irq(&ms->lock);
                bio_list_merge(&ms->failures, &sync);
                spin_unlock_irq(&ms->lock);
+               wake(ms);
        } else
                while ((bio = bio_list_pop(&sync)))
                        do_write(ms, bio);
@@ -1241,7 +1262,7 @@ static void do_failures(struct mirror_set *ms, struct bio_list *failures)
        bio_list_merge(&ms->failures, failures);
        spin_unlock_irq(&ms->lock);
 
-       wake(ms);
+       delayed_wake(ms);
 }
 
 static void trigger_event(struct work_struct *work)
@@ -1255,7 +1276,7 @@ static void trigger_event(struct work_struct *work)
 /*-----------------------------------------------------------------
  * kmirrord
  *---------------------------------------------------------------*/
-static int _do_mirror(struct work_struct *work)
+static void do_mirror(struct work_struct *work)
 {
        struct mirror_set *ms =container_of(work, struct mirror_set,
                                            kmirrord_work);
@@ -1277,23 +1298,7 @@ static int _do_mirror(struct work_struct *work)
        do_writes(ms, &writes);
        do_failures(ms, &failures);
 
-       return (ms->failures.head) ? 1 : 0;
-}
-
-static void do_mirror(struct work_struct *work)
-{
-       /*
-        * If _do_mirror returns 1, we give it
-        * another shot.  This helps for cases like
-        * 'suspend' where we call flush_workqueue
-        * and expect all work to be finished.  If
-        * a failure happens during a suspend, we
-        * couldn't issue a 'wake' because it would
-        * not be honored.  Therefore, we return '1'
-        * from _do_mirror, and retry here.
-        */
-       while (_do_mirror(work))
-               schedule();
+       dm_table_unplug_all(ms->ti->table);
 }
 
 
@@ -1303,7 +1308,7 @@ static void do_mirror(struct work_struct *work)
 static struct mirror_set *alloc_context(unsigned int nr_mirrors,
                                        uint32_t region_size,
                                        struct dm_target *ti,
-                                       struct dirty_log *dl)
+                                       struct dm_dirty_log *dl)
 {
        size_t len;
        struct mirror_set *ms = NULL;
@@ -1403,12 +1408,12 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
 /*
  * Create dirty log: log_type #log_params <log_params>
  */
-static struct dirty_log *create_dirty_log(struct dm_target *ti,
+static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
                                          unsigned int argc, char **argv,
                                          unsigned int *args_used)
 {
        unsigned int param_count;
-       struct dirty_log *dl;
+       struct dm_dirty_log *dl;
 
        if (argc < 2) {
                ti->error = "Insufficient mirror log arguments";
@@ -1427,7 +1432,7 @@ static struct dirty_log *create_dirty_log(struct dm_target *ti,
                return NULL;
        }
 
-       dl = dm_create_dirty_log(argv[0], ti, param_count, argv + 2);
+       dl = dm_dirty_log_create(argv[0], ti, param_count, argv + 2);
        if (!dl) {
                ti->error = "Error creating mirror dirty log";
                return NULL;
@@ -1435,7 +1440,7 @@ static struct dirty_log *create_dirty_log(struct dm_target *ti,
 
        if (!_check_region_size(ti, dl->type->get_region_size(dl))) {
                ti->error = "Invalid region size";
-               dm_destroy_dirty_log(dl);
+               dm_dirty_log_destroy(dl);
                return NULL;
        }
 
@@ -1496,7 +1501,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        int r;
        unsigned int nr_mirrors, m, args_used;
        struct mirror_set *ms;
-       struct dirty_log *dl;
+       struct dm_dirty_log *dl;
 
        dl = create_dirty_log(ti, argc, argv, &args_used);
        if (!dl)
@@ -1506,9 +1511,9 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        argc -= args_used;
 
        if (!argc || sscanf(argv[0], "%u", &nr_mirrors) != 1 ||
-           nr_mirrors < 2 || nr_mirrors > KCOPYD_MAX_REGIONS + 1) {
+           nr_mirrors < 2 || nr_mirrors > DM_KCOPYD_MAX_REGIONS + 1) {
                ti->error = "Invalid number of mirrors";
-               dm_destroy_dirty_log(dl);
+               dm_dirty_log_destroy(dl);
                return -EINVAL;
        }
 
@@ -1516,13 +1521,13 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
        if (argc < nr_mirrors * 2) {
                ti->error = "Too few mirror arguments";
-               dm_destroy_dirty_log(dl);
+               dm_dirty_log_destroy(dl);
                return -EINVAL;
        }
 
        ms = alloc_context(nr_mirrors, dl->type->get_region_size(dl), ti, dl);
        if (!ms) {
-               dm_destroy_dirty_log(dl);
+               dm_dirty_log_destroy(dl);
                return -ENOMEM;
        }
 
@@ -1547,6 +1552,8 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                goto err_free_context;
        }
        INIT_WORK(&ms->kmirrord_work, do_mirror);
+       init_timer(&ms->timer);
+       ms->timer_pending = 0;
        INIT_WORK(&ms->trigger_event, trigger_event);
 
        r = parse_features(ms, argc, argv, &args_used);
@@ -1571,7 +1578,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                goto err_destroy_wq;
        }
 
-       r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client);
+       r = dm_kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client);
        if (r)
                goto err_destroy_wq;
 
@@ -1589,8 +1596,9 @@ static void mirror_dtr(struct dm_target *ti)
 {
        struct mirror_set *ms = (struct mirror_set *) ti->private;
 
+       del_timer_sync(&ms->timer);
        flush_workqueue(ms->kmirrord_wq);
-       kcopyd_client_destroy(ms->kcopyd_client);
+       dm_kcopyd_client_destroy(ms->kcopyd_client);
        destroy_workqueue(ms->kmirrord_wq);
        free_context(ms, ti, ms->nr_mirrors);
 }
@@ -1734,7 +1742,7 @@ out:
 static void mirror_presuspend(struct dm_target *ti)
 {
        struct mirror_set *ms = (struct mirror_set *) ti->private;
-       struct dirty_log *log = ms->rh.log;
+       struct dm_dirty_log *log = ms->rh.log;
 
        atomic_set(&ms->suspend, 1);
 
@@ -1763,7 +1771,7 @@ static void mirror_presuspend(struct dm_target *ti)
 static void mirror_postsuspend(struct dm_target *ti)
 {
        struct mirror_set *ms = ti->private;
-       struct dirty_log *log = ms->rh.log;
+       struct dm_dirty_log *log = ms->rh.log;
 
        if (log->type->postsuspend && log->type->postsuspend(log))
                /* FIXME: need better error handling */
@@ -1773,7 +1781,7 @@ static void mirror_postsuspend(struct dm_target *ti)
 static void mirror_resume(struct dm_target *ti)
 {
        struct mirror_set *ms = ti->private;
-       struct dirty_log *log = ms->rh.log;
+       struct dm_dirty_log *log = ms->rh.log;
 
        atomic_set(&ms->suspend, 0);
        if (log->type->resume && log->type->resume(log))
@@ -1811,7 +1819,7 @@ static int mirror_status(struct dm_target *ti, status_type_t type,
 {
        unsigned int m, sz = 0;
        struct mirror_set *ms = (struct mirror_set *) ti->private;
-       struct dirty_log *log = ms->rh.log;
+       struct dm_dirty_log *log = ms->rh.log;
        char buffer[ms->nr_mirrors + 1];
 
        switch (type) {
@@ -1864,15 +1872,9 @@ static int __init dm_mirror_init(void)
 {
        int r;
 
-       r = dm_dirty_log_init();
-       if (r)
-               return r;
-
        r = dm_register_target(&mirror_target);
-       if (r < 0) {
+       if (r < 0)
                DMERR("Failed to register mirror target");
-               dm_dirty_log_exit();
-       }
 
        return r;
 }
@@ -1884,8 +1886,6 @@ static void __exit dm_mirror_exit(void)
        r = dm_unregister_target(&mirror_target);
        if (r < 0)
                DMERR("unregister failed %d", r);
-
-       dm_dirty_log_exit();
 }
 
 /* Module hooks */
index 4dc8a43c034b0242422399a15a7d6a271f97da3d..1ba8a47d61b116646c6ac8ef533cd5b8f64767a7 100644 (file)
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/log2.h>
+#include <linux/dm-kcopyd.h>
 
 #include "dm-snap.h"
 #include "dm-bio-list.h"
-#include "kcopyd.h"
 
 #define DM_MSG_PREFIX "snapshots"
 
@@ -36,9 +36,9 @@
 #define SNAPSHOT_COPY_PRIORITY 2
 
 /*
- * Each snapshot reserves this many pages for io
+ * Reserve 1MB for each snapshot initially (with minimum of 1 page).
  */
-#define SNAPSHOT_PAGES 256
+#define SNAPSHOT_PAGES (((1UL << 20) >> PAGE_SHIFT) ? : 1)
 
 static struct workqueue_struct *ksnapd;
 static void flush_queued_bios(struct work_struct *work);
@@ -536,7 +536,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        s->last_percent = 0;
        init_rwsem(&s->lock);
        spin_lock_init(&s->pe_lock);
-       s->table = ti->table;
+       s->ti = ti;
 
        /* Allocate hash table for COW data */
        if (init_hash_tables(s)) {
@@ -558,7 +558,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                goto bad4;
        }
 
-       r = kcopyd_client_create(SNAPSHOT_PAGES, &s->kcopyd_client);
+       r = dm_kcopyd_client_create(SNAPSHOT_PAGES, &s->kcopyd_client);
        if (r) {
                ti->error = "Could not create kcopyd client";
                goto bad5;
@@ -591,7 +591,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        return 0;
 
  bad6:
-       kcopyd_client_destroy(s->kcopyd_client);
+       dm_kcopyd_client_destroy(s->kcopyd_client);
 
  bad5:
        s->store.destroy(&s->store);
@@ -613,7 +613,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
 static void __free_exceptions(struct dm_snapshot *s)
 {
-       kcopyd_client_destroy(s->kcopyd_client);
+       dm_kcopyd_client_destroy(s->kcopyd_client);
        s->kcopyd_client = NULL;
 
        exit_exception_table(&s->pending, pending_cache);
@@ -699,7 +699,7 @@ static void __invalidate_snapshot(struct dm_snapshot *s, int err)
 
        s->valid = 0;
 
-       dm_table_event(s->table);
+       dm_table_event(s->ti->table);
 }
 
 static void get_pending_exception(struct dm_snap_pending_exception *pe)
@@ -824,7 +824,7 @@ static void copy_callback(int read_err, unsigned long write_err, void *context)
 static void start_copy(struct dm_snap_pending_exception *pe)
 {
        struct dm_snapshot *s = pe->snap;
-       struct io_region src, dest;
+       struct dm_io_region src, dest;
        struct block_device *bdev = s->origin->bdev;
        sector_t dev_size;
 
@@ -839,7 +839,7 @@ static void start_copy(struct dm_snap_pending_exception *pe)
        dest.count = src.count;
 
        /* Hand over to kcopyd */
-       kcopyd_copy(s->kcopyd_client,
+       dm_kcopyd_copy(s->kcopyd_client,
                    &src, 1, &dest, 0, copy_callback, pe);
 }
 
@@ -1060,7 +1060,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
                        goto next_snapshot;
 
                /* Nothing to do if writing beyond end of snapshot */
-               if (bio->bi_sector >= dm_table_get_size(snap->table))
+               if (bio->bi_sector >= dm_table_get_size(snap->ti->table))
                        goto next_snapshot;
 
                /*
index 93bce5d49742e3441fd24b5cd511483b8027c846..24f9fb73b982d0cd148ef15d56428ba6c7ce6877 100644 (file)
@@ -132,7 +132,7 @@ struct exception_store {
 
 struct dm_snapshot {
        struct rw_semaphore lock;
-       struct dm_table *table;
+       struct dm_target *ti;
 
        struct dm_dev *origin;
        struct dm_dev *cow;
@@ -169,7 +169,7 @@ struct dm_snapshot {
        /* The on disk metadata handler */
        struct exception_store store;
 
-       struct kcopyd_client *kcopyd_client;
+       struct dm_kcopyd_client *kcopyd_client;
 
        /* Queue of snapshot writes for ksnapd to flush */
        struct bio_list queued_bios;
index e75b1437b58b67ad8ecac097d6b3c50e9bf0b2ba..51be53344214906593ec54dec6b6e8e1c018f369 100644 (file)
@@ -245,44 +245,6 @@ int dm_table_create(struct dm_table **result, int mode,
        return 0;
 }
 
-int dm_create_error_table(struct dm_table **result, struct mapped_device *md)
-{
-       struct dm_table *t;
-       sector_t dev_size = 1;
-       int r;
-
-       /*
-        * Find current size of device.
-        * Default to 1 sector if inactive.
-        */
-       t = dm_get_table(md);
-       if (t) {
-               dev_size = dm_table_get_size(t);
-               dm_table_put(t);
-       }
-
-       r = dm_table_create(&t, FMODE_READ, 1, md);
-       if (r)
-               return r;
-
-       r = dm_table_add_target(t, "error", 0, dev_size, NULL);
-       if (r)
-               goto out;
-
-       r = dm_table_complete(t);
-       if (r)
-               goto out;
-
-       *result = t;
-
-out:
-       if (r)
-               dm_table_put(t);
-
-       return r;
-}
-EXPORT_SYMBOL_GPL(dm_create_error_table);
-
 static void free_devices(struct list_head *devices)
 {
        struct list_head *tmp, *next;
@@ -954,7 +916,7 @@ void dm_table_presuspend_targets(struct dm_table *t)
        if (!t)
                return;
 
-       return suspend_targets(t, 0);
+       suspend_targets(t, 0);
 }
 
 void dm_table_postsuspend_targets(struct dm_table *t)
@@ -962,7 +924,7 @@ void dm_table_postsuspend_targets(struct dm_table *t)
        if (!t)
                return;
 
-       return suspend_targets(t, 1);
+       suspend_targets(t, 1);
 }
 
 int dm_table_resume_targets(struct dm_table *t)
index 6617ce4af09579285a2be1090adde8c9f61a3fb4..372369b1cc2068c286964883638c2b3a9f2c11c4 100644 (file)
@@ -204,6 +204,7 @@ static int (*_inits[])(void) __initdata = {
        dm_target_init,
        dm_linear_init,
        dm_stripe_init,
+       dm_kcopyd_init,
        dm_interface_init,
 };
 
@@ -212,6 +213,7 @@ static void (*_exits[])(void) = {
        dm_target_exit,
        dm_linear_exit,
        dm_stripe_exit,
+       dm_kcopyd_exit,
        dm_interface_exit,
 };
 
@@ -922,7 +924,7 @@ static void free_minor(int minor)
 /*
  * See if the device with a specific minor # is free.
  */
-static int specific_minor(struct mapped_device *md, int minor)
+static int specific_minor(int minor)
 {
        int r, m;
 
@@ -955,7 +957,7 @@ out:
        return r;
 }
 
-static int next_free_minor(struct mapped_device *md, int *minor)
+static int next_free_minor(int *minor)
 {
        int r, m;
 
@@ -966,9 +968,8 @@ static int next_free_minor(struct mapped_device *md, int *minor)
        spin_lock(&_minor_lock);
 
        r = idr_get_new(&_minor_idr, MINOR_ALLOCED, &m);
-       if (r) {
+       if (r)
                goto out;
-       }
 
        if (m >= (1 << MINORBITS)) {
                idr_remove(&_minor_idr, m);
@@ -991,7 +992,7 @@ static struct block_device_operations dm_blk_dops;
 static struct mapped_device *alloc_dev(int minor)
 {
        int r;
-       struct mapped_device *md = kmalloc(sizeof(*md), GFP_KERNEL);
+       struct mapped_device *md = kzalloc(sizeof(*md), GFP_KERNEL);
        void *old_md;
 
        if (!md) {
@@ -1004,13 +1005,12 @@ static struct mapped_device *alloc_dev(int minor)
 
        /* get a minor number for the dev */
        if (minor == DM_ANY_MINOR)
-               r = next_free_minor(md, &minor);
+               r = next_free_minor(&minor);
        else
-               r = specific_minor(md, minor);
+               r = specific_minor(minor);
        if (r < 0)
                goto bad_minor;
 
-       memset(md, 0, sizeof(*md));
        init_rwsem(&md->io_lock);
        mutex_init(&md->suspend_lock);
        spin_lock_init(&md->pushback_lock);
index b4584a39383bdeda58fc1f16f596447648f1e110..8c03b634e62e4a8106980750fb9d948b2fb9327f 100644 (file)
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 
-#define DM_NAME "device-mapper"
-
-#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_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) ? \
-                         0 : scnprintf(result + sz, maxlen - sz, x))
-
-#define SECTOR_SHIFT 9
-
-/*
- * Definitions of return values from target end_io function.
- */
-#define DM_ENDIO_INCOMPLETE    1
-#define DM_ENDIO_REQUEUE       2
-
-/*
- * Definitions of return values from target map function.
- */
-#define DM_MAPIO_SUBMITTED     0
-#define DM_MAPIO_REMAPPED      1
-#define DM_MAPIO_REQUEUE       DM_ENDIO_REQUEUE
-
 /*
  * Suspend feature flags
  */
@@ -136,34 +75,6 @@ static inline int array_too_big(unsigned long fixed, unsigned long obj,
        return (num > (ULONG_MAX - fixed) / obj);
 }
 
-/*
- * Ceiling(n / sz)
- */
-#define dm_div_up(n, sz) (((n) + (sz) - 1) / (sz))
-
-#define dm_sector_div_up(n, sz) ( \
-{ \
-       sector_t _r = ((n) + (sz) - 1); \
-       sector_div(_r, (sz)); \
-       _r; \
-} \
-)
-
-/*
- * ceiling(n / size) * size
- */
-#define dm_round_up(n, sz) (dm_div_up((n), (sz)) * (sz))
-
-static inline sector_t to_sector(unsigned long n)
-{
-       return (n >> 9);
-}
-
-static inline unsigned long to_bytes(sector_t n)
-{
-       return (n << 9);
-}
-
 int dm_split_args(int *argc, char ***argvp, char *input);
 
 /*
@@ -189,4 +100,13 @@ int dm_lock_for_deletion(struct mapped_device *md);
 
 void dm_kobject_uevent(struct mapped_device *md);
 
+/*
+ * Dirty log
+ */
+int dm_dirty_log_init(void);
+void dm_dirty_log_exit(void);
+
+int dm_kcopyd_init(void);
+void dm_kcopyd_exit(void);
+
 #endif
diff --git a/drivers/md/kcopyd.h b/drivers/md/kcopyd.h
deleted file mode 100644 (file)
index 4845f2a..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2001 Sistina Software
- *
- * This file is released under the GPL.
- *
- * Kcopyd provides a simple interface for copying an area of one
- * block-device to one or more other block-devices, with an asynchronous
- * completion notification.
- */
-
-#ifndef DM_KCOPYD_H
-#define DM_KCOPYD_H
-
-#include "dm-io.h"
-
-/* FIXME: make this configurable */
-#define KCOPYD_MAX_REGIONS 8
-
-#define KCOPYD_IGNORE_ERROR 1
-
-/*
- * To use kcopyd you must first create a kcopyd client object.
- */
-struct kcopyd_client;
-int kcopyd_client_create(unsigned int num_pages, struct kcopyd_client **result);
-void kcopyd_client_destroy(struct kcopyd_client *kc);
-
-/*
- * Submit a copy job to kcopyd.  This is built on top of the
- * previous three fns.
- *
- * read_err is a boolean,
- * write_err is a bitset, with 1 bit for each destination region
- */
-typedef void (*kcopyd_notify_fn)(int read_err, unsigned long write_err,
-                                void *context);
-
-int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
-               unsigned int num_dests, struct io_region *dests,
-               unsigned int flags, kcopyd_notify_fn fn, void *context);
-
-#endif
index 6477fc66cc2381da08ff3637673e04042388470b..346223856f597e218828aacb233ed18ec3634568 100644 (file)
@@ -299,7 +299,7 @@ static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
 }
 
 /* STK7700-PH: Digital/Analog Hybrid Tuner, e.h. Cinergy HT USB HE */
-struct dibx000_agc_config xc3028_agc_config = {
+static struct dibx000_agc_config xc3028_agc_config = {
        BAND_VHF | BAND_UHF,       /* band_caps */
 
        /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0,
@@ -342,7 +342,7 @@ struct dibx000_agc_config xc3028_agc_config = {
 };
 
 /* PLL Configuration for COFDM BW_MHz = 8.00 with external clock = 30.00 */
-struct dibx000_bandwidth_config xc3028_bw_config = {
+static struct dibx000_bandwidth_config xc3028_bw_config = {
        60000, 30000, /* internal, sampling */
        1, 8, 3, 1, 0, /* pll_cfg: prediv, ratio, range, reset, bypass */
        0, 0, 1, 1, 0, /* misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc,
index 68fab616f55dfa483d62f3d69cb3ad4c6f4ac5ad..f5fceb3cdb3cb0d71b34e7fa8a1bc272cc04f65e 100644 (file)
@@ -307,6 +307,14 @@ config DVB_AU8522
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
          to support this frontend.
 
+config DVB_S5H1411
+       tristate "Samsung S5H1411 based"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+         to support this frontend.
+
 comment "Tuners/PLL support"
        depends on DVB_CORE
 
index 2f873fc0f6498e2aa52dfdcee0cb7b1f44d9c2c1..9747c73dc8269c78c9d8c4e6e7aecbb0a6dded15 100644 (file)
@@ -55,3 +55,4 @@ obj-$(CONFIG_DVB_TUNER_XC5000) += xc5000.o
 obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
 obj-$(CONFIG_DVB_AU8522) += au8522.o
 obj-$(CONFIG_DVB_TDA10048) += tda10048.o
+obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
index 96338f0c4dd47268d60727b9a35b251d62b469ad..de796eab39119506770ea9403e14fa9557dacfdf 100644 (file)
@@ -33,7 +33,7 @@ struct mt312_config {
        u8 demod_address;
 
        /* inverted voltage setting */
-       int voltage_inverted:1;
+       unsigned int voltage_inverted:1;
 };
 
 #if defined(CONFIG_DVB_MT312) || (defined(CONFIG_DVB_MT312_MODULE) && defined(MODULE))
diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb/frontends/s5h1411.c
new file mode 100644 (file)
index 0000000..eb5bfc9
--- /dev/null
@@ -0,0 +1,888 @@
+/*
+    Samsung S5H1411 VSB/QAM demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "dvb-pll.h"
+#include "s5h1411.h"
+
+struct s5h1411_state {
+
+       struct i2c_adapter *i2c;
+
+       /* configuration settings */
+       const struct s5h1411_config *config;
+
+       struct dvb_frontend frontend;
+
+       fe_modulation_t current_modulation;
+
+       u32 current_frequency;
+       int if_freq;
+
+       u8 inversion;
+};
+
+static int debug;
+
+#define dprintk(arg...) do {   \
+       if (debug)              \
+               printk(arg);    \
+       } while (0)
+
+/* Register values to initialise the demod, defaults to VSB */
+static struct init_tab {
+       u8      addr;
+       u8      reg;
+       u16     data;
+} init_tab[] = {
+       { S5H1411_I2C_TOP_ADDR, 0x00, 0x0071, },
+       { S5H1411_I2C_TOP_ADDR, 0x08, 0x0047, },
+       { S5H1411_I2C_TOP_ADDR, 0x1c, 0x0400, },
+       { S5H1411_I2C_TOP_ADDR, 0x1e, 0x0370, },
+       { S5H1411_I2C_TOP_ADDR, 0x1f, 0x342a, },
+       { S5H1411_I2C_TOP_ADDR, 0x24, 0x0231, },
+       { S5H1411_I2C_TOP_ADDR, 0x25, 0x1011, },
+       { S5H1411_I2C_TOP_ADDR, 0x26, 0x0f07, },
+       { S5H1411_I2C_TOP_ADDR, 0x27, 0x0f04, },
+       { S5H1411_I2C_TOP_ADDR, 0x28, 0x070f, },
+       { S5H1411_I2C_TOP_ADDR, 0x29, 0x2820, },
+       { S5H1411_I2C_TOP_ADDR, 0x2a, 0x102e, },
+       { S5H1411_I2C_TOP_ADDR, 0x2b, 0x0220, },
+       { S5H1411_I2C_TOP_ADDR, 0x2e, 0x0d0e, },
+       { S5H1411_I2C_TOP_ADDR, 0x2f, 0x1013, },
+       { S5H1411_I2C_TOP_ADDR, 0x31, 0x171b, },
+       { S5H1411_I2C_TOP_ADDR, 0x32, 0x0e0f, },
+       { S5H1411_I2C_TOP_ADDR, 0x33, 0x0f10, },
+       { S5H1411_I2C_TOP_ADDR, 0x34, 0x170e, },
+       { S5H1411_I2C_TOP_ADDR, 0x35, 0x4b10, },
+       { S5H1411_I2C_TOP_ADDR, 0x36, 0x0f17, },
+       { S5H1411_I2C_TOP_ADDR, 0x3c, 0x1577, },
+       { S5H1411_I2C_TOP_ADDR, 0x3d, 0x081a, },
+       { S5H1411_I2C_TOP_ADDR, 0x3e, 0x77ee, },
+       { S5H1411_I2C_TOP_ADDR, 0x40, 0x1e09, },
+       { S5H1411_I2C_TOP_ADDR, 0x41, 0x0f0c, },
+       { S5H1411_I2C_TOP_ADDR, 0x42, 0x1f10, },
+       { S5H1411_I2C_TOP_ADDR, 0x4d, 0x0509, },
+       { S5H1411_I2C_TOP_ADDR, 0x4e, 0x0a00, },
+       { S5H1411_I2C_TOP_ADDR, 0x50, 0x0000, },
+       { S5H1411_I2C_TOP_ADDR, 0x5b, 0x0000, },
+       { S5H1411_I2C_TOP_ADDR, 0x5c, 0x0008, },
+       { S5H1411_I2C_TOP_ADDR, 0x57, 0x1101, },
+       { S5H1411_I2C_TOP_ADDR, 0x65, 0x007c, },
+       { S5H1411_I2C_TOP_ADDR, 0x68, 0x0512, },
+       { S5H1411_I2C_TOP_ADDR, 0x69, 0x0258, },
+       { S5H1411_I2C_TOP_ADDR, 0x70, 0x0004, },
+       { S5H1411_I2C_TOP_ADDR, 0x71, 0x0007, },
+       { S5H1411_I2C_TOP_ADDR, 0x76, 0x00a9, },
+       { S5H1411_I2C_TOP_ADDR, 0x78, 0x3141, },
+       { S5H1411_I2C_TOP_ADDR, 0x7a, 0x3141, },
+       { S5H1411_I2C_TOP_ADDR, 0xb3, 0x8003, },
+       { S5H1411_I2C_TOP_ADDR, 0xb5, 0xafbb, },
+       { S5H1411_I2C_TOP_ADDR, 0xb5, 0xa6bb, },
+       { S5H1411_I2C_TOP_ADDR, 0xb6, 0x0609, },
+       { S5H1411_I2C_TOP_ADDR, 0xb7, 0x2f06, },
+       { S5H1411_I2C_TOP_ADDR, 0xb8, 0x003f, },
+       { S5H1411_I2C_TOP_ADDR, 0xb9, 0x2700, },
+       { S5H1411_I2C_TOP_ADDR, 0xba, 0xfac8, },
+       { S5H1411_I2C_TOP_ADDR, 0xbe, 0x1003, },
+       { S5H1411_I2C_TOP_ADDR, 0xbf, 0x103f, },
+       { S5H1411_I2C_TOP_ADDR, 0xce, 0x2000, },
+       { S5H1411_I2C_TOP_ADDR, 0xcf, 0x0800, },
+       { S5H1411_I2C_TOP_ADDR, 0xd0, 0x0800, },
+       { S5H1411_I2C_TOP_ADDR, 0xd1, 0x0400, },
+       { S5H1411_I2C_TOP_ADDR, 0xd2, 0x0800, },
+       { S5H1411_I2C_TOP_ADDR, 0xd3, 0x2000, },
+       { S5H1411_I2C_TOP_ADDR, 0xd4, 0x3000, },
+       { S5H1411_I2C_TOP_ADDR, 0xdb, 0x4a9b, },
+       { S5H1411_I2C_TOP_ADDR, 0xdc, 0x1000, },
+       { S5H1411_I2C_TOP_ADDR, 0xde, 0x0001, },
+       { S5H1411_I2C_TOP_ADDR, 0xdf, 0x0000, },
+       { S5H1411_I2C_TOP_ADDR, 0xe3, 0x0301, },
+       { S5H1411_I2C_QAM_ADDR, 0xf3, 0x0000, },
+       { S5H1411_I2C_QAM_ADDR, 0xf3, 0x0001, },
+       { S5H1411_I2C_QAM_ADDR, 0x08, 0x0600, },
+       { S5H1411_I2C_QAM_ADDR, 0x18, 0x4201, },
+       { S5H1411_I2C_QAM_ADDR, 0x1e, 0x6476, },
+       { S5H1411_I2C_QAM_ADDR, 0x21, 0x0830, },
+       { S5H1411_I2C_QAM_ADDR, 0x0c, 0x5679, },
+       { S5H1411_I2C_QAM_ADDR, 0x0d, 0x579b, },
+       { S5H1411_I2C_QAM_ADDR, 0x24, 0x0102, },
+       { S5H1411_I2C_QAM_ADDR, 0x31, 0x7488, },
+       { S5H1411_I2C_QAM_ADDR, 0x32, 0x0a08, },
+       { S5H1411_I2C_QAM_ADDR, 0x3d, 0x8689, },
+       { S5H1411_I2C_QAM_ADDR, 0x49, 0x0048, },
+       { S5H1411_I2C_QAM_ADDR, 0x57, 0x2012, },
+       { S5H1411_I2C_QAM_ADDR, 0x5d, 0x7676, },
+       { S5H1411_I2C_QAM_ADDR, 0x04, 0x0400, },
+       { S5H1411_I2C_QAM_ADDR, 0x58, 0x00c0, },
+       { S5H1411_I2C_QAM_ADDR, 0x5b, 0x0100, },
+};
+
+/* VSB SNR lookup table */
+static struct vsb_snr_tab {
+       u16     val;
+       u16     data;
+} vsb_snr_tab[] = {
+       {  0x39f, 300, },
+       {  0x39b, 295, },
+       {  0x397, 290, },
+       {  0x394, 285, },
+       {  0x38f, 280, },
+       {  0x38b, 275, },
+       {  0x387, 270, },
+       {  0x382, 265, },
+       {  0x37d, 260, },
+       {  0x377, 255, },
+       {  0x370, 250, },
+       {  0x36a, 245, },
+       {  0x364, 240, },
+       {  0x35b, 235, },
+       {  0x353, 230, },
+       {  0x349, 225, },
+       {  0x340, 320, },
+       {  0x337, 215, },
+       {  0x327, 210, },
+       {  0x31b, 205, },
+       {  0x310, 200, },
+       {  0x302, 195, },
+       {  0x2f3, 190, },
+       {  0x2e4, 185, },
+       {  0x2d7, 180, },
+       {  0x2cd, 175, },
+       {  0x2bb, 170, },
+       {  0x2a9, 165, },
+       {  0x29e, 160, },
+       {  0x284, 155, },
+       {  0x27a, 150, },
+       {  0x260, 145, },
+       {  0x23a, 140, },
+       {  0x224, 135, },
+       {  0x213, 130, },
+       {  0x204, 125, },
+       {  0x1fe, 120, },
+       {      0,   0, },
+};
+
+/* QAM64 SNR lookup table */
+static struct qam64_snr_tab {
+       u16     val;
+       u16     data;
+} qam64_snr_tab[] = {
+       {  0x0001,   0, },
+       {  0x0af0, 300, },
+       {  0x0d80, 290, },
+       {  0x10a0, 280, },
+       {  0x14b5, 270, },
+       {  0x1590, 268, },
+       {  0x1680, 266, },
+       {  0x17b0, 264, },
+       {  0x18c0, 262, },
+       {  0x19b0, 260, },
+       {  0x1ad0, 258, },
+       {  0x1d00, 256, },
+       {  0x1da0, 254, },
+       {  0x1ef0, 252, },
+       {  0x2050, 250, },
+       {  0x20f0, 249, },
+       {  0x21d0, 248, },
+       {  0x22b0, 247, },
+       {  0x23a0, 246, },
+       {  0x2470, 245, },
+       {  0x24f0, 244, },
+       {  0x25a0, 243, },
+       {  0x26c0, 242, },
+       {  0x27b0, 241, },
+       {  0x28d0, 240, },
+       {  0x29b0, 239, },
+       {  0x2ad0, 238, },
+       {  0x2ba0, 237, },
+       {  0x2c80, 236, },
+       {  0x2d20, 235, },
+       {  0x2e00, 234, },
+       {  0x2f10, 233, },
+       {  0x3050, 232, },
+       {  0x3190, 231, },
+       {  0x3300, 230, },
+       {  0x3340, 229, },
+       {  0x3200, 228, },
+       {  0x3550, 227, },
+       {  0x3610, 226, },
+       {  0x3600, 225, },
+       {  0x3700, 224, },
+       {  0x3800, 223, },
+       {  0x3920, 222, },
+       {  0x3a20, 221, },
+       {  0x3b30, 220, },
+       {  0x3d00, 219, },
+       {  0x3e00, 218, },
+       {  0x4000, 217, },
+       {  0x4100, 216, },
+       {  0x4300, 215, },
+       {  0x4400, 214, },
+       {  0x4600, 213, },
+       {  0x4700, 212, },
+       {  0x4800, 211, },
+       {  0x4a00, 210, },
+       {  0x4b00, 209, },
+       {  0x4d00, 208, },
+       {  0x4f00, 207, },
+       {  0x5050, 206, },
+       {  0x5200, 205, },
+       {  0x53c0, 204, },
+       {  0x5450, 203, },
+       {  0x5650, 202, },
+       {  0x5820, 201, },
+       {  0x6000, 200, },
+       {  0xffff,   0, },
+};
+
+/* QAM256 SNR lookup table */
+static struct qam256_snr_tab {
+       u16     val;
+       u16     data;
+} qam256_snr_tab[] = {
+       {  0x0001,   0, },
+       {  0x0970, 400, },
+       {  0x0a90, 390, },
+       {  0x0b90, 380, },
+       {  0x0d90, 370, },
+       {  0x0ff0, 360, },
+       {  0x1240, 350, },
+       {  0x1345, 348, },
+       {  0x13c0, 346, },
+       {  0x14c0, 344, },
+       {  0x1500, 342, },
+       {  0x1610, 340, },
+       {  0x1700, 338, },
+       {  0x1800, 336, },
+       {  0x18b0, 334, },
+       {  0x1900, 332, },
+       {  0x1ab0, 330, },
+       {  0x1bc0, 328, },
+       {  0x1cb0, 326, },
+       {  0x1db0, 324, },
+       {  0x1eb0, 322, },
+       {  0x2030, 320, },
+       {  0x2200, 318, },
+       {  0x2280, 316, },
+       {  0x2410, 314, },
+       {  0x25b0, 312, },
+       {  0x27a0, 310, },
+       {  0x2840, 308, },
+       {  0x29d0, 306, },
+       {  0x2b10, 304, },
+       {  0x2d30, 302, },
+       {  0x2f20, 300, },
+       {  0x30c0, 298, },
+       {  0x3260, 297, },
+       {  0x32c0, 296, },
+       {  0x3300, 295, },
+       {  0x33b0, 294, },
+       {  0x34b0, 293, },
+       {  0x35a0, 292, },
+       {  0x3650, 291, },
+       {  0x3800, 290, },
+       {  0x3900, 289, },
+       {  0x3a50, 288, },
+       {  0x3b30, 287, },
+       {  0x3cb0, 286, },
+       {  0x3e20, 285, },
+       {  0x3fa0, 284, },
+       {  0x40a0, 283, },
+       {  0x41c0, 282, },
+       {  0x42f0, 281, },
+       {  0x44a0, 280, },
+       {  0x4600, 279, },
+       {  0x47b0, 278, },
+       {  0x4900, 277, },
+       {  0x4a00, 276, },
+       {  0x4ba0, 275, },
+       {  0x4d00, 274, },
+       {  0x4f00, 273, },
+       {  0x5000, 272, },
+       {  0x51f0, 272, },
+       {  0x53a0, 270, },
+       {  0x5520, 269, },
+       {  0x5700, 268, },
+       {  0x5800, 267, },
+       {  0x5a00, 266, },
+       {  0x5c00, 265, },
+       {  0x5d00, 264, },
+       {  0x5f00, 263, },
+       {  0x6000, 262, },
+       {  0x6200, 261, },
+       {  0x6400, 260, },
+       {  0xffff,   0, },
+};
+
+/* 8 bit registers, 16 bit values */
+static int s5h1411_writereg(struct s5h1411_state *state,
+       u8 addr, u8 reg, u16 data)
+{
+       int ret;
+       u8 buf [] = { reg, data >> 8,  data & 0xff };
+
+       struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
+
+       ret = i2c_transfer(state->i2c, &msg, 1);
+
+       if (ret != 1)
+               printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, "
+                      "ret == %i)\n", __func__, addr, reg, data, ret);
+
+       return (ret != 1) ? -1 : 0;
+}
+
+static u16 s5h1411_readreg(struct s5h1411_state *state, u8 addr, u8 reg)
+{
+       int ret;
+       u8 b0 [] = { reg };
+       u8 b1 [] = { 0, 0 };
+
+       struct i2c_msg msg [] = {
+               { .addr = addr, .flags = 0, .buf = b0, .len = 1 },
+               { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
+
+       ret = i2c_transfer(state->i2c, msg, 2);
+
+       if (ret != 2)
+               printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+                       __func__, ret);
+       return (b1[0] << 8) | b1[1];
+}
+
+static int s5h1411_softreset(struct dvb_frontend *fe)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       dprintk("%s()\n", __func__);
+
+       s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 0);
+       s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 1);
+       return 0;
+}
+
+static int s5h1411_set_if_freq(struct dvb_frontend *fe, int KHz)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       dprintk("%s(%d KHz)\n", __func__, KHz);
+
+       switch (KHz) {
+       case 3250:
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x10d9);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x5342);
+               s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x10d9);
+               break;
+       case 3500:
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1225);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x1e96);
+               s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x1225);
+               break;
+       case 4000:
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x14bc);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0xb53e);
+               s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x14bd);
+               break;
+       default:
+               dprintk("%s(%d KHz) Invalid, defaulting to 5380\n",
+                       __func__, KHz);
+               /* no break, need to continue */
+       case 5380:
+       case 44000:
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1be4);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x3655);
+               s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x1be4);
+               break;
+       }
+
+       state->if_freq = KHz;
+
+       return 0;
+}
+
+static int s5h1411_set_mpeg_timing(struct dvb_frontend *fe, int mode)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+       u16 val;
+
+       dprintk("%s(%d)\n", __func__, mode);
+
+       val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xbe) & 0xcfff;
+       switch (mode) {
+       case S5H1411_MPEGTIMING_CONTINOUS_INVERTING_CLOCK:
+               val |= 0x0000;
+               break;
+       case S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK:
+               dprintk("%s(%d) Mode1 or Defaulting\n", __func__, mode);
+               val |= 0x1000;
+               break;
+       case S5H1411_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK:
+               val |= 0x2000;
+               break;
+       case S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK:
+               val |= 0x3000;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Configure MPEG Signal Timing charactistics */
+       return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbe, val);
+}
+
+static int s5h1411_set_spectralinversion(struct dvb_frontend *fe, int inversion)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+       u16 val;
+
+       dprintk("%s(%d)\n", __func__, inversion);
+       val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x24) & ~0x1000;
+
+       if (inversion == 1)
+               val |= 0x1000; /* Inverted */
+       else
+               val |= 0x0000;
+
+       state->inversion = inversion;
+       return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x24, val);
+}
+
+static int s5h1411_enable_modulation(struct dvb_frontend *fe,
+                                    fe_modulation_t m)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       dprintk("%s(0x%08x)\n", __func__, m);
+
+       switch (m) {
+       case VSB_8:
+               dprintk("%s() VSB_8\n", __func__);
+               s5h1411_set_if_freq(fe, state->config->vsb_if);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x71);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf6, 0x00);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xcd, 0xf1);
+               break;
+       case QAM_64:
+       case QAM_256:
+               dprintk("%s() QAM_AUTO (64/256)\n", __func__);
+               s5h1411_set_if_freq(fe, state->config->qam_if);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x0171);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf6, 0x0001);
+               s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x16, 0x1101);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xcd, 0x00f0);
+               break;
+       default:
+               dprintk("%s() Invalid modulation\n", __func__);
+               return -EINVAL;
+       }
+
+       state->current_modulation = m;
+       s5h1411_softreset(fe);
+
+       return 0;
+}
+
+static int s5h1411_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       dprintk("%s(%d)\n", __func__, enable);
+
+       if (enable)
+               return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
+       else
+               return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 0);
+}
+
+static int s5h1411_set_gpio(struct dvb_frontend *fe, int enable)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+       u16 val;
+
+       dprintk("%s(%d)\n", __func__, enable);
+
+       val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xe0) & ~0x02;
+
+       if (enable)
+               return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0,
+                               val | 0x02);
+       else
+               return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0, val);
+}
+
+static int s5h1411_sleep(struct dvb_frontend *fe, int enable)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       dprintk("%s(%d)\n", __func__, enable);
+
+       if (enable)
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 1);
+       else {
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 0);
+               s5h1411_softreset(fe);
+       }
+
+       return 0;
+}
+
+static int s5h1411_register_reset(struct dvb_frontend *fe)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       dprintk("%s()\n", __func__);
+
+       return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf3, 0);
+}
+
+/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
+static int s5h1411_set_frontend(struct dvb_frontend *fe,
+       struct dvb_frontend_parameters *p)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       dprintk("%s(frequency=%d)\n", __func__, p->frequency);
+
+       s5h1411_softreset(fe);
+
+       state->current_frequency = p->frequency;
+
+       s5h1411_enable_modulation(fe, p->u.vsb.modulation);
+
+       /* Allow the demod to settle */
+       msleep(100);
+
+       if (fe->ops.tuner_ops.set_params) {
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+
+               fe->ops.tuner_ops.set_params(fe, p);
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+
+       return 0;
+}
+
+/* Reset the demod hardware and reset all of the configuration registers
+   to a default state. */
+static int s5h1411_init(struct dvb_frontend *fe)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+       int i;
+
+       dprintk("%s()\n", __func__);
+
+       s5h1411_sleep(fe, 0);
+       s5h1411_register_reset(fe);
+
+       for (i = 0; i < ARRAY_SIZE(init_tab); i++)
+               s5h1411_writereg(state, init_tab[i].addr,
+                       init_tab[i].reg,
+                       init_tab[i].data);
+
+       /* The datasheet says that after initialisation, VSB is default */
+       state->current_modulation = VSB_8;
+
+       if (state->config->output_mode == S5H1411_SERIAL_OUTPUT)
+               /* Serial */
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1101);
+       else
+               /* Parallel */
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1001);
+
+       s5h1411_set_spectralinversion(fe, state->config->inversion);
+       s5h1411_set_if_freq(fe, state->config->vsb_if);
+       s5h1411_set_gpio(fe, state->config->gpio);
+       s5h1411_set_mpeg_timing(fe, state->config->mpeg_timing);
+       s5h1411_softreset(fe);
+
+       /* Note: Leaving the I2C gate closed. */
+       s5h1411_i2c_gate_ctrl(fe, 0);
+
+       return 0;
+}
+
+static int s5h1411_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+       u16 reg;
+       u32 tuner_status = 0;
+
+       *status = 0;
+
+       /* Get the demodulator status */
+       reg = (s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2) >> 15)
+               & 0x0001;
+       if (reg)
+               *status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_SIGNAL;
+
+       switch (state->current_modulation) {
+       case QAM_64:
+       case QAM_256:
+               reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf0);
+               if (reg & 0x100)
+                       *status |= FE_HAS_VITERBI;
+               if (reg & 0x10)
+                       *status |= FE_HAS_SYNC;
+               break;
+       case VSB_8:
+               reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x5e);
+               if (reg & 0x0001)
+                       *status |= FE_HAS_SYNC;
+               reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2);
+               if (reg & 0x1000)
+                       *status |= FE_HAS_VITERBI;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (state->config->status_mode) {
+       case S5H1411_DEMODLOCKING:
+               if (*status & FE_HAS_VITERBI)
+                       *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+               break;
+       case S5H1411_TUNERLOCKING:
+               /* Get the tuner status */
+               if (fe->ops.tuner_ops.get_status) {
+                       if (fe->ops.i2c_gate_ctrl)
+                               fe->ops.i2c_gate_ctrl(fe, 1);
+
+                       fe->ops.tuner_ops.get_status(fe, &tuner_status);
+
+                       if (fe->ops.i2c_gate_ctrl)
+                               fe->ops.i2c_gate_ctrl(fe, 0);
+               }
+               if (tuner_status)
+                       *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+               break;
+       }
+
+       dprintk("%s() status 0x%08x\n", __func__, *status);
+
+       return 0;
+}
+
+static int s5h1411_qam256_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
+{
+       int i, ret = -EINVAL;
+       dprintk("%s()\n", __func__);
+
+       for (i = 0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
+               if (v < qam256_snr_tab[i].val) {
+                       *snr = qam256_snr_tab[i].data;
+                       ret = 0;
+                       break;
+               }
+       }
+       return ret;
+}
+
+static int s5h1411_qam64_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
+{
+       int i, ret = -EINVAL;
+       dprintk("%s()\n", __func__);
+
+       for (i = 0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
+               if (v < qam64_snr_tab[i].val) {
+                       *snr = qam64_snr_tab[i].data;
+                       ret = 0;
+                       break;
+               }
+       }
+       return ret;
+}
+
+static int s5h1411_vsb_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
+{
+       int i, ret = -EINVAL;
+       dprintk("%s()\n", __func__);
+
+       for (i = 0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
+               if (v > vsb_snr_tab[i].val) {
+                       *snr = vsb_snr_tab[i].data;
+                       ret = 0;
+                       break;
+               }
+       }
+       dprintk("%s() snr=%d\n", __func__, *snr);
+       return ret;
+}
+
+static int s5h1411_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+       u16 reg;
+       dprintk("%s()\n", __func__);
+
+       switch (state->current_modulation) {
+       case QAM_64:
+               reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf1);
+               return s5h1411_qam64_lookup_snr(fe, snr, reg);
+       case QAM_256:
+               reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf1);
+               return s5h1411_qam256_lookup_snr(fe, snr, reg);
+       case VSB_8:
+               reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR,
+                       0xf2) & 0x3ff;
+               return s5h1411_vsb_lookup_snr(fe, snr, reg);
+       default:
+               break;
+       }
+
+       return -EINVAL;
+}
+
+static int s5h1411_read_signal_strength(struct dvb_frontend *fe,
+       u16 *signal_strength)
+{
+       return s5h1411_read_snr(fe, signal_strength);
+}
+
+static int s5h1411_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       *ucblocks = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xc9);
+
+       return 0;
+}
+
+static int s5h1411_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       return s5h1411_read_ucblocks(fe, ber);
+}
+
+static int s5h1411_get_frontend(struct dvb_frontend *fe,
+                               struct dvb_frontend_parameters *p)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       p->frequency = state->current_frequency;
+       p->u.vsb.modulation = state->current_modulation;
+
+       return 0;
+}
+
+static int s5h1411_get_tune_settings(struct dvb_frontend *fe,
+                                    struct dvb_frontend_tune_settings *tune)
+{
+       tune->min_delay_ms = 1000;
+       return 0;
+}
+
+static void s5h1411_release(struct dvb_frontend *fe)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+       kfree(state);
+}
+
+static struct dvb_frontend_ops s5h1411_ops;
+
+struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
+                                   struct i2c_adapter *i2c)
+{
+       struct s5h1411_state *state = NULL;
+       u16 reg;
+
+       /* allocate memory for the internal state */
+       state = kmalloc(sizeof(struct s5h1411_state), GFP_KERNEL);
+       if (state == NULL)
+               goto error;
+
+       /* setup the state */
+       state->config = config;
+       state->i2c = i2c;
+       state->current_modulation = VSB_8;
+       state->inversion = state->config->inversion;
+
+       /* check if the demod exists */
+       reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x05);
+       if (reg != 0x0066)
+               goto error;
+
+       /* create dvb_frontend */
+       memcpy(&state->frontend.ops, &s5h1411_ops,
+              sizeof(struct dvb_frontend_ops));
+
+       state->frontend.demodulator_priv = state;
+
+       if (s5h1411_init(&state->frontend) != 0) {
+               printk(KERN_ERR "%s: Failed to initialize correctly\n",
+                       __func__);
+               goto error;
+       }
+
+       /* Note: Leaving the I2C gate open here. */
+       s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
+
+       return &state->frontend;
+
+error:
+       kfree(state);
+       return NULL;
+}
+EXPORT_SYMBOL(s5h1411_attach);
+
+static struct dvb_frontend_ops s5h1411_ops = {
+
+       .info = {
+               .name                   = "Samsung S5H1411 QAM/8VSB Frontend",
+               .type                   = FE_ATSC,
+               .frequency_min          = 54000000,
+               .frequency_max          = 858000000,
+               .frequency_stepsize     = 62500,
+               .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+       },
+
+       .init                 = s5h1411_init,
+       .i2c_gate_ctrl        = s5h1411_i2c_gate_ctrl,
+       .set_frontend         = s5h1411_set_frontend,
+       .get_frontend         = s5h1411_get_frontend,
+       .get_tune_settings    = s5h1411_get_tune_settings,
+       .read_status          = s5h1411_read_status,
+       .read_ber             = s5h1411_read_ber,
+       .read_signal_strength = s5h1411_read_signal_strength,
+       .read_snr             = s5h1411_read_snr,
+       .read_ucblocks        = s5h1411_read_ucblocks,
+       .release              = s5h1411_release,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+MODULE_DESCRIPTION("Samsung S5H1411 QAM-B/ATSC Demodulator driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
diff --git a/drivers/media/dvb/frontends/s5h1411.h b/drivers/media/dvb/frontends/s5h1411.h
new file mode 100644 (file)
index 0000000..1855f64
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+    Samsung S5H1411 VSB/QAM demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __S5H1411_H__
+#define __S5H1411_H__
+
+#include <linux/dvb/frontend.h>
+
+#define S5H1411_I2C_TOP_ADDR (0x32 >> 1)
+#define S5H1411_I2C_QAM_ADDR (0x34 >> 1)
+
+struct s5h1411_config {
+
+       /* serial/parallel output */
+#define S5H1411_PARALLEL_OUTPUT 0
+#define S5H1411_SERIAL_OUTPUT   1
+       u8 output_mode;
+
+       /* GPIO Setting */
+#define S5H1411_GPIO_OFF 0
+#define S5H1411_GPIO_ON  1
+       u8 gpio;
+
+       /* MPEG signal timing */
+#define S5H1411_MPEGTIMING_CONTINOUS_INVERTING_CLOCK       0
+#define S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK    1
+#define S5H1411_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK    2
+#define S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK 3
+       u16 mpeg_timing;
+
+       /* IF Freq for QAM and VSB in KHz */
+#define S5H1411_IF_2500  2500
+#define S5H1411_IF_3500  3500
+#define S5H1411_IF_4000  4000
+#define S5H1411_IF_5380  5380
+#define S5H1411_IF_44000 44000
+#define S5H1411_VSB_IF_DEFAULT S5H1411_IF_44000
+#define S5H1411_QAM_IF_DEFAULT S5H1411_IF_44000
+       u16 qam_if;
+       u16 vsb_if;
+
+       /* Spectral Inversion */
+#define S5H1411_INVERSION_OFF 0
+#define S5H1411_INVERSION_ON  1
+       u8 inversion;
+
+       /* Return lock status based on tuner lock, or demod lock */
+#define S5H1411_TUNERLOCKING 0
+#define S5H1411_DEMODLOCKING 1
+       u8 status_mode;
+};
+
+#if defined(CONFIG_DVB_S5H1411) || \
+       (defined(CONFIG_DVB_S5H1411_MODULE) && defined(MODULE))
+extern struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
+                                          struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *s5h1411_attach(
+       const struct s5h1411_config *config,
+       struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif /* CONFIG_DVB_S5H1411 */
+
+#endif /* __S5H1411_H__ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
index c97c4bd24841a987dc6a8d50b77274636e845d56..41708267e7a4f64a2b5548014eb8f3678871c51f 100644 (file)
@@ -1,7 +1,7 @@
 
 config VIDEO_AU0828
        tristate "Auvitek AU0828 support"
-       depends on VIDEO_DEV && I2C && INPUT
+       depends on VIDEO_DEV && I2C && INPUT && DVB_CORE
        select I2C_ALGOBIT
        select DVB_AU8522 if !DVB_FE_CUSTOMIZE
        select DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
index 8ca91f814277d0ced5d9b1e7ccb1914d15d50727..a2a6983444fa0d8fe146ceadcaabab3378e6d28f 100644 (file)
@@ -36,7 +36,6 @@ struct au0828_board au0828_boards[] = {
                .name   = "DViCO FusionHDTV USB",
        },
 };
-const unsigned int au0828_bcount = ARRAY_SIZE(au0828_boards);
 
 /* Tuner callback function for au0828 boards. Currently only needed
  * for HVR1500Q, which has an xc5000 tuner.
index e65d5642cb1d3b6ae64ce65b0bb7597e24a606a4..54bfc0f05295571eca21b3d8595c7443e940ca0f 100644 (file)
  * 4 = I2C related
  * 8 = Bridge related
  */
-unsigned int debug;
-module_param(debug, int, 0644);
+int au0828_debug;
+module_param_named(debug, au0828_debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable debug messages");
 
-unsigned int usb_debug;
-module_param(usb_debug, int, 0644);
-MODULE_PARM_DESC(usb_debug, "enable usb debug messages");
-
-unsigned int bridge_debug;
-module_param(bridge_debug, int, 0644);
-MODULE_PARM_DESC(bridge_debug, "enable bridge debug messages");
-
 #define _AU0828_BULKPIPE 0x03
 #define _BULKPIPESIZE 0xffff
 
@@ -229,24 +221,18 @@ static int __init au0828_init(void)
 {
        int ret;
 
-       if (debug)
+       if (au0828_debug & 1)
                printk(KERN_INFO "%s() Debugging is enabled\n", __func__);
 
-       if (usb_debug) {
+       if (au0828_debug & 2)
                printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__);
-               debug |= 2;
-       }
 
-       if (i2c_debug) {
+       if (au0828_debug & 4)
                printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__);
-               debug |= 4;
-       }
 
-       if (bridge_debug) {
+       if (au0828_debug & 8)
                printk(KERN_INFO "%s() Bridge Debugging is enabled\n",
                       __func__);
-               debug |= 8;
-       }
 
        printk(KERN_INFO "au0828 driver loaded\n");
 
index 85d0ae9a322f2c1fd43c36a7a7e28842ce91498e..5040d7fc4af56ea14f4307488915a6cac3764498 100644 (file)
@@ -204,7 +204,7 @@ static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
        return ret;
 }
 
-int dvb_register(struct au0828_dev *dev)
+static int dvb_register(struct au0828_dev *dev)
 {
        struct au0828_dvb *dvb = &dev->dvb;
        int result;
index 94c8b74a6651ddfc62099efd89629ed4dc768a97..741a4937b050c05ae92e2eee1a534f89414f3d1f 100644 (file)
 
 #include <media/v4l2-common.h>
 
-unsigned int i2c_debug;
-module_param(i2c_debug, int, 0444);
-MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
-
-unsigned int i2c_scan;
+static int i2c_scan;
 module_param(i2c_scan, int, 0444);
 MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
 
index 0200b9fc5dc442337bc4f4b7809b22bc7645df6e..7beb571798e5d04de72ad9ce45f55d6ed8aa0b55 100644 (file)
@@ -96,15 +96,12 @@ struct au0828_buff {
 /* au0828-core.c */
 extern u32 au0828_read(struct au0828_dev *dev, u16 reg);
 extern u32 au0828_write(struct au0828_dev *dev, u16 reg, u32 val);
-extern unsigned int debug;
-extern unsigned int usb_debug;
-extern unsigned int bridge_debug;
+extern int au0828_debug;
 
 /* ----------------------------------------------------------- */
 /* au0828-cards.c */
 extern struct au0828_board au0828_boards[];
 extern struct usb_device_id au0828_usb_id_table[];
-extern const unsigned int au0828_bcount;
 extern void au0828_gpio_setup(struct au0828_dev *dev);
 extern int au0828_tuner_callback(void *priv, int command, int arg);
 extern void au0828_card_setup(struct au0828_dev *dev);
@@ -115,7 +112,6 @@ extern int au0828_i2c_register(struct au0828_dev *dev);
 extern int au0828_i2c_unregister(struct au0828_dev *dev);
 extern void au0828_call_i2c_clients(struct au0828_dev *dev,
        unsigned int cmd, void *arg);
-extern unsigned int i2c_debug;
 
 /* ----------------------------------------------------------- */
 /* au0828-dvb.c */
@@ -123,6 +119,6 @@ extern int au0828_dvb_register(struct au0828_dev *dev);
 extern void au0828_dvb_unregister(struct au0828_dev *dev);
 
 #define dprintk(level, fmt, arg...)\
-       do { if (debug & level)\
+       do { if (au0828_debug & level)\
                printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\
        } while (0)
index 870d6e197d65152f8c54b1ef0efcf848edbfd6f6..f05649727b60d9d434c435589fb4f78baaea22e4 100644 (file)
@@ -191,7 +191,7 @@ static struct tda18271_config hauppauge_hvr1200_tuner_config = {
        .gate    = TDA18271_GATE_ANALOG,
 };
 
-struct dibx000_agc_config xc3028_agc_config = {
+static struct dibx000_agc_config xc3028_agc_config = {
        BAND_VHF | BAND_UHF,    /* band_caps */
 
        /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0,
@@ -237,7 +237,7 @@ struct dibx000_agc_config xc3028_agc_config = {
 
 /* PLL Configuration for COFDM BW_MHz = 8.000000
  * With external clock = 30.000000 */
-struct dibx000_bandwidth_config xc3028_bw_config = {
+static struct dibx000_bandwidth_config xc3028_bw_config = {
        60000,  /* internal */
        30000,  /* sampling */
        1,      /* pll_cfg: prediv */
index bcf6d9ba063da738dc77f811308467f3a955cff4..27635cdcbaf22d5457f419ff7e9b621dd77826ef 100644 (file)
@@ -58,6 +58,7 @@ config VIDEO_CX88_DVB
        select DVB_CX24123 if !DVB_FE_CUSTOMISE
        select DVB_ISL6421 if !DVB_FE_CUSTOMISE
        select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
        ---help---
          This adds support for DVB/ATSC cards based on the
          Conexant 2388x chip.
index 61c4f72644b8d2e56ee391915d51409d1922c425..6c0c94c5ef91113e8b875b52f823c1e2cccb50c5 100644 (file)
@@ -546,10 +546,12 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
                if (retval < 0)
                        return retval;
 
-               dev->mailbox = blackbird_find_mailbox(dev);
-               if (dev->mailbox < 0)
+               retval = blackbird_find_mailbox(dev);
+               if (retval < 0)
                        return -1;
 
+               dev->mailbox = retval;
+
                retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
                if (retval < 0) {
                        dprintk(0, "ERROR: Firmware ping failed!\n");
index 620159d05506d1c55675ce9ada91c999c14adce0..2b6b283cda15b658c08d1841328350c80aa069f2 100644 (file)
@@ -1591,6 +1591,7 @@ static const struct cx88_board cx88_boards[] = {
                        .vmux   = 2,
                        .gpio0  = 0x16d9,
                }},
+               .mpeg           = CX88_MPEG_DVB,
        },
        [CX88_BOARD_PROLINK_PV_8000GT] = {
                .name           = "Prolink Pixelview MPEG 8000GT",
index f1251b844e0823c48128b27fd03b437be611e578..1c7fe6862a60c05b3f758467bb7dba6fe001985a 100644 (file)
@@ -47,6 +47,7 @@
 #include "isl6421.h"
 #include "tuner-simple.h"
 #include "tda9887.h"
+#include "s5h1411.h"
 
 MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
 MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
@@ -463,6 +464,22 @@ static struct zl10353_config cx88_geniatech_x8000_mt = {
        .no_tuner = 1,
 };
 
+static struct s5h1411_config dvico_fusionhdtv7_config = {
+       .output_mode   = S5H1411_SERIAL_OUTPUT,
+       .gpio          = S5H1411_GPIO_ON,
+       .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+       .qam_if        = S5H1411_IF_44000,
+       .vsb_if        = S5H1411_IF_44000,
+       .inversion     = S5H1411_INVERSION_OFF,
+       .status_mode   = S5H1411_DEMODLOCKING
+};
+
+static struct xc5000_config dvico_fusionhdtv7_tuner_config = {
+       .i2c_address    = 0xc2 >> 1,
+       .if_khz         = 5380,
+       .tuner_callback = cx88_tuner_callback,
+};
+
 static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
 {
        struct dvb_frontend *fe;
@@ -844,6 +861,21 @@ static int dvb_register(struct cx8802_dev *dev)
                if (attach_xc3028(0x61, dev) < 0)
                        return -EINVAL;
                break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
+               dev->dvb.frontend = dvb_attach(s5h1411_attach,
+                                              &dvico_fusionhdtv7_config,
+                                              &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       /* tuner_config.video_dev must point to
+                        * i2c_adap.algo_data
+                        */
+                       dvico_fusionhdtv7_tuner_config.priv =
+                                               dev->core->i2c_adap.algo_data;
+                       dvb_attach(xc5000_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap,
+                                  &dvico_fusionhdtv7_tuner_config);
+               }
+               break;
        default:
                printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
                       dev->core->name);
index f8c41d8c74c4173be55d517b1647b2bf244d27bf..5d837c16ee22ad10908cce01c0ef0d89768f14ed 100644 (file)
@@ -650,7 +650,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets,
 
        dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
                                              GFP_KERNEL);
-       if (!dev->isoc_ctl.urb) {
+       if (!dev->isoc_ctl.transfer_buffer) {
                em28xx_errdev("cannot allocate memory for usbtransfer\n");
                kfree(dev->isoc_ctl.urb);
                return -ENOMEM;
index 11c5fdedc23bc341fb82ab4459d42b53bcab9a5f..7b65f5e537f803355593a85cf73b984843d851c3 100644 (file)
@@ -509,8 +509,11 @@ static int ir_probe(struct i2c_adapter *adap)
        static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 };
        static const int probe_cx23885[] = { 0x6b, -1 };
        const int *probe;
-       struct i2c_client *c;
-       unsigned char buf;
+       struct i2c_msg msg = {
+               .flags = I2C_M_RD,
+               .len = 0,
+               .buf = NULL,
+       };
        int i, rc;
 
        switch (adap->id) {
@@ -536,23 +539,17 @@ static int ir_probe(struct i2c_adapter *adap)
                return 0;
        }
 
-       c = kzalloc(sizeof(*c), GFP_KERNEL);
-       if (!c)
-               return -ENOMEM;
-
-       c->adapter = adap;
        for (i = 0; -1 != probe[i]; i++) {
-               c->addr = probe[i];
-               rc = i2c_master_recv(c, &buf, 0);
+               msg.addr = probe[i];
+               rc = i2c_transfer(adap, &msg, 1);
                dprintk(1,"probe 0x%02x @ %s: %s\n",
                        probe[i], adap->name,
-                       (0 == rc) ? "yes" : "no");
-               if (0 == rc) {
+                       (1 == rc) ? "yes" : "no");
+               if (1 == rc) {
                        ir_attach(adap, probe[i], 0, 0);
                        break;
                }
        }
-       kfree(c);
        return 0;
 }
 
index a8da90f69dd91eba11285efcf2d706839a40791b..158b3d0c653282bf27ca31352be43a8a46ddf173 100644 (file)
@@ -64,6 +64,7 @@ config VIDEO_PVRUSB2_DVB
        depends on VIDEO_PVRUSB2 && DVB_CORE && EXPERIMENTAL
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
        select DVB_S5H1409 if !DVB_FE_CUSTOMISE
+       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
        select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
        select DVB_TDA18271 if !DVB_FE_CUSTOMIZE
        select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
index 2dd06a90adce435869226611f0864d77ee2f3d65..3a141d93e1a9f2cff4792545bc697aedd5e60b29 100644 (file)
@@ -36,6 +36,7 @@ pvr2_device_desc structures.
 #include "pvrusb2-hdw-internal.h"
 #include "lgdt330x.h"
 #include "s5h1409.h"
+#include "s5h1411.h"
 #include "tda10048.h"
 #include "tda18271.h"
 #include "tda8290.h"
@@ -368,6 +369,15 @@ static struct s5h1409_config pvr2_s5h1409_config = {
        .status_mode   = S5H1409_DEMODLOCKING,
 };
 
+static struct s5h1411_config pvr2_s5h1411_config = {
+       .output_mode   = S5H1411_PARALLEL_OUTPUT,
+       .gpio          = S5H1411_GPIO_OFF,
+       .vsb_if        = S5H1411_IF_44000,
+       .qam_if        = S5H1411_IF_4000,
+       .inversion     = S5H1411_INVERSION_ON,
+       .status_mode   = S5H1411_DEMODLOCKING,
+};
+
 static struct tda18271_std_map hauppauge_tda18271_std_map = {
        .atsc_6   = { .if_freq = 5380, .agc_mode = 3, .std = 3,
                      .if_lvl = 6, .rfagc_top = 0x37, },
@@ -390,6 +400,16 @@ static int pvr2_s5h1409_attach(struct pvr2_dvb_adapter *adap)
        return -EIO;
 }
 
+static int pvr2_s5h1411_attach(struct pvr2_dvb_adapter *adap)
+{
+       adap->fe = dvb_attach(s5h1411_attach, &pvr2_s5h1411_config,
+                             &adap->channel.hdw->i2c_adap);
+       if (adap->fe)
+               return 0;
+
+       return -EIO;
+}
+
 static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
 {
        dvb_attach(tda829x_attach, adap->fe,
@@ -406,6 +426,11 @@ struct pvr2_dvb_props pvr2_750xx_dvb_props = {
        .frontend_attach = pvr2_s5h1409_attach,
        .tuner_attach    = pvr2_tda18271_8295_attach,
 };
+
+struct pvr2_dvb_props pvr2_751xx_dvb_props = {
+       .frontend_attach = pvr2_s5h1411_attach,
+       .tuner_attach    = pvr2_tda18271_8295_attach,
+};
 #endif
 
 static const char *pvr2_client_75xxx[] = {
@@ -454,6 +479,9 @@ static const struct pvr2_device_desc pvr2_device_751xx = {
                .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
                .default_std_mask = V4L2_STD_NTSC_M,
                .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+               .dvb_props = &pvr2_751xx_dvb_props,
+#endif
 };
 
 
index c2e2b06fe2e0bbeb80d791309495591e4d75e9da..d016f8b6c70b478153fb726718d08ca57adf6d34 100644 (file)
@@ -104,28 +104,28 @@ struct pvr2_device_desc {
        unsigned char digital_control_scheme;
 
        /* If set, we don't bother trying to load cx23416 firmware. */
-       int flag_skip_cx23416_firmware:1;
+       unsigned int flag_skip_cx23416_firmware:1;
 
        /* If set, the encoder must be healthy in order for digital mode to
           work (otherwise we assume that digital streaming will work even
           if we fail to locate firmware for the encoder).  If the device
           doesn't support digital streaming then this flag has no
           effect. */
-       int flag_digital_requires_cx23416:1;
+       unsigned int flag_digital_requires_cx23416:1;
 
        /* Device has a hauppauge eeprom which we can interrogate. */
-       int flag_has_hauppauge_rom:1;
+       unsigned int flag_has_hauppauge_rom:1;
 
        /* Device does not require a powerup command to be issued. */
-       int flag_no_powerup:1;
+       unsigned int flag_no_powerup:1;
 
        /* Device has a cx25840 - this enables special additional logic to
           handle it. */
-       int flag_has_cx25840:1;
+       unsigned int flag_has_cx25840:1;
 
        /* Device has a wm8775 - this enables special additional logic to
           ensure that it is found. */
-       int flag_has_wm8775:1;
+       unsigned int flag_has_wm8775:1;
 
        /* Device has IR hardware that can be faked into looking like a
           normal Hauppauge i2c IR receiver.  This is currently very
@@ -135,15 +135,15 @@ struct pvr2_device_desc {
           to virtualize the presence of the non-existant IR receiver chip and
           implement the virtual receiver in terms of appropriate FX2
           commands. */
-       int flag_has_hauppauge_custom_ir:1;
+       unsigned int flag_has_hauppauge_custom_ir:1;
 
        /* These bits define which kinds of sources the device can handle.
           Note: Digital tuner presence is inferred by the
           digital_control_scheme enumeration. */
-       int flag_has_fmradio:1;       /* Has FM radio receiver */
-       int flag_has_analogtuner:1;   /* Has analog tuner */
-       int flag_has_composite:1;     /* Has composite input */
-       int flag_has_svideo:1;        /* Has s-video input */
+       unsigned int flag_has_fmradio:1;       /* Has FM radio receiver */
+       unsigned int flag_has_analogtuner:1;   /* Has analog tuner */
+       unsigned int flag_has_composite:1;     /* Has composite input */
+       unsigned int flag_has_svideo:1;        /* Has s-video input */
 };
 
 extern struct usb_device_id pvr2_device_table[];
index 529e00952a8db1c0b813f8f3ae06c1d62d067e3b..2b72e10e6b9f3274c1f6408f0625fc437706a10d 100644 (file)
@@ -369,19 +369,13 @@ static void set_type(struct i2c_client *c, unsigned int type,
                break;
        }
        case TUNER_TEA5767:
-               if (tea5767_attach(&t->fe, t->i2c->adapter, t->i2c->addr) == NULL) {
-                       t->type = TUNER_ABSENT;
-                       t->mode_mask = T_UNINITIALIZED;
-                       return;
-               }
+               if (!tea5767_attach(&t->fe, t->i2c->adapter, t->i2c->addr))
+                       goto attach_failed;
                t->mode_mask = T_RADIO;
                break;
        case TUNER_TEA5761:
-               if (tea5761_attach(&t->fe, t->i2c->adapter, t->i2c->addr) == NULL) {
-                       t->type = TUNER_ABSENT;
-                       t->mode_mask = T_UNINITIALIZED;
-                       return;
-               }
+               if (!tea5761_attach(&t->fe, t->i2c->adapter, t->i2c->addr))
+                       goto attach_failed;
                t->mode_mask = T_RADIO;
                break;
        case TUNER_PHILIPS_FMD1216ME_MK3:
@@ -394,12 +388,9 @@ static void set_type(struct i2c_client *c, unsigned int type,
                buffer[2] = 0x86;
                buffer[3] = 0x54;
                i2c_master_send(c, buffer, 4);
-               if (simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr,
-                                       t->type) == NULL) {
-                       t->type = TUNER_ABSENT;
-                       t->mode_mask = T_UNINITIALIZED;
-                       return;
-               }
+               if (!simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr,
+                                       t->type))
+                       goto attach_failed;
                break;
        case TUNER_PHILIPS_TD1316:
                buffer[0] = 0x0b;
@@ -407,12 +398,9 @@ static void set_type(struct i2c_client *c, unsigned int type,
                buffer[2] = 0x86;
                buffer[3] = 0xa4;
                i2c_master_send(c,buffer,4);
-               if (simple_tuner_attach(&t->fe, t->i2c->adapter,
-                                       t->i2c->addr, t->type) == NULL) {
-                       t->type = TUNER_ABSENT;
-                       t->mode_mask = T_UNINITIALIZED;
-                       return;
-               }
+               if (!simple_tuner_attach(&t->fe, t->i2c->adapter,
+                                       t->i2c->addr, t->type))
+                       goto attach_failed;
                break;
        case TUNER_XC2028:
        {
@@ -421,40 +409,34 @@ static void set_type(struct i2c_client *c, unsigned int type,
                        .i2c_addr  = t->i2c->addr,
                        .callback  = t->tuner_callback,
                };
-               if (!xc2028_attach(&t->fe, &cfg)) {
-                       t->type = TUNER_ABSENT;
-                       t->mode_mask = T_UNINITIALIZED;
-                       return;
-               }
+               if (!xc2028_attach(&t->fe, &cfg))
+                       goto attach_failed;
                break;
        }
        case TUNER_TDA9887:
                tda9887_attach(&t->fe, t->i2c->adapter, t->i2c->addr);
                break;
        case TUNER_XC5000:
+       {
+               struct dvb_tuner_ops *xc_tuner_ops;
+
                xc5000_cfg.i2c_address    = t->i2c->addr;
                xc5000_cfg.if_khz         = 5380;
                xc5000_cfg.priv           = c->adapter->algo_data;
                xc5000_cfg.tuner_callback = t->tuner_callback;
-               if (!xc5000_attach(&t->fe, t->i2c->adapter, &xc5000_cfg)) {
-                       t->type = TUNER_ABSENT;
-                       t->mode_mask = T_UNINITIALIZED;
-                       return;
-               }
-               {
-               struct dvb_tuner_ops *xc_tuner_ops;
+               if (!xc5000_attach(&t->fe, t->i2c->adapter, &xc5000_cfg))
+                       goto attach_failed;
+
                xc_tuner_ops = &t->fe.ops.tuner_ops;
-               if(xc_tuner_ops->init != NULL)
+               if (xc_tuner_ops->init)
                        xc_tuner_ops->init(&t->fe);
-               }
                break;
+       }
        default:
-               if (simple_tuner_attach(&t->fe, t->i2c->adapter,
-                                       t->i2c->addr, t->type) == NULL) {
-                       t->type = TUNER_ABSENT;
-                       t->mode_mask = T_UNINITIALIZED;
-                       return;
-               }
+               if (!simple_tuner_attach(&t->fe, t->i2c->adapter,
+                                       t->i2c->addr, t->type))
+                       goto attach_failed;
+
                break;
        }
 
@@ -476,11 +458,27 @@ static void set_type(struct i2c_client *c, unsigned int type,
        if (t->mode_mask == T_UNINITIALIZED)
                t->mode_mask = new_mode_mask;
 
-       set_freq(c, (V4L2_TUNER_RADIO == t->mode) ? t->radio_freq : t->tv_freq);
+       /* xc2028/3028 and xc5000 requires a firmware to be set-up later
+          trying to set a frequency here will just fail
+          FIXME: better to move set_freq to the tuner code. This is needed
+          on analog tuners for PLL to properly work
+        */
+       if (t->type != TUNER_XC2028 && t->type != TUNER_XC5000)
+               set_freq(c, (V4L2_TUNER_RADIO == t->mode) ?
+                           t->radio_freq : t->tv_freq);
+
        tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
                  c->adapter->name, c->driver->driver.name, c->addr << 1, type,
                  t->mode_mask);
        tuner_i2c_address_check(t);
+       return;
+
+attach_failed:
+       tuner_dbg("Tuner attach for type = %d failed.\n", t->type);
+       t->type = TUNER_ABSENT;
+       t->mode_mask = T_UNINITIALIZED;
+
+       return;
 }
 
 /*
@@ -495,14 +493,16 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
 {
        struct tuner *t = i2c_get_clientdata(c);
 
-       tuner_dbg("set addr for type %i\n", t->type);
-
        if ( (t->type == UNSET && ((tun_setup->addr == ADDR_UNSET) &&
                (t->mode_mask & tun_setup->mode_mask))) ||
                (tun_setup->addr == c->addr)) {
                        set_type(c, tun_setup->type, tun_setup->mode_mask,
                                 tun_setup->config, tun_setup->tuner_callback);
-       }
+       } else
+               tuner_dbg("set addr discarded for type %i, mask %x. "
+                         "Asked to change tuner at addr 0x%02x, with mask %x\n",
+                         t->type, t->mode_mask,
+                         tun_setup->addr, tun_setup->mode_mask);
 }
 
 static inline int check_mode(struct tuner *t, char *cmd)
index cc3db7d79a0d195adc386205621f617ecbb57ac4..9e9003cffc7f20e8d551082b1eceea18b4dd3153 100644 (file)
@@ -432,7 +432,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
 
        type &= type_mask;
 
-       if (!type & SCODE)
+       if (!(type & SCODE))
                type_mask = ~0;
 
        /* Seek for exact match */
index b1e9592acb907bb06ca59d82e8fa6cafcf5384fc..845be1864f685a01fad3a225bc9826ab09d61985 100644 (file)
@@ -888,7 +888,7 @@ static int vivi_open(struct inode *inode, struct file *file)
 {
        int minor = iminor(inode);
        struct vivi_dev *dev;
-       struct vivi_fh *fh;
+       struct vivi_fh *fh = NULL;
        int i;
        int retval = 0;
 
index 4edc120a6359490a816eca96f30dbbc3a5eda624..633cbba072f024f013a17f42cc8b3181c63ef8a4 100644 (file)
@@ -132,8 +132,9 @@ static struct ds1wm_platform_data ds1wm_pdata = {
        .disable   = ds1wm_disable,
 };
 
-static int ds1wm_device_add(struct device *pasic3_dev, int bus_shift)
+static int ds1wm_device_add(struct platform_device *pasic3_pdev, int bus_shift)
 {
+       struct device *pasic3_dev = &pasic3_pdev->dev;
        struct pasic3_data *asic = pasic3_dev->driver_data;
        struct platform_device *pdev;
        int ret;
@@ -144,8 +145,8 @@ static int ds1wm_device_add(struct device *pasic3_dev, int bus_shift)
                return -ENOMEM;
        }
 
-       ret = platform_device_add_resources(pdev, pdev->resource,
-                                               pdev->num_resources);
+       ret = platform_device_add_resources(pdev, pasic3_pdev->resource,
+                                               pasic3_pdev->num_resources);
        if (ret < 0) {
                dev_dbg(pasic3_dev, "failed to add DS1WM resources\n");
                goto exit_pdev_put;
@@ -207,7 +208,7 @@ static int __init pasic3_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
-       ret = ds1wm_device_add(dev, asic->bus_shift);
+       ret = ds1wm_device_add(pdev, asic->bus_shift);
        if (ret < 0)
                dev_warn(dev, "failed to register DS1WM\n");
 
index fafb57fed761c8f1e6fa5c91f136c139593e0211..0736cff9d97a2c7499b4c91eaf30beac046ad9b6 100644 (file)
@@ -31,7 +31,6 @@
 static LIST_HEAD(container_list);
 static DEFINE_MUTEX(container_list_lock);
 static struct class enclosure_class;
-static struct class enclosure_component_class;
 
 /**
  * enclosure_find - find an enclosure given a device
@@ -166,6 +165,40 @@ void enclosure_unregister(struct enclosure_device *edev)
 }
 EXPORT_SYMBOL_GPL(enclosure_unregister);
 
+#define ENCLOSURE_NAME_SIZE    64
+
+static void enclosure_link_name(struct enclosure_component *cdev, char *name)
+{
+       strcpy(name, "enclosure_device:");
+       strcat(name, cdev->cdev.bus_id);
+}
+
+static void enclosure_remove_links(struct enclosure_component *cdev)
+{
+       char name[ENCLOSURE_NAME_SIZE];
+
+       enclosure_link_name(cdev, name);
+       sysfs_remove_link(&cdev->dev->kobj, name);
+       sysfs_remove_link(&cdev->cdev.kobj, "device");
+}
+
+static int enclosure_add_links(struct enclosure_component *cdev)
+{
+       int error;
+       char name[ENCLOSURE_NAME_SIZE];
+
+       error = sysfs_create_link(&cdev->cdev.kobj, &cdev->dev->kobj, "device");
+       if (error)
+               return error;
+
+       enclosure_link_name(cdev, name);
+       error = sysfs_create_link(&cdev->dev->kobj, &cdev->cdev.kobj, name);
+       if (error)
+               sysfs_remove_link(&cdev->cdev.kobj, "device");
+
+       return error;
+}
+
 static void enclosure_release(struct device *cdev)
 {
        struct enclosure_device *edev = to_enclosure_device(cdev);
@@ -178,10 +211,15 @@ static void enclosure_component_release(struct device *dev)
 {
        struct enclosure_component *cdev = to_enclosure_component(dev);
 
-       put_device(cdev->dev);
+       if (cdev->dev) {
+               enclosure_remove_links(cdev);
+               put_device(cdev->dev);
+       }
        put_device(dev->parent);
 }
 
+static struct attribute_group *enclosure_groups[];
+
 /**
  * enclosure_component_register - add a particular component to an enclosure
  * @edev:      the enclosure to add the component
@@ -217,12 +255,14 @@ enclosure_component_register(struct enclosure_device *edev,
        ecomp->number = number;
        cdev = &ecomp->cdev;
        cdev->parent = get_device(&edev->edev);
-       cdev->class = &enclosure_component_class;
        if (name)
                snprintf(cdev->bus_id, BUS_ID_SIZE, "%s", name);
        else
                snprintf(cdev->bus_id, BUS_ID_SIZE, "%u", number);
 
+       cdev->release = enclosure_component_release;
+       cdev->groups = enclosure_groups;
+
        err = device_register(cdev);
        if (err)
                ERR_PTR(err);
@@ -255,10 +295,12 @@ int enclosure_add_device(struct enclosure_device *edev, int component,
 
        cdev = &edev->component[component];
 
-       device_del(&cdev->cdev);
+       if (cdev->dev)
+               enclosure_remove_links(cdev);
+
        put_device(cdev->dev);
        cdev->dev = get_device(dev);
-       return device_add(&cdev->cdev);
+       return enclosure_add_links(cdev);
 }
 EXPORT_SYMBOL_GPL(enclosure_add_device);
 
@@ -442,24 +484,32 @@ static ssize_t get_component_type(struct device *cdev,
 }
 
 
-static struct device_attribute enclosure_component_attrs[] = {
-       __ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault,
-              set_component_fault),
-       __ATTR(status, S_IRUGO | S_IWUSR, get_component_status,
-              set_component_status),
-       __ATTR(active, S_IRUGO | S_IWUSR, get_component_active,
-              set_component_active),
-       __ATTR(locate, S_IRUGO | S_IWUSR, get_component_locate,
-              set_component_locate),
-       __ATTR(type, S_IRUGO, get_component_type, NULL),
-       __ATTR_NULL
+static DEVICE_ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault,
+                   set_component_fault);
+static DEVICE_ATTR(status, S_IRUGO | S_IWUSR, get_component_status,
+                  set_component_status);
+static DEVICE_ATTR(active, S_IRUGO | S_IWUSR, get_component_active,
+                  set_component_active);
+static DEVICE_ATTR(locate, S_IRUGO | S_IWUSR, get_component_locate,
+                  set_component_locate);
+static DEVICE_ATTR(type, S_IRUGO, get_component_type, NULL);
+
+static struct attribute *enclosure_component_attrs[] = {
+       &dev_attr_fault.attr,
+       &dev_attr_status.attr,
+       &dev_attr_active.attr,
+       &dev_attr_locate.attr,
+       &dev_attr_type.attr,
+       NULL
 };
 
-static struct class enclosure_component_class =  {
-       .name                   = "enclosure_component",
-       .owner                  = THIS_MODULE,
-       .dev_attrs      = enclosure_component_attrs,
-       .dev_release            = enclosure_component_release,
+static struct attribute_group enclosure_group = {
+       .attrs = enclosure_component_attrs,
+};
+
+static struct attribute_group *enclosure_groups[] = {
+       &enclosure_group,
+       NULL
 };
 
 static int __init enclosure_init(void)
@@ -469,20 +519,12 @@ static int __init enclosure_init(void)
        err = class_register(&enclosure_class);
        if (err)
                return err;
-       err = class_register(&enclosure_component_class);
-       if (err)
-               goto err_out;
 
        return 0;
- err_out:
-       class_unregister(&enclosure_class);
-
-       return err;
 }
 
 static void __exit enclosure_exit(void)
 {
-       class_unregister(&enclosure_component_class);
        class_unregister(&enclosure_class);
 }
 
index 95244a7e73531ad0fdf2d451d907edabcfbf5a4c..626ac083f4e09c294c4d465dd3c85e886082867d 100644 (file)
@@ -213,9 +213,10 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema
        void __iomem *base = host->base;
        char *ptr = buffer;
        u32 status;
+       int host_remain = host->size;
 
        do {
-               int count = host->size - (readl(base + MMCIFIFOCNT) << 2);
+               int count = host_remain - (readl(base + MMCIFIFOCNT) << 2);
 
                if (count > remain)
                        count = remain;
@@ -227,6 +228,7 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema
 
                ptr += count;
                remain -= count;
+               host_remain -= count;
 
                if (remain == 0)
                        break;
index e8503341e3b147f5bc242e640bb1596e261695e9..eed06d068fd12f36f64c11a37ea0e3ea7c611d32 100644 (file)
@@ -158,6 +158,12 @@ config MTD_OF_PARTS
          the partition map from the children of the flash node,
          as described in Documentation/powerpc/booting-without-of.txt.
 
+config MTD_AR7_PARTS
+       tristate "TI AR7 partitioning support"
+       depends on MTD_PARTITIONS
+       ---help---
+         TI AR7 partitioning support
+
 comment "User Modules And Translation Layers"
 
 config MTD_CHAR
index 538e33d11d46ce026265bc5c504b6c08222ee198..4b77335715f0cb64bb702178ced7a547e6aaabea 100644 (file)
@@ -11,6 +11,7 @@ obj-$(CONFIG_MTD_CONCAT)      += mtdconcat.o
 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
 obj-$(CONFIG_MTD_AFS_PARTS)    += afs.o
+obj-$(CONFIG_MTD_AR7_PARTS)    += ar7part.o
 obj-$(CONFIG_MTD_OF_PARTS)      += ofpart.o
 
 # 'Users' - code which presents functionality to userspace.
diff --git a/drivers/mtd/ar7part.c b/drivers/mtd/ar7part.c
new file mode 100644 (file)
index 0000000..ecf170b
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright Â© 2007 Eugene Konev <ejka@openwrt.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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * TI AR7 flash partition table.
+ * Based on ar7 map by Felix Fietkau <nbd@openwrt.org>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/bootmem.h>
+#include <linux/magic.h>
+
+#define AR7_PARTS      4
+#define ROOT_OFFSET    0xe0000
+
+#define LOADER_MAGIC1  le32_to_cpu(0xfeedfa42)
+#define LOADER_MAGIC2  le32_to_cpu(0xfeed1281)
+
+#ifndef SQUASHFS_MAGIC
+#define SQUASHFS_MAGIC 0x73717368
+#endif
+
+struct ar7_bin_rec {
+       unsigned int checksum;
+       unsigned int length;
+       unsigned int address;
+};
+
+static struct mtd_partition ar7_parts[AR7_PARTS];
+
+static int create_mtd_partitions(struct mtd_info *master,
+                                struct mtd_partition **pparts,
+                                unsigned long origin)
+{
+       struct ar7_bin_rec header;
+       unsigned int offset;
+       size_t len;
+       unsigned int pre_size = master->erasesize, post_size = 0;
+       unsigned int root_offset = ROOT_OFFSET;
+
+       int retries = 10;
+
+       ar7_parts[0].name = "loader";
+       ar7_parts[0].offset = 0;
+       ar7_parts[0].size = master->erasesize;
+       ar7_parts[0].mask_flags = MTD_WRITEABLE;
+
+       ar7_parts[1].name = "config";
+       ar7_parts[1].offset = 0;
+       ar7_parts[1].size = master->erasesize;
+       ar7_parts[1].mask_flags = 0;
+
+       do { /* Try 10 blocks starting from master->erasesize */
+               offset = pre_size;
+               master->read(master, offset,
+                            sizeof(header), &len, (uint8_t *)&header);
+               if (!strncmp((char *)&header, "TIENV0.8", 8))
+                       ar7_parts[1].offset = pre_size;
+               if (header.checksum == LOADER_MAGIC1)
+                       break;
+               if (header.checksum == LOADER_MAGIC2)
+                       break;
+               pre_size += master->erasesize;
+       } while (retries--);
+
+       pre_size = offset;
+
+       if (!ar7_parts[1].offset) {
+               ar7_parts[1].offset = master->size - master->erasesize;
+               post_size = master->erasesize;
+       }
+
+       switch (header.checksum) {
+       case LOADER_MAGIC1:
+               while (header.length) {
+                       offset += sizeof(header) + header.length;
+                       master->read(master, offset, sizeof(header),
+                                    &len, (uint8_t *)&header);
+               }
+               root_offset = offset + sizeof(header) + 4;
+               break;
+       case LOADER_MAGIC2:
+               while (header.length) {
+                       offset += sizeof(header) + header.length;
+                       master->read(master, offset, sizeof(header),
+                                    &len, (uint8_t *)&header);
+               }
+               root_offset = offset + sizeof(header) + 4 + 0xff;
+               root_offset &= ~(uint32_t)0xff;
+               break;
+       default:
+               printk(KERN_WARNING "Unknown magic: %08x\n", header.checksum);
+               break;
+       }
+
+       master->read(master, root_offset,
+               sizeof(header), &len, (u8 *)&header);
+       if (header.checksum != SQUASHFS_MAGIC) {
+               root_offset += master->erasesize - 1;
+               root_offset &= ~(master->erasesize - 1);
+       }
+
+       ar7_parts[2].name = "linux";
+       ar7_parts[2].offset = pre_size;
+       ar7_parts[2].size = master->size - pre_size - post_size;
+       ar7_parts[2].mask_flags = 0;
+
+       ar7_parts[3].name = "rootfs";
+       ar7_parts[3].offset = root_offset;
+       ar7_parts[3].size = master->size - root_offset - post_size;
+       ar7_parts[3].mask_flags = 0;
+
+       *pparts = ar7_parts;
+       return AR7_PARTS;
+}
+
+static struct mtd_part_parser ar7_parser = {
+       .owner = THIS_MODULE,
+       .parse_fn = create_mtd_partitions,
+       .name = "ar7part",
+};
+
+static int __init ar7_parser_init(void)
+{
+       return register_mtd_parser(&ar7_parser);
+}
+
+module_init(ar7_parser_init);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR( "Felix Fietkau <nbd@openwrt.org>, "
+               "Eugene Konev <ejka@openwrt.org>");
+MODULE_DESCRIPTION("MTD partitioning for TI AR7");
index 0080452531d6a35df3a651e94d46d0f5ac5df003..e812df607a5c9aef596e96c4800881cb2df15967 100644 (file)
@@ -384,7 +384,7 @@ read_pri_intelext(struct map_info *map, __u16 adr)
                        if (extp_size > 4096) {
                                printk(KERN_ERR
                                        "%s: cfi_pri_intelext is too fat\n",
-                                       __FUNCTION__);
+                                       __func__);
                                return NULL;
                        }
                        goto again;
@@ -619,6 +619,9 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
                                  sizeof(struct cfi_intelext_blockinfo);
                }
 
+               if (!numparts)
+                       numparts = 1;
+
                /* Programming Region info */
                if (extp->MinorVersion >= '4') {
                        struct cfi_intelext_programming_regioninfo *prinfo;
@@ -641,7 +644,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
                if ((1 << partshift) < mtd->erasesize) {
                        printk( KERN_ERR
                                "%s: bad number of hw partitions (%d)\n",
-                               __FUNCTION__, numparts);
+                               __func__, numparts);
                        return -EINVAL;
                }
 
@@ -1071,10 +1074,10 @@ static int __xipram xip_wait_for_operation(
                        chip->state = newstate;
                        map_write(map, CMD(0xff), adr);
                        (void) map_read(map, adr);
-                       asm volatile (".rep 8; nop; .endr");
+                       xip_iprefetch();
                        local_irq_enable();
                        spin_unlock(chip->mutex);
-                       asm volatile (".rep 8; nop; .endr");
+                       xip_iprefetch();
                        cond_resched();
 
                        /*
@@ -2013,7 +2016,7 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
 
 #ifdef DEBUG_LOCK_BITS
        printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
-              __FUNCTION__, ofs, len);
+              __func__, ofs, len);
        cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
                ofs, len, NULL);
 #endif
@@ -2023,7 +2026,7 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
 
 #ifdef DEBUG_LOCK_BITS
        printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
-              __FUNCTION__, ret);
+              __func__, ret);
        cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
                ofs, len, NULL);
 #endif
@@ -2037,7 +2040,7 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
 
 #ifdef DEBUG_LOCK_BITS
        printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
-              __FUNCTION__, ofs, len);
+              __func__, ofs, len);
        cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
                ofs, len, NULL);
 #endif
@@ -2047,7 +2050,7 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
 
 #ifdef DEBUG_LOCK_BITS
        printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
-              __FUNCTION__, ret);
+              __func__, ret);
        cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
                ofs, len, NULL);
 #endif
index 458d477614d680c0fb718e20e16ee6692fc71a8a..f7fcc6389533c3221dac34ab72878605d4f94e0b 100644 (file)
@@ -220,6 +220,28 @@ static void fixup_use_atmel_lock(struct mtd_info *mtd, void *param)
        mtd->flags |= MTD_POWERUP_LOCK;
 }
 
+static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param)
+{
+       struct map_info *map = mtd->priv;
+       struct cfi_private *cfi = map->fldrv_priv;
+
+       if ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0x003f) {
+               cfi->cfiq->EraseRegionInfo[0] |= 0x0040;
+               pr_warning("%s: Bad S29GL064N CFI data, adjust from 64 to 128 sectors\n", mtd->name);
+       }
+}
+
+static void fixup_s29gl032n_sectors(struct mtd_info *mtd, void *param)
+{
+       struct map_info *map = mtd->priv;
+       struct cfi_private *cfi = map->fldrv_priv;
+
+       if ((cfi->cfiq->EraseRegionInfo[1] & 0xffff) == 0x007e) {
+               cfi->cfiq->EraseRegionInfo[1] &= ~0x0040;
+               pr_warning("%s: Bad S29GL032N CFI data, adjust from 127 to 63 sectors\n", mtd->name);
+       }
+}
+
 static struct cfi_fixup cfi_fixup_table[] = {
        { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
 #ifdef AMD_BOOTLOC_BUG
@@ -231,6 +253,10 @@ static struct cfi_fixup cfi_fixup_table[] = {
        { CFI_MFR_AMD, 0x0056, fixup_use_secsi, NULL, },
        { CFI_MFR_AMD, 0x005C, fixup_use_secsi, NULL, },
        { CFI_MFR_AMD, 0x005F, fixup_use_secsi, NULL, },
+       { CFI_MFR_AMD, 0x0c01, fixup_s29gl064n_sectors, NULL, },
+       { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, },
+       { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, },
+       { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, },
 #if !FORCE_WORD_WRITE
        { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
 #endif
@@ -723,10 +749,10 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
                        chip->erase_suspended = 1;
                        map_write(map, CMD(0xf0), adr);
                        (void) map_read(map, adr);
-                       asm volatile (".rep 8; nop; .endr");
+                       xip_iprefetch();
                        local_irq_enable();
                        spin_unlock(chip->mutex);
-                       asm volatile (".rep 8; nop; .endr");
+                       xip_iprefetch();
                        cond_resched();
 
                        /*
index 492e2ab27420ff76bcc532c961452eeb75a59e32..1b720cc571f315dfbb1ec2a7faed160835bbb00b 100644 (file)
@@ -445,7 +445,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
  retry:
 
 #ifdef DEBUG_CFI_FEATURES
-       printk("%s: chip->state[%d]\n", __FUNCTION__, chip->state);
+       printk("%s: chip->state[%d]\n", __func__, chip->state);
 #endif
        spin_lock_bh(chip->mutex);
 
@@ -463,7 +463,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
                map_write(map, CMD(0x70), cmd_adr);
                 chip->state = FL_STATUS;
 #ifdef DEBUG_CFI_FEATURES
-        printk("%s: 1 status[%x]\n", __FUNCTION__, map_read(map, cmd_adr));
+       printk("%s: 1 status[%x]\n", __func__, map_read(map, cmd_adr));
 #endif
 
        case FL_STATUS:
@@ -591,7 +591,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
         /* check for errors: 'lock bit', 'VPP', 'dead cell'/'unerased cell' or 'incorrect cmd' -- saw */
         if (map_word_bitsset(map, status, CMD(0x3a))) {
 #ifdef DEBUG_CFI_FEATURES
-               printk("%s: 2 status[%lx]\n", __FUNCTION__, status.x[0]);
+               printk("%s: 2 status[%lx]\n", __func__, status.x[0]);
 #endif
                /* clear status */
                map_write(map, CMD(0x50), cmd_adr);
@@ -625,9 +625,9 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to,
        ofs = to  - (chipnum << cfi->chipshift);
 
 #ifdef DEBUG_CFI_FEATURES
-        printk("%s: map_bankwidth(map)[%x]\n", __FUNCTION__, map_bankwidth(map));
-        printk("%s: chipnum[%x] wbufsize[%x]\n", __FUNCTION__, chipnum, wbufsize);
-        printk("%s: ofs[%x] len[%x]\n", __FUNCTION__, ofs, len);
+       printk("%s: map_bankwidth(map)[%x]\n", __func__, map_bankwidth(map));
+       printk("%s: chipnum[%x] wbufsize[%x]\n", __func__, chipnum, wbufsize);
+       printk("%s: ofs[%x] len[%x]\n", __func__, ofs, len);
 #endif
 
         /* Write buffer is worth it only if more than one word to write... */
@@ -893,7 +893,8 @@ retry:
        return ret;
 }
 
-int cfi_staa_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
+static int cfi_staa_erase_varsize(struct mtd_info *mtd,
+                                 struct erase_info *instr)
 {      struct map_info *map = mtd->priv;
        struct cfi_private *cfi = map->fldrv_priv;
        unsigned long adr, len;
index f651b6ef1c5d6c44805b066fab343eb965f952d0..a4463a91ce31877881beb14427bf8bc6b6f5fd5a 100644 (file)
@@ -39,7 +39,7 @@ struct mtd_info *cfi_probe(struct map_info *map);
 #define xip_allowed(base, map) \
 do { \
        (void) map_read(map, base); \
-       asm volatile (".rep 8; nop; .endr"); \
+       xip_iprefetch(); \
        local_irq_enable(); \
 } while (0)
 
@@ -232,6 +232,11 @@ static int __xipram cfi_chip_setup(struct map_info *map,
        cfi->mfr = cfi_read_query16(map, base);
        cfi->id = cfi_read_query16(map, base + ofs_factor);
 
+       /* Get AMD/Spansion extended JEDEC ID */
+       if (cfi->mfr == CFI_MFR_AMD && (cfi->id & 0xff) == 0x7e)
+               cfi->id = cfi_read_query(map, base + 0xe * ofs_factor) << 8 |
+                         cfi_read_query(map, base + 0xf * ofs_factor);
+
        /* Put it back into Read Mode */
        cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
        /* ... even if it's an Intel chip */
index 2e51496c248e0b718273ec3715d5c16b2c689ff8..72e0022a47bf50e360686068b66e6d52dbe895a6 100644 (file)
@@ -65,7 +65,7 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n
 
 #ifdef CONFIG_MTD_XIP
        (void) map_read(map, base);
-       asm volatile (".rep 8; nop; .endr");
+       xip_iprefetch();
        local_irq_enable();
 #endif
 
index 4be51a86a85cbbe711eaca3973ab9716692735ae..aa07575eb28834adfd09683a95ed87e1a5e6ccc6 100644 (file)
 #define M29F800AB      0x0058
 #define M29W800DT      0x00D7
 #define M29W800DB      0x005B
+#define M29W400DT      0x00EE
+#define M29W400DB      0x00EF
 #define M29W160DT      0x22C4
 #define M29W160DB      0x2249
 #define M29W040B       0x00E3
 #define SST49LF030A    0x001C
 #define SST49LF040A    0x0051
 #define SST49LF080A    0x005B
+#define SST36VF3203    0x7354
 
 /* Toshiba */
 #define TC58FVT160     0x00C2
@@ -1113,7 +1116,7 @@ static const struct amd_flash_info jedec_table[] = {
                .regions        = {
                        ERASEINFO(0x10000,8),
                }
-        }, {
+       }, {
                .mfr_id         = MANUFACTURER_MACRONIX,
                .dev_id         = MX29F016,
                .name           = "Macronix MX29F016",
@@ -1125,7 +1128,7 @@ static const struct amd_flash_info jedec_table[] = {
                .regions        = {
                        ERASEINFO(0x10000,32),
                }
-        }, {
+       }, {
                .mfr_id         = MANUFACTURER_MACRONIX,
                .dev_id         = MX29F004T,
                .name           = "Macronix MX29F004T",
@@ -1140,7 +1143,7 @@ static const struct amd_flash_info jedec_table[] = {
                        ERASEINFO(0x02000,2),
                        ERASEINFO(0x04000,1),
                }
-        }, {
+       }, {
                .mfr_id         = MANUFACTURER_MACRONIX,
                .dev_id         = MX29F004B,
                .name           = "Macronix MX29F004B",
@@ -1218,7 +1221,7 @@ static const struct amd_flash_info jedec_table[] = {
                .regions        = {
                        ERASEINFO(0x40000,16),
                }
-        }, {
+       }, {
                .mfr_id         = MANUFACTURER_SST,
                .dev_id         = SST39LF512,
                .name           = "SST 39LF512",
@@ -1230,7 +1233,7 @@ static const struct amd_flash_info jedec_table[] = {
                .regions        = {
                        ERASEINFO(0x01000,16),
                }
-        }, {
+       }, {
                .mfr_id         = MANUFACTURER_SST,
                .dev_id         = SST39LF010,
                .name           = "SST 39LF010",
@@ -1242,7 +1245,7 @@ static const struct amd_flash_info jedec_table[] = {
                .regions        = {
                        ERASEINFO(0x01000,32),
                }
-        }, {
+       }, {
                .mfr_id         = MANUFACTURER_SST,
                .dev_id         = SST29EE020,
                .name           = "SST 29EE020",
@@ -1276,7 +1279,7 @@ static const struct amd_flash_info jedec_table[] = {
                .regions        = {
                        ERASEINFO(0x01000,64),
                }
-        }, {
+       }, {
                .mfr_id         = MANUFACTURER_SST,
                .dev_id         = SST39LF040,
                .name           = "SST 39LF040",
@@ -1288,7 +1291,7 @@ static const struct amd_flash_info jedec_table[] = {
                .regions        = {
                        ERASEINFO(0x01000,128),
                }
-        }, {
+       }, {
                .mfr_id         = MANUFACTURER_SST,
                .dev_id         = SST39SF010A,
                .name           = "SST 39SF010A",
@@ -1300,7 +1303,7 @@ static const struct amd_flash_info jedec_table[] = {
                .regions        = {
                        ERASEINFO(0x01000,32),
                }
-        }, {
+       }, {
                .mfr_id         = MANUFACTURER_SST,
                .dev_id         = SST39SF020A,
                .name           = "SST 39SF020A",
@@ -1411,6 +1414,18 @@ static const struct amd_flash_info jedec_table[] = {
                        ERASEINFO(0x1000,256),
                        ERASEINFO(0x1000,256)
                }
+       }, {
+               .mfr_id         = MANUFACTURER_SST,
+               .dev_id         = SST36VF3203,
+               .name           = "SST 36VF3203",
+               .devtypes       = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
+               .uaddr          = MTD_UADDR_0x0AAA_0x0555,
+               .dev_size       = SIZE_4MiB,
+               .cmd_set        = P_ID_AMD_STD,
+               .nr_regions     = 1,
+               .regions        = {
+                       ERASEINFO(0x10000,64),
+               }
        }, {
                .mfr_id         = MANUFACTURER_ST,
                .dev_id         = M29F800AB,
@@ -1426,7 +1441,7 @@ static const struct amd_flash_info jedec_table[] = {
                        ERASEINFO(0x08000,1),
                        ERASEINFO(0x10000,15),
                }
-       }, {
+       }, {
                .mfr_id         = MANUFACTURER_ST,      /* FIXME - CFI device? */
                .dev_id         = M29W800DT,
                .name           = "ST M29W800DT",
@@ -1456,6 +1471,36 @@ static const struct amd_flash_info jedec_table[] = {
                        ERASEINFO(0x08000,1),
                        ERASEINFO(0x10000,15)
                }
+       },  {
+               .mfr_id         = MANUFACTURER_ST,
+               .dev_id         = M29W400DT,
+               .name           = "ST M29W400DT",
+               .devtypes       = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
+               .uaddr          = MTD_UADDR_0x0AAA_0x0555,
+               .dev_size       = SIZE_512KiB,
+               .cmd_set        = P_ID_AMD_STD,
+               .nr_regions     = 4,
+               .regions        = {
+                       ERASEINFO(0x04000,7),
+                       ERASEINFO(0x02000,1),
+                       ERASEINFO(0x08000,2),
+                       ERASEINFO(0x10000,1)
+               }
+       }, {
+               .mfr_id         = MANUFACTURER_ST,
+               .dev_id         = M29W400DB,
+               .name           = "ST M29W400DB",
+               .devtypes       = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
+               .uaddr          = MTD_UADDR_0x0AAA_0x0555,
+               .dev_size       = SIZE_512KiB,
+               .cmd_set        = P_ID_AMD_STD,
+               .nr_regions     = 4,
+               .regions        = {
+                       ERASEINFO(0x04000,1),
+                       ERASEINFO(0x02000,2),
+                       ERASEINFO(0x08000,1),
+                       ERASEINFO(0x10000,7)
+               }
        }, {
                .mfr_id         = MANUFACTURER_ST,      /* FIXME - CFI device? */
                .dev_id         = M29W160DT,
@@ -1486,7 +1531,7 @@ static const struct amd_flash_info jedec_table[] = {
                        ERASEINFO(0x08000,1),
                        ERASEINFO(0x10000,31)
                }
-        }, {
+       }, {
                .mfr_id         = MANUFACTURER_ST,
                .dev_id         = M29W040B,
                .name           = "ST M29W040B",
@@ -1498,7 +1543,7 @@ static const struct amd_flash_info jedec_table[] = {
                .regions        = {
                        ERASEINFO(0x10000,8),
                }
-        }, {
+       }, {
                .mfr_id         = MANUFACTURER_ST,
                .dev_id         = M50FW040,
                .name           = "ST M50FW040",
@@ -1510,7 +1555,7 @@ static const struct amd_flash_info jedec_table[] = {
                .regions        = {
                        ERASEINFO(0x10000,8),
                }
-        }, {
+       }, {
                .mfr_id         = MANUFACTURER_ST,
                .dev_id         = M50FW080,
                .name           = "ST M50FW080",
@@ -1522,7 +1567,7 @@ static const struct amd_flash_info jedec_table[] = {
                .regions        = {
                        ERASEINFO(0x10000,16),
                }
-        }, {
+       }, {
                .mfr_id         = MANUFACTURER_ST,
                .dev_id         = M50FW016,
                .name           = "ST M50FW016",
index b44292abd9f7bd68c94228ac11200b3549dc1711..e472a0e9de9d913228cfa47bc8351b9f360c9e12 100644 (file)
@@ -119,7 +119,8 @@ static struct mtd_partition * newpart(char *s,
                char *p;
 
                name = ++s;
-               if ((p = strchr(name, delim)) == 0)
+               p = strchr(name, delim);
+               if (!p)
                {
                        printk(KERN_ERR ERRP "no closing %c found in partition name\n", delim);
                        return NULL;
@@ -159,9 +160,10 @@ static struct mtd_partition * newpart(char *s,
                        return NULL;
                }
                /* more partitions follow, parse them */
-               if ((parts = newpart(s + 1, &s, num_parts,
-                                    this_part + 1, &extra_mem, extra_mem_size)) == 0)
-                 return NULL;
+               parts = newpart(s + 1, &s, num_parts, this_part + 1,
+                               &extra_mem, extra_mem_size);
+               if (!parts)
+                       return NULL;
        }
        else
        {       /* this is the last partition: allocate space for all */
@@ -308,9 +310,6 @@ static int parse_cmdline_partitions(struct mtd_info *master,
        struct cmdline_mtd_partition *part;
        char *mtd_id = master->name;
 
-       if(!cmdline)
-               return -EINVAL;
-
        /* parse command line */
        if (!cmdline_parsed)
                mtdpart_setup_real(cmdline);
@@ -341,7 +340,7 @@ static int parse_cmdline_partitions(struct mtd_info *master,
                        return part->num_parts;
                }
        }
-       return -EINVAL;
+       return 0;
 }
 
 
index 811d56fd890f6da79135d854ae52fc8d581d167f..35ed1103dbb22096c183eb0a903072ec8ef73e1a 100644 (file)
@@ -77,6 +77,13 @@ config MTD_M25P80
          if you want to specify device partitioning or to use a device which
          doesn't support the JEDEC ID instruction.
 
+config M25PXX_USE_FAST_READ
+       bool "Use FAST_READ OPCode allowing SPI CLK <= 50MHz"
+       depends on MTD_M25P80
+       default y
+       help
+         This option enables FAST_READ access supported by ST M25Pxx.
+
 config MTD_SLRAM
        tristate "Uncached system RAM"
        help
index ad1880c67518eead88feb416b72a598fb86a9ba6..519d942e7940c6167672c2d53829530e3e7d9fcc 100644 (file)
@@ -305,7 +305,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
        }
        list_add(&dev->list, &blkmtd_device_list);
        INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index,
-                       dev->mtd.name + strlen("blkmtd: "),
+                       dev->mtd.name + strlen("block2mtd: "),
                        dev->mtd.erasesize >> 10, dev->mtd.erasesize);
        return dev;
 
@@ -366,9 +366,9 @@ static inline void kill_final_newline(char *str)
 }
 
 
-#define parse_err(fmt, args...) do {           \
-       ERROR("block2mtd: " fmt "\n", ## args); \
-       return 0;                               \
+#define parse_err(fmt, args...) do {   \
+       ERROR(fmt, ## args);            \
+       return 0;                       \
 } while (0)
 
 #ifndef MODULE
@@ -473,7 +473,7 @@ static void __devexit block2mtd_exit(void)
                block2mtd_sync(&dev->mtd);
                del_mtd_device(&dev->mtd);
                INFO("mtd%d: [%s] removed", dev->mtd.index,
-                               dev->mtd.name + strlen("blkmtd: "));
+                               dev->mtd.name + strlen("block2mtd: "));
                list_del(&dev->list);
                block2mtd_free_device(dev);
        }
index 99fd210feaece71fa8f39658e3fa16d4bdebdcfb..1d324e5c412d547834f05eab936e181f92085c67 100644 (file)
@@ -275,7 +275,7 @@ static __u8 read8 (__u32 offset)
 {
    volatile __u8 *data = (__u8 *) (FLASH_OFFSET + offset);
 #ifdef LART_DEBUG
-   printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.2x\n",__FUNCTION__,offset,*data);
+   printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.2x\n", __func__, offset, *data);
 #endif
    return (*data);
 }
@@ -284,7 +284,7 @@ static __u32 read32 (__u32 offset)
 {
    volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset);
 #ifdef LART_DEBUG
-   printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.8x\n",__FUNCTION__,offset,*data);
+   printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.8x\n", __func__, offset, *data);
 #endif
    return (*data);
 }
@@ -294,7 +294,7 @@ static void write32 (__u32 x,__u32 offset)
    volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset);
    *data = x;
 #ifdef LART_DEBUG
-   printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n",__FUNCTION__,offset,*data);
+   printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n", __func__, offset, *data);
 #endif
 }
 
@@ -337,7 +337,7 @@ static inline int erase_block (__u32 offset)
    __u32 status;
 
 #ifdef LART_DEBUG
-   printk (KERN_DEBUG "%s(): 0x%.8x\n",__FUNCTION__,offset);
+   printk (KERN_DEBUG "%s(): 0x%.8x\n", __func__, offset);
 #endif
 
    /* erase and confirm */
@@ -371,7 +371,7 @@ static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
    int i,first;
 
 #ifdef LART_DEBUG
-   printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n",__FUNCTION__,instr->addr,instr->len);
+   printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n", __func__, instr->addr, instr->len);
 #endif
 
    /* sanity checks */
@@ -442,7 +442,7 @@ static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
 static int flash_read (struct mtd_info *mtd,loff_t from,size_t len,size_t *retlen,u_char *buf)
 {
 #ifdef LART_DEBUG
-   printk (KERN_DEBUG "%s(from = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) from,len);
+   printk (KERN_DEBUG "%s(from = 0x%.8x, len = %d)\n", __func__, (__u32)from, len);
 #endif
 
    /* sanity checks */
@@ -488,7 +488,7 @@ static inline int write_dword (__u32 offset,__u32 x)
    __u32 status;
 
 #ifdef LART_DEBUG
-   printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n",__FUNCTION__,offset,x);
+   printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n", __func__, offset, x);
 #endif
 
    /* setup writing */
@@ -524,7 +524,7 @@ static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen
    int i,n;
 
 #ifdef LART_DEBUG
-   printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) to,len);
+   printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n", __func__, (__u32)to, len);
 #endif
 
    *retlen = 0;
index 98df5bcc02f3b42ea6f3aa5417e3437bd32e9d21..25efd331ef28ce35b4a48f0463f594e221d94aa7 100644 (file)
@@ -33,7 +33,7 @@
 /* Flash opcodes. */
 #define        OPCODE_WREN             0x06    /* Write enable */
 #define        OPCODE_RDSR             0x05    /* Read status register */
-#define        OPCODE_READ             0x03    /* Read data bytes (low frequency) */
+#define        OPCODE_NORM_READ        0x03    /* Read data bytes (low frequency) */
 #define        OPCODE_FAST_READ        0x0b    /* Read data bytes (high frequency) */
 #define        OPCODE_PP               0x02    /* Page program (up to 256 bytes) */
 #define        OPCODE_BE_4K            0x20    /* Erase 4KiB block */
 
 /* Define max times to check status register before we give up. */
 #define        MAX_READY_WAIT_COUNT    100000
+#define        CMD_SIZE                4
 
+#ifdef CONFIG_M25PXX_USE_FAST_READ
+#define OPCODE_READ    OPCODE_FAST_READ
+#define FAST_READ_DUMMY_BYTE 1
+#else
+#define OPCODE_READ    OPCODE_NORM_READ
+#define FAST_READ_DUMMY_BYTE 0
+#endif
 
 #ifdef CONFIG_MTD_PARTITIONS
 #define        mtd_has_partitions()    (1)
@@ -68,7 +76,7 @@ struct m25p {
        struct mtd_info         mtd;
        unsigned                partitioned:1;
        u8                      erase_opcode;
-       u8                      command[4];
+       u8                      command[CMD_SIZE + FAST_READ_DUMMY_BYTE];
 };
 
 static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
@@ -151,7 +159,7 @@ static int wait_till_ready(struct m25p *flash)
 static int erase_sector(struct m25p *flash, u32 offset)
 {
        DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n",
-                       flash->spi->dev.bus_id, __FUNCTION__,
+                       flash->spi->dev.bus_id, __func__,
                        flash->mtd.erasesize / 1024, offset);
 
        /* Wait until finished previous write command. */
@@ -167,7 +175,7 @@ static int erase_sector(struct m25p *flash, u32 offset)
        flash->command[2] = offset >> 8;
        flash->command[3] = offset;
 
-       spi_write(flash->spi, flash->command, sizeof(flash->command));
+       spi_write(flash->spi, flash->command, CMD_SIZE);
 
        return 0;
 }
@@ -188,7 +196,7 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
        u32 addr,len;
 
        DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
-                       flash->spi->dev.bus_id, __FUNCTION__, "at",
+                       flash->spi->dev.bus_id, __func__, "at",
                        (u32)instr->addr, instr->len);
 
        /* sanity checks */
@@ -240,7 +248,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
        struct spi_message m;
 
        DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
-                       flash->spi->dev.bus_id, __FUNCTION__, "from",
+                       flash->spi->dev.bus_id, __func__, "from",
                        (u32)from, len);
 
        /* sanity checks */
@@ -253,8 +261,12 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
        spi_message_init(&m);
        memset(t, 0, (sizeof t));
 
+       /* NOTE:
+        * OPCODE_FAST_READ (if available) is faster.
+        * Should add 1 byte DUMMY_BYTE.
+        */
        t[0].tx_buf = flash->command;
-       t[0].len = sizeof(flash->command);
+       t[0].len = CMD_SIZE + FAST_READ_DUMMY_BYTE;
        spi_message_add_tail(&t[0], &m);
 
        t[1].rx_buf = buf;
@@ -287,7 +299,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
 
        spi_sync(flash->spi, &m);
 
-       *retlen = m.actual_length - sizeof(flash->command);
+       *retlen = m.actual_length - CMD_SIZE - FAST_READ_DUMMY_BYTE;
 
        mutex_unlock(&flash->lock);
 
@@ -308,7 +320,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
        struct spi_message m;
 
        DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
-                       flash->spi->dev.bus_id, __FUNCTION__, "to",
+                       flash->spi->dev.bus_id, __func__, "to",
                        (u32)to, len);
 
        if (retlen)
@@ -325,7 +337,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
        memset(t, 0, (sizeof t));
 
        t[0].tx_buf = flash->command;
-       t[0].len = sizeof(flash->command);
+       t[0].len = CMD_SIZE;
        spi_message_add_tail(&t[0], &m);
 
        t[1].tx_buf = buf;
@@ -354,7 +366,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
 
                spi_sync(flash->spi, &m);
 
-               *retlen = m.actual_length - sizeof(flash->command);
+               *retlen = m.actual_length - CMD_SIZE;
        } else {
                u32 i;
 
@@ -364,7 +376,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
                t[1].len = page_size;
                spi_sync(flash->spi, &m);
 
-               *retlen = m.actual_length - sizeof(flash->command);
+               *retlen = m.actual_length - CMD_SIZE;
 
                /* write everything in PAGESIZE chunks */
                for (i = page_size; i < len; i += page_size) {
@@ -387,8 +399,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
                        spi_sync(flash->spi, &m);
 
                        if (retlen)
-                               *retlen += m.actual_length
-                                       - sizeof(flash->command);
+                               *retlen += m.actual_length - CMD_SIZE;
                }
        }
 
@@ -435,6 +446,7 @@ static struct flash_info __devinitdata m25p_data [] = {
        { "at25fs040",  0x1f6604, 64 * 1024, 8, SECT_4K, },
 
        { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, },
+       { "at25df641",  0x1f4800, 64 * 1024, 128, SECT_4K, },
 
        { "at26f004",   0x1f0400, 64 * 1024, 8, SECT_4K, },
        { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, },
index e427c82d5f4cb046ff4234e4ce8919062569fda3..bf485ff49457303cc3307655d266085ff23ea098 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/mtd/compatmac.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/mtdram.h>
 
 static unsigned long total_size = CONFIG_MTDRAM_TOTAL_SIZE;
 static unsigned long erase_size = CONFIG_MTDRAM_ERASE_SIZE;
index 180298b92a7af9a80c229a9969a30852b233fb90..5f960182da957eaa8c4a12295fe93b66677e4287 100644 (file)
@@ -282,7 +282,7 @@ static int phram_setup(const char *val, struct kernel_param *kp)
 }
 
 module_param_call(phram, phram_setup, NULL, NULL, 000);
-MODULE_PARM_DESC(phram,"Memory region to map. \"map=<name>,<start>,<length>\"");
+MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>\"");
 
 
 static int __init init_phram(void)
index c815d0f38577281f3b033570d2ac1607a361e15f..4a79b187b568870ad207eaa94e905aec5133e390 100644 (file)
@@ -136,8 +136,6 @@ typedef struct partition_t {
 #endif
 } partition_t;
 
-void ftl_freepart(partition_t *part);
-
 /* Partition state flags */
 #define FTL_FORMATTED  0x01
 
@@ -1014,7 +1012,7 @@ static int ftl_writesect(struct mtd_blktrans_dev *dev,
 
 /*====================================================================*/
 
-void ftl_freepart(partition_t *part)
+static void ftl_freepart(partition_t *part)
 {
        vfree(part->VirtualBlockMap);
        part->VirtualBlockMap = NULL;
@@ -1069,7 +1067,7 @@ static void ftl_remove_dev(struct mtd_blktrans_dev *dev)
        kfree(dev);
 }
 
-struct mtd_blktrans_ops ftl_tr = {
+static struct mtd_blktrans_ops ftl_tr = {
        .name           = "ftl",
        .major          = FTL_MAJOR,
        .part_bits      = PART_BITS,
index b8917beeb65099262da1e316282d663e43933e39..c551d2f0779c2e8c141c3a18c3f5bae05686dd84 100644 (file)
 
 char inftlmountrev[]="$Revision: 1.18 $";
 
-extern int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
-                         size_t *retlen, uint8_t *buf);
-extern int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
-                          size_t *retlen, uint8_t *buf);
-
 /*
  * find_boot_record: Find the INFTL Media Header and its Spare copy which
  *     contains the various device information of the INFTL partition and
index 12c253664eb223e524d31b2fb6bc800f9286cd44..1bd69aa9e22acd2905a28e0e5c76d27d0bd00c94 100644 (file)
@@ -21,6 +21,9 @@ config MTD_PHYSMAP
          particular board as well as the bus width, either statically
          with config options or at run-time.
 
+         To compile this driver as a module, choose M here: the
+         module will be called physmap.
+
 config MTD_PHYSMAP_START
        hex "Physical start address of flash mapping"
        depends on MTD_PHYSMAP
index fc3b2672d1e2a58d18bdd248af1f8362f8b76321..1f492062f8ca7fb18f62f7fbf35ee3ce54a6e758 100644 (file)
@@ -137,7 +137,7 @@ static int bast_flash_probe(struct platform_device *pdev)
        if (info->map.size > AREA_MAXSIZE)
                info->map.size = AREA_MAXSIZE;
 
-       pr_debug("%s: area %08lx, size %ld\n", __FUNCTION__,
+       pr_debug("%s: area %08lx, size %ld\n", __func__,
                 info->map.phys, info->map.size);
 
        info->area = request_mem_region(res->start, info->map.size,
@@ -149,7 +149,7 @@ static int bast_flash_probe(struct platform_device *pdev)
        }
 
        info->map.virt = ioremap(res->start, info->map.size);
-       pr_debug("%s: virt at %08x\n", __FUNCTION__, (int)info->map.virt);
+       pr_debug("%s: virt at %08x\n", __func__, (int)info->map.virt);
 
        if (info->map.virt == 0) {
                printk(KERN_ERR PFX "failed to ioremap() region\n");
@@ -223,3 +223,4 @@ module_exit(bast_flash_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("BAST MTD Map driver");
+MODULE_ALIAS("platform:bast-nor");
index 688ef495888a6ba1efeef5ccff6f9a9646c4a102..59d8fb49270aa93a4d477d2fee8b7cb21ba9438a 100644 (file)
@@ -28,6 +28,9 @@
 
 #define ROM_PROBE_STEP_SIZE (64*1024)
 
+#define DEV_CK804 1
+#define DEV_MCP55 2
+
 struct ck804xrom_window {
        void __iomem *virt;
        unsigned long phys;
@@ -45,8 +48,9 @@ struct ck804xrom_map_info {
        char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
 };
 
-
-/* The 2 bits controlling the window size are often set to allow reading
+/*
+ * The following applies to ck804 only:
+ * The 2 bits controlling the window size are often set to allow reading
  * the BIOS, but too small to allow writing, since the lock registers are
  * 4MiB lower in the address space than the data.
  *
@@ -58,10 +62,17 @@ struct ck804xrom_map_info {
  * If only the 7 Bit is set, it is a 4MiB window.  Otherwise, a
  * 64KiB window.
  *
+ * The following applies to mcp55 only:
+ * The 15 bits controlling the window size are distributed as follows: 
+ * byte @0x88: bit 0..7
+ * byte @0x8c: bit 8..15
+ * word @0x90: bit 16..30
+ * If all bits are enabled, we have a 16? MiB window
+ * Please set win_size_bits to 0x7fffffff if you actually want to do something
  */
 static uint win_size_bits = 0;
 module_param(win_size_bits, uint, 0);
-MODULE_PARM_DESC(win_size_bits, "ROM window size bits override for 0x88 byte, normally set by BIOS.");
+MODULE_PARM_DESC(win_size_bits, "ROM window size bits override, normally set by BIOS.");
 
 static struct ck804xrom_window ck804xrom_window = {
        .maps = LIST_HEAD_INIT(ck804xrom_window.maps),
@@ -102,10 +113,11 @@ static void ck804xrom_cleanup(struct ck804xrom_window *window)
 
 
 static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
-       const struct pci_device_id *ent)
+                                        const struct pci_device_id *ent)
 {
        static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
        u8 byte;
+       u16 word;
        struct ck804xrom_window *window = &ck804xrom_window;
        struct ck804xrom_map_info *map = NULL;
        unsigned long map_top;
@@ -113,26 +125,42 @@ static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
        /* Remember the pci dev I find the window in */
        window->pdev = pci_dev_get(pdev);
 
-       /* Enable the selected rom window.  This is often incorrectly
-        * set up by the BIOS, and the 4MiB offset for the lock registers
-        * requires the full 5MiB of window space.
-        *
-        * This 'write, then read' approach leaves the bits for
-        * other uses of the hardware info.
-        */
-        pci_read_config_byte(pdev, 0x88, &byte);
-        pci_write_config_byte(pdev, 0x88, byte | win_size_bits );
-
-
-       /* Assume the rom window is properly setup, and find it's size */
-       pci_read_config_byte(pdev, 0x88, &byte);
-
-       if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6)))
-               window->phys = 0xffb00000; /* 5MiB */
-       else if ((byte & (1<<7)) == (1<<7))
-               window->phys = 0xffc00000; /* 4MiB */
-       else
-               window->phys = 0xffff0000; /* 64KiB */
+       switch (ent->driver_data) {
+       case DEV_CK804:
+               /* Enable the selected rom window.  This is often incorrectly
+                * set up by the BIOS, and the 4MiB offset for the lock registers
+                * requires the full 5MiB of window space.
+                *
+                * This 'write, then read' approach leaves the bits for
+                * other uses of the hardware info.
+                */
+               pci_read_config_byte(pdev, 0x88, &byte);
+               pci_write_config_byte(pdev, 0x88, byte | win_size_bits );
+
+               /* Assume the rom window is properly setup, and find it's size */
+               pci_read_config_byte(pdev, 0x88, &byte);
+
+               if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6)))
+                       window->phys = 0xffb00000; /* 5MiB */
+               else if ((byte & (1<<7)) == (1<<7))
+                       window->phys = 0xffc00000; /* 4MiB */
+               else
+                       window->phys = 0xffff0000; /* 64KiB */
+               break;
+
+       case DEV_MCP55:
+               pci_read_config_byte(pdev, 0x88, &byte);
+               pci_write_config_byte(pdev, 0x88, byte | (win_size_bits & 0xff));
+
+               pci_read_config_byte(pdev, 0x8c, &byte);
+               pci_write_config_byte(pdev, 0x8c, byte | ((win_size_bits & 0xff00) >> 8));
+
+               pci_read_config_word(pdev, 0x90, &word);
+               pci_write_config_word(pdev, 0x90, word | ((win_size_bits & 0x7fff0000) >> 16));
+
+               window->phys = 0xff000000; /* 16MiB, hardcoded for now */
+               break;
+       }
 
        window->size = 0xffffffffUL - window->phys + 1UL;
 
@@ -303,8 +331,15 @@ static void __devexit ck804xrom_remove_one (struct pci_dev *pdev)
 }
 
 static struct pci_device_id ck804xrom_pci_tbl[] = {
-       { PCI_VENDOR_ID_NVIDIA, 0x0051,
-        PCI_ANY_ID, PCI_ANY_ID, }, /* nvidia ck804 */
+       { PCI_VENDOR_ID_NVIDIA, 0x0051, PCI_ANY_ID, PCI_ANY_ID, DEV_CK804 },
+       { PCI_VENDOR_ID_NVIDIA, 0x0360, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
+       { PCI_VENDOR_ID_NVIDIA, 0x0361, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
+       { PCI_VENDOR_ID_NVIDIA, 0x0362, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
+       { PCI_VENDOR_ID_NVIDIA, 0x0363, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
+       { PCI_VENDOR_ID_NVIDIA, 0x0364, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
+       { PCI_VENDOR_ID_NVIDIA, 0x0365, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
+       { PCI_VENDOR_ID_NVIDIA, 0x0366, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
+       { PCI_VENDOR_ID_NVIDIA, 0x0367, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
        { 0, }
 };
 
@@ -332,7 +367,7 @@ static int __init init_ck804xrom(void)
                        break;
        }
        if (pdev) {
-               retVal = ck804xrom_init_one(pdev, &ck804xrom_pci_tbl[0]);
+               retVal = ck804xrom_init_one(pdev, id);
                pci_dev_put(pdev);
                return retVal;
        }
index 6946d802e6f67e1c03a577e01fa345d2b794715b..325c8880c4379393b4266c0849ee0bfc85488344 100644 (file)
@@ -190,6 +190,7 @@ static struct platform_driver armflash_driver = {
        .remove         = armflash_remove,
        .driver         = {
                .name   = "armflash",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -209,3 +210,4 @@ module_exit(armflash_exit);
 MODULE_AUTHOR("ARM Ltd");
 MODULE_DESCRIPTION("ARM Integrator CFI map driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:armflash");
index c26488a1793abd769ede3be3083afb5562c98925..c8396b8574c4624debf97d0846ab0a88dd07867f 100644 (file)
@@ -253,6 +253,7 @@ static struct platform_driver ixp2000_flash_driver = {
        .remove         = ixp2000_flash_remove,
        .driver         = {
                .name   = "IXP2000-Flash",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -270,4 +271,4 @@ module_init(ixp2000_flash_init);
 module_exit(ixp2000_flash_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
-
+MODULE_ALIAS("platform:IXP2000-Flash");
index 7a828e3e6446d7f9254f083d3b02bb2e9e02e9e0..01f19a4714b5b7383506d929208b0637a6cc7c0f 100644 (file)
@@ -275,6 +275,7 @@ static struct platform_driver ixp4xx_flash_driver = {
        .remove         = ixp4xx_flash_remove,
        .driver         = {
                .name   = "IXP4XX-Flash",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -295,3 +296,4 @@ module_exit(ixp4xx_flash_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems");
 MODULE_AUTHOR("Deepak Saxena");
+MODULE_ALIAS("platform:IXP4XX-Flash");
index e8d9ae535673d68d04b547f029dbdadefd6b3e58..240b0e2d095d6bade93555986d0cd09cc163aa80 100644 (file)
@@ -70,7 +70,7 @@ static void omap_set_vpp(struct map_info *map, int enable)
        }
 }
 
-static int __devinit omapflash_probe(struct platform_device *pdev)
+static int __init omapflash_probe(struct platform_device *pdev)
 {
        int err;
        struct omapflash_info *info;
@@ -130,7 +130,7 @@ out_free_info:
        return err;
 }
 
-static int __devexit omapflash_remove(struct platform_device *pdev)
+static int __exit omapflash_remove(struct platform_device *pdev)
 {
        struct omapflash_info *info = platform_get_drvdata(pdev);
 
@@ -152,16 +152,16 @@ static int __devexit omapflash_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver omapflash_driver = {
-       .probe  = omapflash_probe,
-       .remove = __devexit_p(omapflash_remove),
+       .remove = __exit_p(omapflash_remove),
        .driver = {
                .name   = "omapflash",
+               .owner  = THIS_MODULE,
        },
 };
 
 static int __init omapflash_init(void)
 {
-       return platform_driver_register(&omapflash_driver);
+       return platform_driver_probe(&omapflash_driver, omapflash_probe);
 }
 
 static void __exit omapflash_exit(void)
@@ -174,4 +174,4 @@ module_exit(omapflash_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("MTD NOR map driver for TI OMAP boards");
-
+MODULE_ALIAS("platform:omapflash");
index eaeb56a4070acadbe9633fddad14bc8b69a0f829..1912d968718b38e81752b8c5df587b9081ef92f7 100644 (file)
@@ -33,7 +33,7 @@ MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy");
 #undef DEBUG
 #define DEBUG(n, format, arg...) \
        if (n <= debug) {        \
-               printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
+               printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
        }
 
 #else
index bc4649a17b9d022d44bab69ebb0de575edb9bdd3..183255fcfdcbd288dc38e697b6a6ed8ff3be3321 100644 (file)
@@ -242,6 +242,7 @@ static struct platform_driver physmap_flash_driver = {
        .shutdown       = physmap_flash_shutdown,
        .driver         = {
                .name   = "physmap-flash",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -319,3 +320,10 @@ module_exit(physmap_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
 MODULE_DESCRIPTION("Generic configurable MTD map driver");
+
+/* legacy platform drivers can't hotplug or coldplg */
+#ifndef PHYSMAP_COMPAT
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:physmap-flash");
+#endif
+
index 894c0b27128982fc5d52a6fc79a7b32efecc320f..f0b10ca0502920240b9fee8e3ff728df1808d451 100644 (file)
@@ -47,6 +47,7 @@ struct platram_info {
        struct mtd_info         *mtd;
        struct map_info          map;
        struct mtd_partition    *partitions;
+       bool                    free_partitions;
        struct resource         *area;
        struct platdata_mtd_ram *pdata;
 };
@@ -98,7 +99,8 @@ static int platram_remove(struct platform_device *pdev)
 #ifdef CONFIG_MTD_PARTITIONS
                if (info->partitions) {
                        del_mtd_partitions(info->mtd);
-                       kfree(info->partitions);
+                       if (info->free_partitions)
+                               kfree(info->partitions);
                }
 #endif
                del_mtd_device(info->mtd);
@@ -176,7 +178,8 @@ static int platram_probe(struct platform_device *pdev)
 
        info->map.phys = res->start;
        info->map.size = (res->end - res->start) + 1;
-       info->map.name = pdata->mapname != NULL ? pdata->mapname : (char *)pdev->name;
+       info->map.name = pdata->mapname != NULL ?
+                       (char *)pdata->mapname : (char *)pdev->name;
        info->map.bankwidth = pdata->bankwidth;
 
        /* register our usage of the memory area */
@@ -203,9 +206,19 @@ static int platram_probe(struct platform_device *pdev)
 
        dev_dbg(&pdev->dev, "initialised map, probing for mtd\n");
 
-       /* probe for the right mtd map driver */
+       /* probe for the right mtd map driver
+        * supplied by the platform_data struct */
+
+       if (pdata->map_probes != 0) {
+               const char **map_probes = pdata->map_probes;
+
+               for ( ; !info->mtd && *map_probes; map_probes++)
+                       info->mtd = do_map_probe(*map_probes , &info->map);
+       }
+       /* fallback to map_ram */
+       else
+               info->mtd = do_map_probe("map_ram", &info->map);
 
-       info->mtd = do_map_probe("map_ram" , &info->map);
        if (info->mtd == NULL) {
                dev_err(&pdev->dev, "failed to probe for map_ram\n");
                err = -ENOMEM;
@@ -220,19 +233,21 @@ static int platram_probe(struct platform_device *pdev)
         * to add this device whole */
 
 #ifdef CONFIG_MTD_PARTITIONS
-       if (pdata->nr_partitions > 0) {
-               const char **probes = { NULL };
-
-               if (pdata->probes)
-                       probes = (const char **)pdata->probes;
-
-               err = parse_mtd_partitions(info->mtd, probes,
+       if (!pdata->nr_partitions) {
+               /* try to probe using the supplied probe type */
+               if (pdata->probes) {
+                       err = parse_mtd_partitions(info->mtd, pdata->probes,
                                           &info->partitions, 0);
-               if (err > 0) {
-                       err = add_mtd_partitions(info->mtd, info->partitions,
-                                                err);
+                       info->free_partitions = 1;
+                       if (err > 0)
+                               err = add_mtd_partitions(info->mtd,
+                                       info->partitions, err);
                }
        }
+       /* use the static mapping */
+       else
+               err = add_mtd_partitions(info->mtd, pdata->partitions,
+                               pdata->nr_partitions);
 #endif /* CONFIG_MTD_PARTITIONS */
 
        if (add_mtd_device(info->mtd)) {
@@ -240,7 +255,9 @@ static int platram_probe(struct platform_device *pdev)
                err = -ENOMEM;
        }
 
-       dev_info(&pdev->dev, "registered mtd device\n");
+       if (!err)
+               dev_info(&pdev->dev, "registered mtd device\n");
+
        return err;
 
  exit_free:
@@ -251,6 +268,9 @@ static int platram_probe(struct platform_device *pdev)
 
 /* device driver info */
 
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:mtd-ram");
+
 static struct platform_driver platram_driver = {
        .probe          = platram_probe,
        .remove         = platram_remove,
index 02bde8c982ec68978de22a6a424286019189d4d9..f43ba2815cbbda28a27676d054058dc56e2b0369 100644 (file)
@@ -46,7 +46,7 @@ static struct mtd_partition **msp_parts;
 static struct map_info *msp_maps;
 static int fcnt;
 
-#define DEBUG_MARKER printk(KERN_NOTICE "%s[%d]\n",__FUNCTION__,__LINE__)
+#define DEBUG_MARKER printk(KERN_NOTICE "%s[%d]\n", __func__, __LINE__)
 
 int __init init_msp_flash(void)
 {
index f904e6bd02e05856f220bea1fe89afb0566b60c6..c7d5a52a2d559e997c62ba629bdf38f28f72e2c1 100644 (file)
@@ -456,6 +456,7 @@ static struct platform_driver sa1100_mtd_driver = {
        .shutdown       = sa1100_mtd_shutdown,
        .driver         = {
                .name   = "flash",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -475,3 +476,4 @@ module_exit(sa1100_mtd_exit);
 MODULE_AUTHOR("Nicolas Pitre");
 MODULE_DESCRIPTION("SA1100 CFI map driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:flash");
index 12fe53c0d2fc124eeb6a479f7e94713b8c773507..917dc778f24e12f2c758473c38266804aa517d79 100644 (file)
@@ -92,7 +92,7 @@ int __init init_sharpsl(void)
        parts = sharpsl_partitions;
        nb_parts = ARRAY_SIZE(sharpsl_partitions);
 
-       printk(KERN_NOTICE "Using %s partision definition\n", part_type);
+       printk(KERN_NOTICE "Using %s partition definition\n", part_type);
        add_mtd_partitions(mymtd, parts, nb_parts);
 
        return 0;
index 37e4ded9b60033c2b8dce6005953d77687c3d41c..5217340573140f9f7994e88b4ee0d93e74e013fe 100644 (file)
@@ -124,7 +124,7 @@ int __init init_tqm_mtd(void)
        //request maximum flash size address space
        start_scan_addr = ioremap(flash_addr, flash_size);
        if (!start_scan_addr) {
-               printk(KERN_WARNING "%s:Failed to ioremap address:0x%x\n", __FUNCTION__, flash_addr);
+               printk(KERN_WARNING "%s:Failed to ioremap address:0x%x\n", __func__, flash_addr);
                return -EIO;
        }
 
@@ -132,7 +132,7 @@ int __init init_tqm_mtd(void)
                if(mtd_size >= flash_size)
                        break;
 
-               printk(KERN_INFO "%s: chip probing count %d\n", __FUNCTION__, idx);
+               printk(KERN_INFO "%s: chip probing count %d\n", __func__, idx);
 
                map_banks[idx] = kzalloc(sizeof(struct map_info), GFP_KERNEL);
                if(map_banks[idx] == NULL) {
@@ -178,7 +178,7 @@ int __init init_tqm_mtd(void)
                        mtd_size += mtd_banks[idx]->size;
                        num_banks++;
 
-                       printk(KERN_INFO "%s: bank%d, name:%s, size:%dbytes \n", __FUNCTION__, num_banks,
+                       printk(KERN_INFO "%s: bank%d, name:%s, size:%dbytes \n", __func__, num_banks,
                        mtd_banks[idx]->name, mtd_banks[idx]->size);
                }
        }
index d3cf05012b46a0a9df82888cb39ccd1bfd07f642..5a680e1e61f14dbc2ba684482792f2f40aabbee9 100644 (file)
@@ -35,7 +35,7 @@
 
 #define OOPS_PAGE_SIZE 4096
 
-struct mtdoops_context {
+static struct mtdoops_context {
        int mtd_index;
        struct work_struct work_erase;
        struct work_struct work_write;
index 959fb86cda01e113aca653ef91c646b26f954aa3..5076faf9ca66c54ae300d960f5befccbfc01fb55 100644 (file)
@@ -278,6 +278,54 @@ config MTD_NAND_AT91
        help
          Enables support for NAND Flash / Smart Media Card interface
          on Atmel AT91 processors.
+choice
+       prompt "ECC management for NAND Flash / SmartMedia on AT91"
+       depends on MTD_NAND_AT91
+
+config MTD_NAND_AT91_ECC_HW
+       bool "Hardware ECC"
+       depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9260
+       help
+         Uses hardware ECC provided by the at91sam9260/at91sam9263 chip
+         instead of software ECC.
+         The hardware ECC controller is capable of single bit error
+         correction and 2-bit random detection per page.
+
+         NB : hardware and software ECC schemes are incompatible.
+         If you switch from one to another, you'll have to erase your
+         mtd partition.
+
+         If unsure, say Y
+
+config MTD_NAND_AT91_ECC_SOFT
+       bool "Software ECC"
+       help
+         Uses software ECC.
+
+         NB : hardware and software ECC schemes are incompatible.
+         If you switch from one to another, you'll have to erase your
+         mtd partition.
+
+config MTD_NAND_AT91_ECC_NONE
+       bool "No ECC (testing only, DANGEROUS)"
+       depends on DEBUG_KERNEL
+       help
+         No ECC will be used.
+         It's not a good idea and it should be reserved for testing
+         purpose only.
+
+         If unsure, say N
+
+         endchoice
+
+endchoice
+
+config MTD_NAND_PXA3xx
+       bool "Support for NAND flash devices on PXA3xx"
+       depends on MTD_NAND && PXA3xx
+       help
+         This enables the driver for the NAND flash device found on
+         PXA3xx processors
 
 config MTD_NAND_CM_X270
        tristate "Support for NAND Flash on CM-X270 modules"
@@ -330,4 +378,12 @@ config MTD_NAND_FSL_ELBC
          Enabling this option will enable you to use this to control
          external NAND devices.
 
+config MTD_NAND_FSL_UPM
+       tristate "Support for NAND on Freescale UPM"
+       depends on MTD_NAND && OF_GPIO && (PPC_83xx || PPC_85xx)
+       select FSL_LBC
+       help
+         Enables support for NAND Flash chips wired onto Freescale PowerPC
+         processor localbus with User-Programmable Machine support.
+
 endif # MTD_NAND
index 80d575eeee96663ba0ea51a7256949e18179a271..a6e74a46992a7bde250a5ca7a5d9b20eef96ea00 100644 (file)
@@ -27,10 +27,12 @@ obj-$(CONFIG_MTD_NAND_NDFC)         += ndfc.o
 obj-$(CONFIG_MTD_NAND_AT91)            += at91_nand.o
 obj-$(CONFIG_MTD_NAND_CM_X270)         += cmx270_nand.o
 obj-$(CONFIG_MTD_NAND_BASLER_EXCITE)   += excite_nandflash.o
+obj-$(CONFIG_MTD_NAND_PXA3xx)          += pxa3xx_nand.o
 obj-$(CONFIG_MTD_NAND_PLATFORM)                += plat_nand.o
 obj-$(CONFIG_MTD_ALAUDA)               += alauda.o
 obj-$(CONFIG_MTD_NAND_PASEMI)          += pasemi_nand.o
 obj-$(CONFIG_MTD_NAND_ORION)           += orion_nand.o
 obj-$(CONFIG_MTD_NAND_FSL_ELBC)                += fsl_elbc_nand.o
+obj-$(CONFIG_MTD_NAND_FSL_UPM)         += fsl_upm.o
 
 nand-objs := nand_base.o nand_bbt.o
index c9fb2acf4056b3baab4ccb1ab1e980b2af08d026..414ceaecdb3a2058bbba13def192553ed40ce29f 100644 (file)
@@ -9,6 +9,15 @@
  *  Derived from drivers/mtd/spia.c
  *      Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com)
  *
+ *
+ *  Add Hardware ECC support for AT91SAM9260 / AT91SAM9263
+ *     Richard Genoud (richard.genoud@gmail.com), Adeneo Copyright (C) 2007
+ *
+ *     Derived from Das U-Boot source code
+ *                     (u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c)
+ *     (C) Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
+ *
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
+#ifdef CONFIG_MTD_NAND_AT91_ECC_HW
+#define hard_ecc       1
+#else
+#define hard_ecc       0
+#endif
+
+#ifdef CONFIG_MTD_NAND_AT91_ECC_NONE
+#define no_ecc         1
+#else
+#define no_ecc         0
+#endif
+
+/* Register access macros */
+#define ecc_readl(add, reg)                            \
+       __raw_readl(add + AT91_ECC_##reg)
+#define ecc_writel(add, reg, value)                    \
+       __raw_writel((value), add + AT91_ECC_##reg)
+
+#include <asm/arch/at91_ecc.h> /* AT91SAM9260/3 ECC registers */
+
+/* oob layout for large page size
+ * bad block info is on bytes 0 and 1
+ * the bytes have to be consecutives to avoid
+ * several NAND_CMD_RNDOUT during read
+ */
+static struct nand_ecclayout at91_oobinfo_large = {
+       .eccbytes = 4,
+       .eccpos = {60, 61, 62, 63},
+       .oobfree = {
+               {2, 58}
+       },
+};
+
+/* oob layout for small page size
+ * bad block info is on bytes 4 and 5
+ * the bytes have to be consecutives to avoid
+ * several NAND_CMD_RNDOUT during read
+ */
+static struct nand_ecclayout at91_oobinfo_small = {
+       .eccbytes = 4,
+       .eccpos = {0, 1, 2, 3},
+       .oobfree = {
+               {6, 10}
+       },
+};
+
 struct at91_nand_host {
        struct nand_chip        nand_chip;
        struct mtd_info         mtd;
        void __iomem            *io_base;
        struct at91_nand_data   *board;
+       struct device           *dev;
+       void __iomem            *ecc;
 };
 
 /*
@@ -44,6 +101,12 @@ static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
        struct nand_chip *nand_chip = mtd->priv;
        struct at91_nand_host *host = nand_chip->priv;
 
+       if (host->board->enable_pin && (ctrl & NAND_CTRL_CHANGE)) {
+               if (ctrl & NAND_NCE)
+                       at91_set_gpio_value(host->board->enable_pin, 0);
+               else
+                       at91_set_gpio_value(host->board->enable_pin, 1);
+       }
        if (cmd == NAND_CMD_NONE)
                return;
 
@@ -82,8 +145,217 @@ static void at91_nand_disable(struct at91_nand_host *host)
                at91_set_gpio_value(host->board->enable_pin, 1);
 }
 
+/*
+ * write oob for small pages
+ */
+static int at91_nand_write_oob_512(struct mtd_info *mtd,
+               struct nand_chip *chip, int page)
+{
+       int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
+       int eccsize = chip->ecc.size, length = mtd->oobsize;
+       int len, pos, status = 0;
+       const uint8_t *bufpoi = chip->oob_poi;
+
+       pos = eccsize + chunk;
+
+       chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page);
+       len = min_t(int, length, chunk);
+       chip->write_buf(mtd, bufpoi, len);
+       bufpoi += len;
+       length -= len;
+       if (length > 0)
+               chip->write_buf(mtd, bufpoi, length);
+
+       chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+       status = chip->waitfunc(mtd, chip);
+
+       return status & NAND_STATUS_FAIL ? -EIO : 0;
+
+}
+
+/*
+ * read oob for small pages
+ */
+static int at91_nand_read_oob_512(struct mtd_info *mtd,
+               struct nand_chip *chip, int page, int sndcmd)
+{
+       if (sndcmd) {
+               chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+               sndcmd = 0;
+       }
+       chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+       return sndcmd;
+}
+
+/*
+ * Calculate HW ECC
+ *
+ * function called after a write
+ *
+ * mtd:        MTD block structure
+ * dat:        raw data (unused)
+ * ecc_code:   buffer for ECC
+ */
+static int at91_nand_calculate(struct mtd_info *mtd,
+               const u_char *dat, unsigned char *ecc_code)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct at91_nand_host *host = nand_chip->priv;
+       uint32_t *eccpos = nand_chip->ecc.layout->eccpos;
+       unsigned int ecc_value;
+
+       /* get the first 2 ECC bytes */
+       ecc_value = ecc_readl(host->ecc, PR);
+
+       ecc_code[eccpos[0]] = ecc_value & 0xFF;
+       ecc_code[eccpos[1]] = (ecc_value >> 8) & 0xFF;
+
+       /* get the last 2 ECC bytes */
+       ecc_value = ecc_readl(host->ecc, NPR) & AT91_ECC_NPARITY;
+
+       ecc_code[eccpos[2]] = ecc_value & 0xFF;
+       ecc_code[eccpos[3]] = (ecc_value >> 8) & 0xFF;
+
+       return 0;
+}
+
+/*
+ * HW ECC read page function
+ *
+ * mtd:        mtd info structure
+ * chip:       nand chip info structure
+ * buf:        buffer to store read data
+ */
+static int at91_nand_read_page(struct mtd_info *mtd,
+               struct nand_chip *chip, uint8_t *buf)
+{
+       int eccsize = chip->ecc.size;
+       int eccbytes = chip->ecc.bytes;
+       uint32_t *eccpos = chip->ecc.layout->eccpos;
+       uint8_t *p = buf;
+       uint8_t *oob = chip->oob_poi;
+       uint8_t *ecc_pos;
+       int stat;
+
+       /* read the page */
+       chip->read_buf(mtd, p, eccsize);
+
+       /* move to ECC position if needed */
+       if (eccpos[0] != 0) {
+               /* This only works on large pages
+                * because the ECC controller waits for
+                * NAND_CMD_RNDOUTSTART after the
+                * NAND_CMD_RNDOUT.
+                * anyway, for small pages, the eccpos[0] == 0
+                */
+               chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
+                               mtd->writesize + eccpos[0], -1);
+       }
+
+       /* the ECC controller needs to read the ECC just after the data */
+       ecc_pos = oob + eccpos[0];
+       chip->read_buf(mtd, ecc_pos, eccbytes);
+
+       /* check if there's an error */
+       stat = chip->ecc.correct(mtd, p, oob, NULL);
+
+       if (stat < 0)
+               mtd->ecc_stats.failed++;
+       else
+               mtd->ecc_stats.corrected += stat;
+
+       /* get back to oob start (end of page) */
+       chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
+
+       /* read the oob */
+       chip->read_buf(mtd, oob, mtd->oobsize);
+
+       return 0;
+}
+
+/*
+ * HW ECC Correction
+ *
+ * function called after a read
+ *
+ * mtd:        MTD block structure
+ * dat:        raw data read from the chip
+ * read_ecc:   ECC from the chip (unused)
+ * isnull:     unused
+ *
+ * Detect and correct a 1 bit error for a page
+ */
+static int at91_nand_correct(struct mtd_info *mtd, u_char *dat,
+               u_char *read_ecc, u_char *isnull)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct at91_nand_host *host = nand_chip->priv;
+       unsigned int ecc_status;
+       unsigned int ecc_word, ecc_bit;
+
+       /* get the status from the Status Register */
+       ecc_status = ecc_readl(host->ecc, SR);
+
+       /* if there's no error */
+       if (likely(!(ecc_status & AT91_ECC_RECERR)))
+               return 0;
+
+       /* get error bit offset (4 bits) */
+       ecc_bit = ecc_readl(host->ecc, PR) & AT91_ECC_BITADDR;
+       /* get word address (12 bits) */
+       ecc_word = ecc_readl(host->ecc, PR) & AT91_ECC_WORDADDR;
+       ecc_word >>= 4;
+
+       /* if there are multiple errors */
+       if (ecc_status & AT91_ECC_MULERR) {
+               /* check if it is a freshly erased block
+                * (filled with 0xff) */
+               if ((ecc_bit == AT91_ECC_BITADDR)
+                               && (ecc_word == (AT91_ECC_WORDADDR >> 4))) {
+                       /* the block has just been erased, return OK */
+                       return 0;
+               }
+               /* it doesn't seems to be a freshly
+                * erased block.
+                * We can't correct so many errors */
+               dev_dbg(host->dev, "at91_nand : multiple errors detected."
+                               " Unable to correct.\n");
+               return -EIO;
+       }
+
+       /* if there's a single bit error : we can correct it */
+       if (ecc_status & AT91_ECC_ECCERR) {
+               /* there's nothing much to do here.
+                * the bit error is on the ECC itself.
+                */
+               dev_dbg(host->dev, "at91_nand : one bit error on ECC code."
+                               " Nothing to correct\n");
+               return 0;
+       }
+
+       dev_dbg(host->dev, "at91_nand : one bit error on data."
+                       " (word offset in the page :"
+                       " 0x%x bit offset : 0x%x)\n",
+                       ecc_word, ecc_bit);
+       /* correct the error */
+       if (nand_chip->options & NAND_BUSWIDTH_16) {
+               /* 16 bits words */
+               ((unsigned short *) dat)[ecc_word] ^= (1 << ecc_bit);
+       } else {
+               /* 8 bits words */
+               dat[ecc_word] ^= (1 << ecc_bit);
+       }
+       dev_dbg(host->dev, "at91_nand : error corrected\n");
+       return 1;
+}
+
+/*
+ * Enable HW ECC : unsused
+ */
+static void at91_nand_hwctl(struct mtd_info *mtd, int mode) { ; }
+
 #ifdef CONFIG_MTD_PARTITIONS
-const char *part_probes[] = { "cmdlinepart", NULL };
+static const char *part_probes[] = { "cmdlinepart", NULL };
 #endif
 
 /*
@@ -94,6 +366,8 @@ static int __init at91_nand_probe(struct platform_device *pdev)
        struct at91_nand_host *host;
        struct mtd_info *mtd;
        struct nand_chip *nand_chip;
+       struct resource *regs;
+       struct resource *mem;
        int res;
 
 #ifdef CONFIG_MTD_PARTITIONS
@@ -108,8 +382,13 @@ static int __init at91_nand_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
-       host->io_base = ioremap(pdev->resource[0].start,
-                               pdev->resource[0].end - pdev->resource[0].start + 1);
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem) {
+               printk(KERN_ERR "at91_nand: can't get I/O resource mem\n");
+               return -ENXIO;
+       }
+
+       host->io_base = ioremap(mem->start, mem->end - mem->start + 1);
        if (host->io_base == NULL) {
                printk(KERN_ERR "at91_nand: ioremap failed\n");
                kfree(host);
@@ -119,6 +398,7 @@ static int __init at91_nand_probe(struct platform_device *pdev)
        mtd = &host->mtd;
        nand_chip = &host->nand_chip;
        host->board = pdev->dev.platform_data;
+       host->dev = &pdev->dev;
 
        nand_chip->priv = host;         /* link the private data structures */
        mtd->priv = nand_chip;
@@ -132,7 +412,32 @@ static int __init at91_nand_probe(struct platform_device *pdev)
        if (host->board->rdy_pin)
                nand_chip->dev_ready = at91_nand_device_ready;
 
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (!regs && hard_ecc) {
+               printk(KERN_ERR "at91_nand: can't get I/O resource "
+                               "regs\nFalling back on software ECC\n");
+       }
+
        nand_chip->ecc.mode = NAND_ECC_SOFT;    /* enable ECC */
+       if (no_ecc)
+               nand_chip->ecc.mode = NAND_ECC_NONE;
+       if (hard_ecc && regs) {
+               host->ecc = ioremap(regs->start, regs->end - regs->start + 1);
+               if (host->ecc == NULL) {
+                       printk(KERN_ERR "at91_nand: ioremap failed\n");
+                       res = -EIO;
+                       goto err_ecc_ioremap;
+               }
+               nand_chip->ecc.mode = NAND_ECC_HW_SYNDROME;
+               nand_chip->ecc.calculate = at91_nand_calculate;
+               nand_chip->ecc.correct = at91_nand_correct;
+               nand_chip->ecc.hwctl = at91_nand_hwctl;
+               nand_chip->ecc.read_page = at91_nand_read_page;
+               nand_chip->ecc.bytes = 4;
+               nand_chip->ecc.prepad = 0;
+               nand_chip->ecc.postpad = 0;
+       }
+
        nand_chip->chip_delay = 20;             /* 20us command delay time */
 
        if (host->board->bus_width_16)          /* 16-bit bus width */
@@ -149,8 +454,53 @@ static int __init at91_nand_probe(struct platform_device *pdev)
                }
        }
 
-       /* Scan to find existance of the device */
-       if (nand_scan(mtd, 1)) {
+       /* first scan to find the device and get the page size */
+       if (nand_scan_ident(mtd, 1)) {
+               res = -ENXIO;
+               goto out;
+       }
+
+       if (nand_chip->ecc.mode == NAND_ECC_HW_SYNDROME) {
+               /* ECC is calculated for the whole page (1 step) */
+               nand_chip->ecc.size = mtd->writesize;
+
+               /* set ECC page size and oob layout */
+               switch (mtd->writesize) {
+               case 512:
+                       nand_chip->ecc.layout = &at91_oobinfo_small;
+                       nand_chip->ecc.read_oob = at91_nand_read_oob_512;
+                       nand_chip->ecc.write_oob = at91_nand_write_oob_512;
+                       ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_528);
+                       break;
+               case 1024:
+                       nand_chip->ecc.layout = &at91_oobinfo_large;
+                       ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_1056);
+                       break;
+               case 2048:
+                       nand_chip->ecc.layout = &at91_oobinfo_large;
+                       ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_2112);
+                       break;
+               case 4096:
+                       nand_chip->ecc.layout = &at91_oobinfo_large;
+                       ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_4224);
+                       break;
+               default:
+                       /* page size not handled by HW ECC */
+                       /* switching back to soft ECC */
+                       nand_chip->ecc.mode = NAND_ECC_SOFT;
+                       nand_chip->ecc.calculate = NULL;
+                       nand_chip->ecc.correct = NULL;
+                       nand_chip->ecc.hwctl = NULL;
+                       nand_chip->ecc.read_page = NULL;
+                       nand_chip->ecc.postpad = 0;
+                       nand_chip->ecc.prepad = 0;
+                       nand_chip->ecc.bytes = 0;
+                       break;
+               }
+       }
+
+       /* second phase scan */
+       if (nand_scan_tail(mtd)) {
                res = -ENXIO;
                goto out;
        }
@@ -179,9 +529,15 @@ static int __init at91_nand_probe(struct platform_device *pdev)
        if (!res)
                return res;
 
+#ifdef CONFIG_MTD_PARTITIONS
 release:
+#endif
        nand_release(mtd);
+
 out:
+       iounmap(host->ecc);
+
+err_ecc_ioremap:
        at91_nand_disable(host);
        platform_set_drvdata(pdev, NULL);
        iounmap(host->io_base);
@@ -202,6 +558,7 @@ static int __devexit at91_nand_remove(struct platform_device *pdev)
        at91_nand_disable(host);
 
        iounmap(host->io_base);
+       iounmap(host->ecc);
        kfree(host);
 
        return 0;
@@ -233,4 +590,5 @@ module_exit(at91_nand_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Rick Bronson");
-MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91RM9200");
+MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91RM9200 / AT91SAM9");
+MODULE_ALIAS("platform:at91_nand");
index 747042ab094a6b101e558a4f379ff9b2848a81c1..e87a57297328c4a72cde3d01c605e94d0299eee3 100644 (file)
@@ -1,6 +1,6 @@
 /* linux/drivers/mtd/nand/bf5xx_nand.c
  *
- * Copyright 2006-2007 Analog Devices Inc.
+ * Copyright 2006-2008 Analog Devices Inc.
  *     http://blackfin.uclinux.org/
  *     Bryan Wu <bryan.wu@analog.com>
  *
@@ -74,7 +74,7 @@ static int hardware_ecc = 1;
 static int hardware_ecc;
 #endif
 
-static unsigned short bfin_nfc_pin_req[] =
+static const unsigned short bfin_nfc_pin_req[] =
        {P_NAND_CE,
         P_NAND_RB,
         P_NAND_D0,
@@ -581,12 +581,6 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info)
        bfin_write_NFC_IRQSTAT(val);
        SSYNC();
 
-       if (peripheral_request_list(bfin_nfc_pin_req, DRV_NAME)) {
-               printk(KERN_ERR DRV_NAME
-               ": Requesting Peripherals failed\n");
-               return -EFAULT;
-       }
-
        /* DMA initialization  */
        if (bf5xx_nand_dma_init(info))
                err = -ENXIO;
@@ -654,6 +648,12 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
 
        dev_dbg(&pdev->dev, "(%p)\n", pdev);
 
+       if (peripheral_request_list(bfin_nfc_pin_req, DRV_NAME)) {
+               printk(KERN_ERR DRV_NAME
+               ": Requesting Peripherals failed\n");
+               return -EFAULT;
+       }
+
        if (!plat) {
                dev_err(&pdev->dev, "no platform specific information\n");
                goto exit_error;
@@ -803,3 +803,4 @@ module_exit(bf5xx_nand_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR(DRV_AUTHOR);
 MODULE_DESCRIPTION(DRV_DESC);
+MODULE_ALIAS("platform:" DRV_NAME);
index 8dab69657b1914eefb5ebb0eebf1420f2b78edba..3370a800fd3612fd43f6bb54d4cf8a36cbdf2f14 100644 (file)
@@ -279,7 +279,7 @@ static int is_geode(void)
 
 
 #ifdef CONFIG_MTD_PARTITIONS
-const char *part_probes[] = { "cmdlinepart", NULL };
+static const char *part_probes[] = { "cmdlinepart", NULL };
 #endif
 
 
index 378b7aa638125cfd92929cb537fa2bbd1871cf7f..4b69aacdf5ca45410207dca1f8908413f166e1c1 100644 (file)
@@ -184,11 +184,11 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
                 in_be32(&lbc->fbar), in_be32(&lbc->fpar),
                 in_be32(&lbc->fbcr), priv->bank);
 
+       ctrl->irq_status = 0;
        /* execute special operation */
        out_be32(&lbc->lsor, priv->bank);
 
        /* wait for FCM complete flag or timeout */
-       ctrl->irq_status = 0;
        wait_event_timeout(ctrl->irq_wait, ctrl->irq_status,
                           FCM_TIMEOUT_MSECS * HZ/1000);
        ctrl->status = ctrl->irq_status;
@@ -346,19 +346,20 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
                ctrl->column = column;
                ctrl->oob = 0;
 
-               fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) |
-                     (NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
-
                if (priv->page_size) {
+                       fcr = (NAND_CMD_SEQIN << FCR_CMD0_SHIFT) |
+                             (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT);
+
                        out_be32(&lbc->fir,
                                 (FIR_OP_CW0 << FIR_OP0_SHIFT) |
                                 (FIR_OP_CA  << FIR_OP1_SHIFT) |
                                 (FIR_OP_PA  << FIR_OP2_SHIFT) |
                                 (FIR_OP_WB  << FIR_OP3_SHIFT) |
                                 (FIR_OP_CW1 << FIR_OP4_SHIFT));
-
-                       fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT;
                } else {
+                       fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) |
+                             (NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
+
                        out_be32(&lbc->fir,
                                 (FIR_OP_CW0 << FIR_OP0_SHIFT) |
                                 (FIR_OP_CM2 << FIR_OP1_SHIFT) |
@@ -480,7 +481,7 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
        struct fsl_elbc_ctrl *ctrl = priv->ctrl;
        unsigned int bufsize = mtd->writesize + mtd->oobsize;
 
-       if (len < 0) {
+       if (len <= 0) {
                dev_err(ctrl->dev, "write_buf of %d bytes", len);
                ctrl->status = 0;
                return;
@@ -495,6 +496,15 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
        }
 
        memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
+       /*
+        * This is workaround for the weird elbc hangs during nand write,
+        * Scott Wood says: "...perhaps difference in how long it takes a
+        * write to make it through the localbus compared to a write to IMMR
+        * is causing problems, and sync isn't helping for some reason."
+        * Reading back the last byte helps though.
+        */
+       in_8(&ctrl->addr[ctrl->index] + len - 1);
+
        ctrl->index += len;
 }
 
@@ -666,7 +676,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
        /* adjust Option Register and ECC to match Flash page size */
        if (mtd->writesize == 512) {
                priv->page_size = 0;
-               clrbits32(&lbc->bank[priv->bank].or, ~OR_FCM_PGS);
+               clrbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS);
        } else if (mtd->writesize == 2048) {
                priv->page_size = 1;
                setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS);
@@ -687,11 +697,6 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
                return -1;
        }
 
-       /* The default u-boot configuration on MPC8313ERDB causes errors;
-        * more delay is needed.  This should be safe for other boards
-        * as well.
-        */
-       setbits32(&lbc->bank[priv->bank].or, 0x70);
        return 0;
 }
 
@@ -779,6 +784,8 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
 
        nand_release(&priv->mtd);
 
+       kfree(priv->mtd.name);
+
        if (priv->vbase)
                iounmap(priv->vbase);
 
@@ -839,6 +846,12 @@ static int fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
                goto err;
        }
 
+       priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", res.start);
+       if (!priv->mtd.name) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
        ret = fsl_elbc_chip_init(priv);
        if (ret)
                goto err;
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
new file mode 100644 (file)
index 0000000..1ebfd87
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * Freescale UPM NAND driver.
+ *
+ * Copyright Â© 2007-2008  MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/mtd.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/io.h>
+#include <asm/fsl_lbc.h>
+
+struct fsl_upm_nand {
+       struct device *dev;
+       struct mtd_info mtd;
+       struct nand_chip chip;
+       int last_ctrl;
+#ifdef CONFIG_MTD_PARTITIONS
+       struct mtd_partition *parts;
+#endif
+
+       struct fsl_upm upm;
+       uint8_t upm_addr_offset;
+       uint8_t upm_cmd_offset;
+       void __iomem *io_base;
+       int rnb_gpio;
+       const uint32_t *wait_pattern;
+       const uint32_t *wait_write;
+       int chip_delay;
+};
+
+#define to_fsl_upm_nand(mtd) container_of(mtd, struct fsl_upm_nand, mtd)
+
+static int fun_chip_ready(struct mtd_info *mtd)
+{
+       struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
+
+       if (gpio_get_value(fun->rnb_gpio))
+               return 1;
+
+       dev_vdbg(fun->dev, "busy\n");
+       return 0;
+}
+
+static void fun_wait_rnb(struct fsl_upm_nand *fun)
+{
+       int cnt = 1000000;
+
+       if (fun->rnb_gpio >= 0) {
+               while (--cnt && !fun_chip_ready(&fun->mtd))
+                       cpu_relax();
+       }
+
+       if (!cnt)
+               dev_err(fun->dev, "tired waiting for RNB\n");
+}
+
+static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+       struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
+
+       if (!(ctrl & fun->last_ctrl)) {
+               fsl_upm_end_pattern(&fun->upm);
+
+               if (cmd == NAND_CMD_NONE)
+                       return;
+
+               fun->last_ctrl = ctrl & (NAND_ALE | NAND_CLE);
+       }
+
+       if (ctrl & NAND_CTRL_CHANGE) {
+               if (ctrl & NAND_ALE)
+                       fsl_upm_start_pattern(&fun->upm, fun->upm_addr_offset);
+               else if (ctrl & NAND_CLE)
+                       fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset);
+       }
+
+       fsl_upm_run_pattern(&fun->upm, fun->io_base, cmd);
+
+       if (fun->wait_pattern)
+               fun_wait_rnb(fun);
+}
+
+static uint8_t fun_read_byte(struct mtd_info *mtd)
+{
+       struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
+
+       return in_8(fun->chip.IO_ADDR_R);
+}
+
+static void fun_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+       struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
+       int i;
+
+       for (i = 0; i < len; i++)
+               buf[i] = in_8(fun->chip.IO_ADDR_R);
+}
+
+static void fun_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+       struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
+       int i;
+
+       for (i = 0; i < len; i++) {
+               out_8(fun->chip.IO_ADDR_W, buf[i]);
+               if (fun->wait_write)
+                       fun_wait_rnb(fun);
+       }
+}
+
+static int __devinit fun_chip_init(struct fsl_upm_nand *fun)
+{
+       int ret;
+#ifdef CONFIG_MTD_PARTITIONS
+       static const char *part_types[] = { "cmdlinepart", NULL, };
+#endif
+
+       fun->chip.IO_ADDR_R = fun->io_base;
+       fun->chip.IO_ADDR_W = fun->io_base;
+       fun->chip.cmd_ctrl = fun_cmd_ctrl;
+       fun->chip.chip_delay = fun->chip_delay;
+       fun->chip.read_byte = fun_read_byte;
+       fun->chip.read_buf = fun_read_buf;
+       fun->chip.write_buf = fun_write_buf;
+       fun->chip.ecc.mode = NAND_ECC_SOFT;
+
+       if (fun->rnb_gpio >= 0)
+               fun->chip.dev_ready = fun_chip_ready;
+
+       fun->mtd.priv = &fun->chip;
+       fun->mtd.owner = THIS_MODULE;
+
+       ret = nand_scan(&fun->mtd, 1);
+       if (ret)
+               return ret;
+
+       fun->mtd.name = fun->dev->bus_id;
+
+#ifdef CONFIG_MTD_PARTITIONS
+       ret = parse_mtd_partitions(&fun->mtd, part_types, &fun->parts, 0);
+       if (ret > 0)
+               return add_mtd_partitions(&fun->mtd, fun->parts, ret);
+#endif
+       return add_mtd_device(&fun->mtd);
+}
+
+static int __devinit fun_probe(struct of_device *ofdev,
+                              const struct of_device_id *ofid)
+{
+       struct fsl_upm_nand *fun;
+       struct resource io_res;
+       const uint32_t *prop;
+       int ret;
+       int size;
+
+       fun = kzalloc(sizeof(*fun), GFP_KERNEL);
+       if (!fun)
+               return -ENOMEM;
+
+       ret = of_address_to_resource(ofdev->node, 0, &io_res);
+       if (ret) {
+               dev_err(&ofdev->dev, "can't get IO base\n");
+               goto err1;
+       }
+
+       ret = fsl_upm_find(io_res.start, &fun->upm);
+       if (ret) {
+               dev_err(&ofdev->dev, "can't find UPM\n");
+               goto err1;
+       }
+
+       prop = of_get_property(ofdev->node, "fsl,upm-addr-offset", &size);
+       if (!prop || size != sizeof(uint32_t)) {
+               dev_err(&ofdev->dev, "can't get UPM address offset\n");
+               ret = -EINVAL;
+               goto err2;
+       }
+       fun->upm_addr_offset = *prop;
+
+       prop = of_get_property(ofdev->node, "fsl,upm-cmd-offset", &size);
+       if (!prop || size != sizeof(uint32_t)) {
+               dev_err(&ofdev->dev, "can't get UPM command offset\n");
+               ret = -EINVAL;
+               goto err2;
+       }
+       fun->upm_cmd_offset = *prop;
+
+       fun->rnb_gpio = of_get_gpio(ofdev->node, 0);
+       if (fun->rnb_gpio >= 0) {
+               ret = gpio_request(fun->rnb_gpio, ofdev->dev.bus_id);
+               if (ret) {
+                       dev_err(&ofdev->dev, "can't request RNB gpio\n");
+                       goto err2;
+               }
+               gpio_direction_input(fun->rnb_gpio);
+       } else if (fun->rnb_gpio == -EINVAL) {
+               dev_err(&ofdev->dev, "specified RNB gpio is invalid\n");
+               goto err2;
+       }
+
+       fun->io_base = devm_ioremap_nocache(&ofdev->dev, io_res.start,
+                                         io_res.end - io_res.start + 1);
+       if (!fun->io_base) {
+               ret = -ENOMEM;
+               goto err2;
+       }
+
+       fun->dev = &ofdev->dev;
+       fun->last_ctrl = NAND_CLE;
+       fun->wait_pattern = of_get_property(ofdev->node, "fsl,wait-pattern",
+                                           NULL);
+       fun->wait_write = of_get_property(ofdev->node, "fsl,wait-write", NULL);
+
+       prop = of_get_property(ofdev->node, "chip-delay", NULL);
+       if (prop)
+               fun->chip_delay = *prop;
+       else
+               fun->chip_delay = 50;
+
+       ret = fun_chip_init(fun);
+       if (ret)
+               goto err2;
+
+       dev_set_drvdata(&ofdev->dev, fun);
+
+       return 0;
+err2:
+       if (fun->rnb_gpio >= 0)
+               gpio_free(fun->rnb_gpio);
+err1:
+       kfree(fun);
+
+       return ret;
+}
+
+static int __devexit fun_remove(struct of_device *ofdev)
+{
+       struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev);
+
+       nand_release(&fun->mtd);
+
+       if (fun->rnb_gpio >= 0)
+               gpio_free(fun->rnb_gpio);
+
+       kfree(fun);
+
+       return 0;
+}
+
+static struct of_device_id of_fun_match[] = {
+       { .compatible = "fsl,upm-nand" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, of_fun_match);
+
+static struct of_platform_driver of_fun_driver = {
+       .name           = "fsl,upm-nand",
+       .match_table    = of_fun_match,
+       .probe          = fun_probe,
+       .remove         = __devexit_p(fun_remove),
+};
+
+static int __init fun_module_init(void)
+{
+       return of_register_platform_driver(&of_fun_driver);
+}
+module_init(fun_module_init);
+
+static void __exit fun_module_exit(void)
+{
+       of_unregister_platform_driver(&of_fun_driver);
+}
+module_exit(fun_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
+MODULE_DESCRIPTION("Driver for NAND chips working through Freescale "
+                  "LocalBus User-Programmable Machine");
index 7acb1a0e7409fbf950a06e97f8e58b3a1be38559..ba1bdf787323190377c20aa239317ee278769b5b 100644 (file)
@@ -2229,6 +2229,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 {
        struct nand_flash_dev *type = NULL;
        int i, dev_id, maf_idx;
+       int tmp_id, tmp_manf;
 
        /* Select the device */
        chip->select_chip(mtd, 0);
@@ -2240,6 +2241,26 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
        *maf_id = chip->read_byte(mtd);
        dev_id = chip->read_byte(mtd);
 
+       /* Try again to make sure, as some systems the bus-hold or other
+        * interface concerns can cause random data which looks like a
+        * possibly credible NAND flash to appear. If the two results do
+        * not match, ignore the device completely.
+        */
+
+       chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
+
+       /* Read manufacturer and device IDs */
+
+       tmp_manf = chip->read_byte(mtd);
+       tmp_id = chip->read_byte(mtd);
+
+       if (tmp_manf != *maf_id || tmp_id != dev_id) {
+               printk(KERN_INFO "%s: second ID read did not match "
+                      "%02x,%02x against %02x,%02x\n", __func__,
+                      *maf_id, dev_id, tmp_manf, tmp_id);
+               return ERR_PTR(-ENODEV);
+       }
+
        /* Lookup the flash id */
        for (i = 0; nand_flash_ids[i].name != NULL; i++) {
                if (dev_id == nand_flash_ids[i].id) {
index 1c0e89f00e8dc0d98bc1882079874c2330d8c677..955959eb02d49f301463e8b7ec998431df3bcfe8 100644 (file)
@@ -317,3 +317,5 @@ module_exit(ndfc_nand_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
 MODULE_DESCRIPTION("Platform driver for NDFC");
+MODULE_ALIAS("platform:ndfc-chip");
+MODULE_ALIAS("platform:ndfc-nand");
index ec5ad28b237ef338859b072157b7a24f00b32507..59e05a1c50cf438086085dec1ebc6ca7ea4c36ef 100644 (file)
@@ -169,3 +169,4 @@ module_exit(orion_nand_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Tzachi Perelstein");
 MODULE_DESCRIPTION("NAND glue for Orion platforms");
+MODULE_ALIAS("platform:orion_nand");
index f6d5c2adc4fd41171c892859b96e85c10f45c369..f674c5427b17c5a7783a38f1b178848070705de9 100644 (file)
@@ -54,6 +54,7 @@ static int __init plat_nand_probe(struct platform_device *pdev)
        data->chip.priv = &data;
        data->mtd.priv = &data->chip;
        data->mtd.owner = THIS_MODULE;
+       data->mtd.name = pdev->dev.bus_id;
 
        data->chip.IO_ADDR_R = data->io_base;
        data->chip.IO_ADDR_W = data->io_base;
@@ -150,3 +151,4 @@ module_exit(plat_nand_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Vitaly Wool");
 MODULE_DESCRIPTION("Simple generic NAND driver");
+MODULE_ALIAS("platform:gen_nand");
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
new file mode 100644 (file)
index 0000000..fceb468
--- /dev/null
@@ -0,0 +1,1249 @@
+/*
+ * drivers/mtd/nand/pxa3xx_nand.c
+ *
+ * Copyright Â© 2005 Intel Corporation
+ * Copyright Â© 2006 Marvell International 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.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <asm/dma.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa3xx_nand.h>
+
+#define        CHIP_DELAY_TIMEOUT      (2 * HZ/10)
+
+/* registers and bit definitions */
+#define NDCR           (0x00) /* Control register */
+#define NDTR0CS0       (0x04) /* Timing Parameter 0 for CS0 */
+#define NDTR1CS0       (0x0C) /* Timing Parameter 1 for CS0 */
+#define NDSR           (0x14) /* Status Register */
+#define NDPCR          (0x18) /* Page Count Register */
+#define NDBDR0         (0x1C) /* Bad Block Register 0 */
+#define NDBDR1         (0x20) /* Bad Block Register 1 */
+#define NDDB           (0x40) /* Data Buffer */
+#define NDCB0          (0x48) /* Command Buffer0 */
+#define NDCB1          (0x4C) /* Command Buffer1 */
+#define NDCB2          (0x50) /* Command Buffer2 */
+
+#define NDCR_SPARE_EN          (0x1 << 31)
+#define NDCR_ECC_EN            (0x1 << 30)
+#define NDCR_DMA_EN            (0x1 << 29)
+#define NDCR_ND_RUN            (0x1 << 28)
+#define NDCR_DWIDTH_C          (0x1 << 27)
+#define NDCR_DWIDTH_M          (0x1 << 26)
+#define NDCR_PAGE_SZ           (0x1 << 24)
+#define NDCR_NCSX              (0x1 << 23)
+#define NDCR_ND_MODE           (0x3 << 21)
+#define NDCR_NAND_MODE         (0x0)
+#define NDCR_CLR_PG_CNT                (0x1 << 20)
+#define NDCR_CLR_ECC           (0x1 << 19)
+#define NDCR_RD_ID_CNT_MASK    (0x7 << 16)
+#define NDCR_RD_ID_CNT(x)      (((x) << 16) & NDCR_RD_ID_CNT_MASK)
+
+#define NDCR_RA_START          (0x1 << 15)
+#define NDCR_PG_PER_BLK                (0x1 << 14)
+#define NDCR_ND_ARB_EN         (0x1 << 12)
+
+#define NDSR_MASK              (0xfff)
+#define NDSR_RDY               (0x1 << 11)
+#define NDSR_CS0_PAGED         (0x1 << 10)
+#define NDSR_CS1_PAGED         (0x1 << 9)
+#define NDSR_CS0_CMDD          (0x1 << 8)
+#define NDSR_CS1_CMDD          (0x1 << 7)
+#define NDSR_CS0_BBD           (0x1 << 6)
+#define NDSR_CS1_BBD           (0x1 << 5)
+#define NDSR_DBERR             (0x1 << 4)
+#define NDSR_SBERR             (0x1 << 3)
+#define NDSR_WRDREQ            (0x1 << 2)
+#define NDSR_RDDREQ            (0x1 << 1)
+#define NDSR_WRCMDREQ          (0x1)
+
+#define NDCB0_AUTO_RS          (0x1 << 25)
+#define NDCB0_CSEL             (0x1 << 24)
+#define NDCB0_CMD_TYPE_MASK    (0x7 << 21)
+#define NDCB0_CMD_TYPE(x)      (((x) << 21) & NDCB0_CMD_TYPE_MASK)
+#define NDCB0_NC               (0x1 << 20)
+#define NDCB0_DBC              (0x1 << 19)
+#define NDCB0_ADDR_CYC_MASK    (0x7 << 16)
+#define NDCB0_ADDR_CYC(x)      (((x) << 16) & NDCB0_ADDR_CYC_MASK)
+#define NDCB0_CMD2_MASK                (0xff << 8)
+#define NDCB0_CMD1_MASK                (0xff)
+#define NDCB0_ADDR_CYC_SHIFT   (16)
+
+/* dma-able I/O address for the NAND data and commands */
+#define NDCB0_DMA_ADDR         (0x43100048)
+#define NDDB_DMA_ADDR          (0x43100040)
+
+/* macros for registers read/write */
+#define nand_writel(info, off, val)    \
+       __raw_writel((val), (info)->mmio_base + (off))
+
+#define nand_readl(info, off)          \
+       __raw_readl((info)->mmio_base + (off))
+
+/* error code and state */
+enum {
+       ERR_NONE        = 0,
+       ERR_DMABUSERR   = -1,
+       ERR_SENDCMD     = -2,
+       ERR_DBERR       = -3,
+       ERR_BBERR       = -4,
+};
+
+enum {
+       STATE_READY     = 0,
+       STATE_CMD_HANDLE,
+       STATE_DMA_READING,
+       STATE_DMA_WRITING,
+       STATE_DMA_DONE,
+       STATE_PIO_READING,
+       STATE_PIO_WRITING,
+};
+
+struct pxa3xx_nand_timing {
+       unsigned int    tCH;  /* Enable signal hold time */
+       unsigned int    tCS;  /* Enable signal setup time */
+       unsigned int    tWH;  /* ND_nWE high duration */
+       unsigned int    tWP;  /* ND_nWE pulse time */
+       unsigned int    tRH;  /* ND_nRE high duration */
+       unsigned int    tRP;  /* ND_nRE pulse width */
+       unsigned int    tR;   /* ND_nWE high to ND_nRE low for read */
+       unsigned int    tWHR; /* ND_nWE high to ND_nRE low for status read */
+       unsigned int    tAR;  /* ND_ALE low to ND_nRE low delay */
+};
+
+struct pxa3xx_nand_cmdset {
+       uint16_t        read1;
+       uint16_t        read2;
+       uint16_t        program;
+       uint16_t        read_status;
+       uint16_t        read_id;
+       uint16_t        erase;
+       uint16_t        reset;
+       uint16_t        lock;
+       uint16_t        unlock;
+       uint16_t        lock_status;
+};
+
+struct pxa3xx_nand_flash {
+       struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
+       struct pxa3xx_nand_cmdset *cmdset;
+
+       uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */
+       uint32_t page_size;     /* Page size in bytes (PAGE_SZ) */
+       uint32_t flash_width;   /* Width of Flash memory (DWIDTH_M) */
+       uint32_t dfc_width;     /* Width of flash controller(DWIDTH_C) */
+       uint32_t num_blocks;    /* Number of physical blocks in Flash */
+       uint32_t chip_id;
+
+       /* NOTE: these are automatically calculated, do not define */
+       size_t          oob_size;
+       size_t          read_id_bytes;
+
+       unsigned int    col_addr_cycles;
+       unsigned int    row_addr_cycles;
+};
+
+struct pxa3xx_nand_info {
+       struct nand_chip        nand_chip;
+
+       struct platform_device   *pdev;
+       struct pxa3xx_nand_flash *flash_info;
+
+       struct clk              *clk;
+       void __iomem            *mmio_base;
+
+       unsigned int            buf_start;
+       unsigned int            buf_count;
+
+       /* DMA information */
+       int                     drcmr_dat;
+       int                     drcmr_cmd;
+
+       unsigned char           *data_buff;
+       dma_addr_t              data_buff_phys;
+       size_t                  data_buff_size;
+       int                     data_dma_ch;
+       struct pxa_dma_desc     *data_desc;
+       dma_addr_t              data_desc_addr;
+
+       uint32_t                reg_ndcr;
+
+       /* saved column/page_addr during CMD_SEQIN */
+       int                     seqin_column;
+       int                     seqin_page_addr;
+
+       /* relate to the command */
+       unsigned int            state;
+
+       int                     use_ecc;        /* use HW ECC ? */
+       int                     use_dma;        /* use DMA ? */
+
+       size_t                  data_size;      /* data size in FIFO */
+       int                     retcode;
+       struct completion       cmd_complete;
+
+       /* generated NDCBx register values */
+       uint32_t                ndcb0;
+       uint32_t                ndcb1;
+       uint32_t                ndcb2;
+};
+
+static int use_dma = 1;
+module_param(use_dma, bool, 0444);
+MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW");
+
+static struct pxa3xx_nand_cmdset smallpage_cmdset = {
+       .read1          = 0x0000,
+       .read2          = 0x0050,
+       .program        = 0x1080,
+       .read_status    = 0x0070,
+       .read_id        = 0x0090,
+       .erase          = 0xD060,
+       .reset          = 0x00FF,
+       .lock           = 0x002A,
+       .unlock         = 0x2423,
+       .lock_status    = 0x007A,
+};
+
+static struct pxa3xx_nand_cmdset largepage_cmdset = {
+       .read1          = 0x3000,
+       .read2          = 0x0050,
+       .program        = 0x1080,
+       .read_status    = 0x0070,
+       .read_id        = 0x0090,
+       .erase          = 0xD060,
+       .reset          = 0x00FF,
+       .lock           = 0x002A,
+       .unlock         = 0x2423,
+       .lock_status    = 0x007A,
+};
+
+static struct pxa3xx_nand_timing samsung512MbX16_timing = {
+       .tCH    = 10,
+       .tCS    = 0,
+       .tWH    = 20,
+       .tWP    = 40,
+       .tRH    = 30,
+       .tRP    = 40,
+       .tR     = 11123,
+       .tWHR   = 110,
+       .tAR    = 10,
+};
+
+static struct pxa3xx_nand_flash samsung512MbX16 = {
+       .timing         = &samsung512MbX16_timing,
+       .cmdset         = &smallpage_cmdset,
+       .page_per_block = 32,
+       .page_size      = 512,
+       .flash_width    = 16,
+       .dfc_width      = 16,
+       .num_blocks     = 4096,
+       .chip_id        = 0x46ec,
+};
+
+static struct pxa3xx_nand_timing micron_timing = {
+       .tCH    = 10,
+       .tCS    = 25,
+       .tWH    = 15,
+       .tWP    = 25,
+       .tRH    = 15,
+       .tRP    = 25,
+       .tR     = 25000,
+       .tWHR   = 60,
+       .tAR    = 10,
+};
+
+static struct pxa3xx_nand_flash micron1GbX8 = {
+       .timing         = &micron_timing,
+       .cmdset         = &largepage_cmdset,
+       .page_per_block = 64,
+       .page_size      = 2048,
+       .flash_width    = 8,
+       .dfc_width      = 8,
+       .num_blocks     = 1024,
+       .chip_id        = 0xa12c,
+};
+
+static struct pxa3xx_nand_flash micron1GbX16 = {
+       .timing         = &micron_timing,
+       .cmdset         = &largepage_cmdset,
+       .page_per_block = 64,
+       .page_size      = 2048,
+       .flash_width    = 16,
+       .dfc_width      = 16,
+       .num_blocks     = 1024,
+       .chip_id        = 0xb12c,
+};
+
+static struct pxa3xx_nand_flash *builtin_flash_types[] = {
+       &samsung512MbX16,
+       &micron1GbX8,
+       &micron1GbX16,
+};
+
+#define NDTR0_tCH(c)   (min((c), 7) << 19)
+#define NDTR0_tCS(c)   (min((c), 7) << 16)
+#define NDTR0_tWH(c)   (min((c), 7) << 11)
+#define NDTR0_tWP(c)   (min((c), 7) << 8)
+#define NDTR0_tRH(c)   (min((c), 7) << 3)
+#define NDTR0_tRP(c)   (min((c), 7) << 0)
+
+#define NDTR1_tR(c)    (min((c), 65535) << 16)
+#define NDTR1_tWHR(c)  (min((c), 15) << 4)
+#define NDTR1_tAR(c)   (min((c), 15) << 0)
+
+/* convert nano-seconds to nand flash controller clock cycles */
+#define ns2cycle(ns, clk)      (int)(((ns) * (clk / 1000000) / 1000) + 1)
+
+static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
+                                  struct pxa3xx_nand_timing *t)
+{
+       unsigned long nand_clk = clk_get_rate(info->clk);
+       uint32_t ndtr0, ndtr1;
+
+       ndtr0 = NDTR0_tCH(ns2cycle(t->tCH, nand_clk)) |
+               NDTR0_tCS(ns2cycle(t->tCS, nand_clk)) |
+               NDTR0_tWH(ns2cycle(t->tWH, nand_clk)) |
+               NDTR0_tWP(ns2cycle(t->tWP, nand_clk)) |
+               NDTR0_tRH(ns2cycle(t->tRH, nand_clk)) |
+               NDTR0_tRP(ns2cycle(t->tRP, nand_clk));
+
+       ndtr1 = NDTR1_tR(ns2cycle(t->tR, nand_clk)) |
+               NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) |
+               NDTR1_tAR(ns2cycle(t->tAR, nand_clk));
+
+       nand_writel(info, NDTR0CS0, ndtr0);
+       nand_writel(info, NDTR1CS0, ndtr1);
+}
+
+#define WAIT_EVENT_TIMEOUT     10
+
+static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event)
+{
+       int timeout = WAIT_EVENT_TIMEOUT;
+       uint32_t ndsr;
+
+       while (timeout--) {
+               ndsr = nand_readl(info, NDSR) & NDSR_MASK;
+               if (ndsr & event) {
+                       nand_writel(info, NDSR, ndsr);
+                       return 0;
+               }
+               udelay(10);
+       }
+
+       return -ETIMEDOUT;
+}
+
+static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
+                       uint16_t cmd, int column, int page_addr)
+{
+       struct pxa3xx_nand_flash *f = info->flash_info;
+       struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
+
+       /* calculate data size */
+       switch (f->page_size) {
+       case 2048:
+               info->data_size = (info->use_ecc) ? 2088 : 2112;
+               break;
+       case 512:
+               info->data_size = (info->use_ecc) ? 520 : 528;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* generate values for NDCBx registers */
+       info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
+       info->ndcb1 = 0;
+       info->ndcb2 = 0;
+       info->ndcb0 |= NDCB0_ADDR_CYC(f->row_addr_cycles + f->col_addr_cycles);
+
+       if (f->col_addr_cycles == 2) {
+               /* large block, 2 cycles for column address
+                * row address starts from 3rd cycle
+                */
+               info->ndcb1 |= (page_addr << 16) | (column & 0xffff);
+               if (f->row_addr_cycles == 3)
+                       info->ndcb2 = (page_addr >> 16) & 0xff;
+       } else
+               /* small block, 1 cycles for column address
+                * row address starts from 2nd cycle
+                */
+               info->ndcb1 = (page_addr << 8) | (column & 0xff);
+
+       if (cmd == cmdset->program)
+               info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
+
+       return 0;
+}
+
+static int prepare_erase_cmd(struct pxa3xx_nand_info *info,
+                       uint16_t cmd, int page_addr)
+{
+       info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
+       info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3);
+       info->ndcb1 = page_addr;
+       info->ndcb2 = 0;
+       return 0;
+}
+
+static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
+{
+       struct pxa3xx_nand_cmdset *cmdset = info->flash_info->cmdset;
+
+       info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
+       info->ndcb1 = 0;
+       info->ndcb2 = 0;
+
+       if (cmd == cmdset->read_id) {
+               info->ndcb0 |= NDCB0_CMD_TYPE(3);
+               info->data_size = 8;
+       } else if (cmd == cmdset->read_status) {
+               info->ndcb0 |= NDCB0_CMD_TYPE(4);
+               info->data_size = 8;
+       } else if (cmd == cmdset->reset || cmd == cmdset->lock ||
+                  cmd == cmdset->unlock) {
+               info->ndcb0 |= NDCB0_CMD_TYPE(5);
+       } else
+               return -EINVAL;
+
+       return 0;
+}
+
+static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
+{
+       uint32_t ndcr;
+
+       ndcr = nand_readl(info, NDCR);
+       nand_writel(info, NDCR, ndcr & ~int_mask);
+}
+
+static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
+{
+       uint32_t ndcr;
+
+       ndcr = nand_readl(info, NDCR);
+       nand_writel(info, NDCR, ndcr | int_mask);
+}
+
+/* NOTE: it is a must to set ND_RUN firstly, then write command buffer
+ * otherwise, it does not work
+ */
+static int write_cmd(struct pxa3xx_nand_info *info)
+{
+       uint32_t ndcr;
+
+       /* clear status bits and run */
+       nand_writel(info, NDSR, NDSR_MASK);
+
+       ndcr = info->reg_ndcr;
+
+       ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
+       ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
+       ndcr |= NDCR_ND_RUN;
+
+       nand_writel(info, NDCR, ndcr);
+
+       if (wait_for_event(info, NDSR_WRCMDREQ)) {
+               printk(KERN_ERR "timed out writing command\n");
+               return -ETIMEDOUT;
+       }
+
+       nand_writel(info, NDCB0, info->ndcb0);
+       nand_writel(info, NDCB0, info->ndcb1);
+       nand_writel(info, NDCB0, info->ndcb2);
+       return 0;
+}
+
+static int handle_data_pio(struct pxa3xx_nand_info *info)
+{
+       int ret, timeout = CHIP_DELAY_TIMEOUT;
+
+       switch (info->state) {
+       case STATE_PIO_WRITING:
+               __raw_writesl(info->mmio_base + NDDB, info->data_buff,
+                               info->data_size << 2);
+
+               enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
+
+               ret = wait_for_completion_timeout(&info->cmd_complete, timeout);
+               if (!ret) {
+                       printk(KERN_ERR "program command time out\n");
+                       return -1;
+               }
+               break;
+       case STATE_PIO_READING:
+               __raw_readsl(info->mmio_base + NDDB, info->data_buff,
+                               info->data_size << 2);
+               break;
+       default:
+               printk(KERN_ERR "%s: invalid state %d\n", __func__,
+                               info->state);
+               return -EINVAL;
+       }
+
+       info->state = STATE_READY;
+       return 0;
+}
+
+static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out)
+{
+       struct pxa_dma_desc *desc = info->data_desc;
+       int dma_len = ALIGN(info->data_size, 32);
+
+       desc->ddadr = DDADR_STOP;
+       desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len;
+
+       if (dir_out) {
+               desc->dsadr = info->data_buff_phys;
+               desc->dtadr = NDDB_DMA_ADDR;
+               desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG;
+       } else {
+               desc->dtadr = info->data_buff_phys;
+               desc->dsadr = NDDB_DMA_ADDR;
+               desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
+       }
+
+       DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch;
+       DDADR(info->data_dma_ch) = info->data_desc_addr;
+       DCSR(info->data_dma_ch) |= DCSR_RUN;
+}
+
+static void pxa3xx_nand_data_dma_irq(int channel, void *data)
+{
+       struct pxa3xx_nand_info *info = data;
+       uint32_t dcsr;
+
+       dcsr = DCSR(channel);
+       DCSR(channel) = dcsr;
+
+       if (dcsr & DCSR_BUSERR) {
+               info->retcode = ERR_DMABUSERR;
+               complete(&info->cmd_complete);
+       }
+
+       if (info->state == STATE_DMA_WRITING) {
+               info->state = STATE_DMA_DONE;
+               enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
+       } else {
+               info->state = STATE_READY;
+               complete(&info->cmd_complete);
+       }
+}
+
+static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
+{
+       struct pxa3xx_nand_info *info = devid;
+       unsigned int status;
+
+       status = nand_readl(info, NDSR);
+
+       if (status & (NDSR_RDDREQ | NDSR_DBERR)) {
+               if (status & NDSR_DBERR)
+                       info->retcode = ERR_DBERR;
+
+               disable_int(info, NDSR_RDDREQ | NDSR_DBERR);
+
+               if (info->use_dma) {
+                       info->state = STATE_DMA_READING;
+                       start_data_dma(info, 0);
+               } else {
+                       info->state = STATE_PIO_READING;
+                       complete(&info->cmd_complete);
+               }
+       } else if (status & NDSR_WRDREQ) {
+               disable_int(info, NDSR_WRDREQ);
+               if (info->use_dma) {
+                       info->state = STATE_DMA_WRITING;
+                       start_data_dma(info, 1);
+               } else {
+                       info->state = STATE_PIO_WRITING;
+                       complete(&info->cmd_complete);
+               }
+       } else if (status & (NDSR_CS0_BBD | NDSR_CS0_CMDD)) {
+               if (status & NDSR_CS0_BBD)
+                       info->retcode = ERR_BBERR;
+
+               disable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
+               info->state = STATE_READY;
+               complete(&info->cmd_complete);
+       }
+       nand_writel(info, NDSR, status);
+       return IRQ_HANDLED;
+}
+
+static int pxa3xx_nand_do_cmd(struct pxa3xx_nand_info *info, uint32_t event)
+{
+       uint32_t ndcr;
+       int ret, timeout = CHIP_DELAY_TIMEOUT;
+
+       if (write_cmd(info)) {
+               info->retcode = ERR_SENDCMD;
+               goto fail_stop;
+       }
+
+       info->state = STATE_CMD_HANDLE;
+
+       enable_int(info, event);
+
+       ret = wait_for_completion_timeout(&info->cmd_complete, timeout);
+       if (!ret) {
+               printk(KERN_ERR "command execution timed out\n");
+               info->retcode = ERR_SENDCMD;
+               goto fail_stop;
+       }
+
+       if (info->use_dma == 0 && info->data_size > 0)
+               if (handle_data_pio(info))
+                       goto fail_stop;
+
+       return 0;
+
+fail_stop:
+       ndcr = nand_readl(info, NDCR);
+       nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
+       udelay(10);
+       return -ETIMEDOUT;
+}
+
+static int pxa3xx_nand_dev_ready(struct mtd_info *mtd)
+{
+       struct pxa3xx_nand_info *info = mtd->priv;
+       return (nand_readl(info, NDSR) & NDSR_RDY) ? 1 : 0;
+}
+
+static inline int is_buf_blank(uint8_t *buf, size_t len)
+{
+       for (; len > 0; len--)
+               if (*buf++ != 0xff)
+                       return 0;
+       return 1;
+}
+
+static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
+                               int column, int page_addr)
+{
+       struct pxa3xx_nand_info *info = mtd->priv;
+       struct pxa3xx_nand_flash *flash_info = info->flash_info;
+       struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset;
+       int ret;
+
+       info->use_dma = (use_dma) ? 1 : 0;
+       info->use_ecc = 0;
+       info->data_size = 0;
+       info->state = STATE_READY;
+
+       init_completion(&info->cmd_complete);
+
+       switch (command) {
+       case NAND_CMD_READOOB:
+               /* disable HW ECC to get all the OOB data */
+               info->buf_count = mtd->writesize + mtd->oobsize;
+               info->buf_start = mtd->writesize + column;
+
+               if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr))
+                       break;
+
+               pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR);
+
+               /* We only are OOB, so if the data has error, does not matter */
+               if (info->retcode == ERR_DBERR)
+                       info->retcode = ERR_NONE;
+               break;
+
+       case NAND_CMD_READ0:
+               info->use_ecc = 1;
+               info->retcode = ERR_NONE;
+               info->buf_start = column;
+               info->buf_count = mtd->writesize + mtd->oobsize;
+               memset(info->data_buff, 0xFF, info->buf_count);
+
+               if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr))
+                       break;
+
+               pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR);
+
+               if (info->retcode == ERR_DBERR) {
+                       /* for blank page (all 0xff), HW will calculate its ECC as
+                        * 0, which is different from the ECC information within
+                        * OOB, ignore such double bit errors
+                        */
+                       if (is_buf_blank(info->data_buff, mtd->writesize))
+                               info->retcode = ERR_NONE;
+               }
+               break;
+       case NAND_CMD_SEQIN:
+               info->buf_start = column;
+               info->buf_count = mtd->writesize + mtd->oobsize;
+               memset(info->data_buff, 0xff, info->buf_count);
+
+               /* save column/page_addr for next CMD_PAGEPROG */
+               info->seqin_column = column;
+               info->seqin_page_addr = page_addr;
+               break;
+       case NAND_CMD_PAGEPROG:
+               info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1;
+
+               if (prepare_read_prog_cmd(info, cmdset->program,
+                               info->seqin_column, info->seqin_page_addr))
+                       break;
+
+               pxa3xx_nand_do_cmd(info, NDSR_WRDREQ);
+               break;
+       case NAND_CMD_ERASE1:
+               if (prepare_erase_cmd(info, cmdset->erase, page_addr))
+                       break;
+
+               pxa3xx_nand_do_cmd(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
+               break;
+       case NAND_CMD_ERASE2:
+               break;
+       case NAND_CMD_READID:
+       case NAND_CMD_STATUS:
+               info->use_dma = 0;      /* force PIO read */
+               info->buf_start = 0;
+               info->buf_count = (command == NAND_CMD_READID) ?
+                               flash_info->read_id_bytes : 1;
+
+               if (prepare_other_cmd(info, (command == NAND_CMD_READID) ?
+                               cmdset->read_id : cmdset->read_status))
+                       break;
+
+               pxa3xx_nand_do_cmd(info, NDSR_RDDREQ);
+               break;
+       case NAND_CMD_RESET:
+               if (prepare_other_cmd(info, cmdset->reset))
+                       break;
+
+               ret = pxa3xx_nand_do_cmd(info, NDSR_CS0_CMDD);
+               if (ret == 0) {
+                       int timeout = 2;
+                       uint32_t ndcr;
+
+                       while (timeout--) {
+                               if (nand_readl(info, NDSR) & NDSR_RDY)
+                                       break;
+                               msleep(10);
+                       }
+
+                       ndcr = nand_readl(info, NDCR);
+                       nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
+               }
+               break;
+       default:
+               printk(KERN_ERR "non-supported command.\n");
+               break;
+       }
+
+       if (info->retcode == ERR_DBERR) {
+               printk(KERN_ERR "double bit error @ page %08x\n", page_addr);
+               info->retcode = ERR_NONE;
+       }
+}
+
+static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
+{
+       struct pxa3xx_nand_info *info = mtd->priv;
+       char retval = 0xFF;
+
+       if (info->buf_start < info->buf_count)
+               /* Has just send a new command? */
+               retval = info->data_buff[info->buf_start++];
+
+       return retval;
+}
+
+static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
+{
+       struct pxa3xx_nand_info *info = mtd->priv;
+       u16 retval = 0xFFFF;
+
+       if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
+               retval = *((u16 *)(info->data_buff+info->buf_start));
+               info->buf_start += 2;
+       }
+       return retval;
+}
+
+static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+       struct pxa3xx_nand_info *info = mtd->priv;
+       int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
+
+       memcpy(buf, info->data_buff + info->buf_start, real_len);
+       info->buf_start += real_len;
+}
+
+static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
+               const uint8_t *buf, int len)
+{
+       struct pxa3xx_nand_info *info = mtd->priv;
+       int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
+
+       memcpy(info->data_buff + info->buf_start, buf, real_len);
+       info->buf_start += real_len;
+}
+
+static int pxa3xx_nand_verify_buf(struct mtd_info *mtd,
+               const uint8_t *buf, int len)
+{
+       return 0;
+}
+
+static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+       return;
+}
+
+static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
+{
+       struct pxa3xx_nand_info *info = mtd->priv;
+
+       /* pxa3xx_nand_send_command has waited for command complete */
+       if (this->state == FL_WRITING || this->state == FL_ERASING) {
+               if (info->retcode == ERR_NONE)
+                       return 0;
+               else {
+                       /*
+                        * any error make it return 0x01 which will tell
+                        * the caller the erase and write fail
+                        */
+                       return 0x01;
+               }
+       }
+
+       return 0;
+}
+
+static void pxa3xx_nand_ecc_hwctl(struct mtd_info *mtd, int mode)
+{
+       return;
+}
+
+static int pxa3xx_nand_ecc_calculate(struct mtd_info *mtd,
+               const uint8_t *dat, uint8_t *ecc_code)
+{
+       return 0;
+}
+
+static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd,
+               uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc)
+{
+       struct pxa3xx_nand_info *info = mtd->priv;
+       /*
+        * Any error include ERR_SEND_CMD, ERR_DBERR, ERR_BUSERR, we
+        * consider it as a ecc error which will tell the caller the
+        * read fail We have distinguish all the errors, but the
+        * nand_read_ecc only check this function return value
+        */
+       if (info->retcode != ERR_NONE)
+               return -1;
+
+       return 0;
+}
+
+static int __readid(struct pxa3xx_nand_info *info, uint32_t *id)
+{
+       struct pxa3xx_nand_flash *f = info->flash_info;
+       struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
+       uint32_t ndcr;
+       uint8_t  id_buff[8];
+
+       if (prepare_other_cmd(info, cmdset->read_id)) {
+               printk(KERN_ERR "failed to prepare command\n");
+               return -EINVAL;
+       }
+
+       /* Send command */
+       if (write_cmd(info))
+               goto fail_timeout;
+
+       /* Wait for CMDDM(command done successfully) */
+       if (wait_for_event(info, NDSR_RDDREQ))
+               goto fail_timeout;
+
+       __raw_readsl(info->mmio_base + NDDB, id_buff, 2);
+       *id = id_buff[0] | (id_buff[1] << 8);
+       return 0;
+
+fail_timeout:
+       ndcr = nand_readl(info, NDCR);
+       nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
+       udelay(10);
+       return -ETIMEDOUT;
+}
+
+static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
+                                   struct pxa3xx_nand_flash *f)
+{
+       struct platform_device *pdev = info->pdev;
+       struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+       uint32_t ndcr = 0x00000FFF; /* disable all interrupts */
+
+       if (f->page_size != 2048 && f->page_size != 512)
+               return -EINVAL;
+
+       if (f->flash_width != 16 && f->flash_width != 8)
+               return -EINVAL;
+
+       /* calculate flash information */
+       f->oob_size = (f->page_size == 2048) ? 64 : 16;
+       f->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
+
+       /* calculate addressing information */
+       f->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
+
+       if (f->num_blocks * f->page_per_block > 65536)
+               f->row_addr_cycles = 3;
+       else
+               f->row_addr_cycles = 2;
+
+       ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
+       ndcr |= (f->col_addr_cycles == 2) ? NDCR_RA_START : 0;
+       ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
+       ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
+       ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
+       ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
+
+       ndcr |= NDCR_RD_ID_CNT(f->read_id_bytes);
+       ndcr |= NDCR_SPARE_EN; /* enable spare by default */
+
+       info->reg_ndcr = ndcr;
+
+       pxa3xx_nand_set_timing(info, f->timing);
+       info->flash_info = f;
+       return 0;
+}
+
+static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info)
+{
+       struct pxa3xx_nand_flash *f;
+       uint32_t id;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) {
+
+               f = builtin_flash_types[i];
+
+               if (pxa3xx_nand_config_flash(info, f))
+                       continue;
+
+               if (__readid(info, &id))
+                       continue;
+
+               if (id == f->chip_id)
+                       return 0;
+       }
+
+       return -ENODEV;
+}
+
+/* the maximum possible buffer size for large page with OOB data
+ * is: 2048 + 64 = 2112 bytes, allocate a page here for both the
+ * data buffer and the DMA descriptor
+ */
+#define MAX_BUFF_SIZE  PAGE_SIZE
+
+static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
+{
+       struct platform_device *pdev = info->pdev;
+       int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc);
+
+       if (use_dma == 0) {
+               info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
+               if (info->data_buff == NULL)
+                       return -ENOMEM;
+               return 0;
+       }
+
+       info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
+                               &info->data_buff_phys, GFP_KERNEL);
+       if (info->data_buff == NULL) {
+               dev_err(&pdev->dev, "failed to allocate dma buffer\n");
+               return -ENOMEM;
+       }
+
+       info->data_buff_size = MAX_BUFF_SIZE;
+       info->data_desc = (void *)info->data_buff + data_desc_offset;
+       info->data_desc_addr = info->data_buff_phys + data_desc_offset;
+
+       info->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW,
+                               pxa3xx_nand_data_dma_irq, info);
+       if (info->data_dma_ch < 0) {
+               dev_err(&pdev->dev, "failed to request data dma\n");
+               dma_free_coherent(&pdev->dev, info->data_buff_size,
+                               info->data_buff, info->data_buff_phys);
+               return info->data_dma_ch;
+       }
+
+       return 0;
+}
+
+static struct nand_ecclayout hw_smallpage_ecclayout = {
+       .eccbytes = 6,
+       .eccpos = {8, 9, 10, 11, 12, 13 },
+       .oobfree = { {2, 6} }
+};
+
+static struct nand_ecclayout hw_largepage_ecclayout = {
+       .eccbytes = 24,
+       .eccpos = {
+               40, 41, 42, 43, 44, 45, 46, 47,
+               48, 49, 50, 51, 52, 53, 54, 55,
+               56, 57, 58, 59, 60, 61, 62, 63},
+       .oobfree = { {2, 38} }
+};
+
+static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
+                                struct pxa3xx_nand_info *info)
+{
+       struct pxa3xx_nand_flash *f = info->flash_info;
+       struct nand_chip *this = &info->nand_chip;
+
+       this->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0;
+
+       this->waitfunc          = pxa3xx_nand_waitfunc;
+       this->select_chip       = pxa3xx_nand_select_chip;
+       this->dev_ready         = pxa3xx_nand_dev_ready;
+       this->cmdfunc           = pxa3xx_nand_cmdfunc;
+       this->read_word         = pxa3xx_nand_read_word;
+       this->read_byte         = pxa3xx_nand_read_byte;
+       this->read_buf          = pxa3xx_nand_read_buf;
+       this->write_buf         = pxa3xx_nand_write_buf;
+       this->verify_buf        = pxa3xx_nand_verify_buf;
+
+       this->ecc.mode          = NAND_ECC_HW;
+       this->ecc.hwctl         = pxa3xx_nand_ecc_hwctl;
+       this->ecc.calculate     = pxa3xx_nand_ecc_calculate;
+       this->ecc.correct       = pxa3xx_nand_ecc_correct;
+       this->ecc.size          = f->page_size;
+
+       if (f->page_size == 2048)
+               this->ecc.layout = &hw_largepage_ecclayout;
+       else
+               this->ecc.layout = &hw_smallpage_ecclayout;
+
+       this->chip_delay = 25;
+}
+
+static int pxa3xx_nand_probe(struct platform_device *pdev)
+{
+       struct pxa3xx_nand_platform_data *pdata;
+       struct pxa3xx_nand_info *info;
+       struct nand_chip *this;
+       struct mtd_info *mtd;
+       struct resource *r;
+       int ret = 0, irq;
+
+       pdata = pdev->dev.platform_data;
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "no platform data defined\n");
+               return -ENODEV;
+       }
+
+       mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info),
+                       GFP_KERNEL);
+       if (!mtd) {
+               dev_err(&pdev->dev, "failed to allocate memory\n");
+               return -ENOMEM;
+       }
+
+       info = (struct pxa3xx_nand_info *)(&mtd[1]);
+       info->pdev = pdev;
+
+       this = &info->nand_chip;
+       mtd->priv = info;
+
+       info->clk = clk_get(&pdev->dev, "NANDCLK");
+       if (IS_ERR(info->clk)) {
+               dev_err(&pdev->dev, "failed to get nand clock\n");
+               ret = PTR_ERR(info->clk);
+               goto fail_free_mtd;
+       }
+       clk_enable(info->clk);
+
+       r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (r == NULL) {
+               dev_err(&pdev->dev, "no resource defined for data DMA\n");
+               ret = -ENXIO;
+               goto fail_put_clk;
+       }
+       info->drcmr_dat = r->start;
+
+       r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (r == NULL) {
+               dev_err(&pdev->dev, "no resource defined for command DMA\n");
+               ret = -ENXIO;
+               goto fail_put_clk;
+       }
+       info->drcmr_cmd = r->start;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "no IRQ resource defined\n");
+               ret = -ENXIO;
+               goto fail_put_clk;
+       }
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (r == NULL) {
+               dev_err(&pdev->dev, "no IO memory resource defined\n");
+               ret = -ENODEV;
+               goto fail_put_clk;
+       }
+
+       r = request_mem_region(r->start, r->end - r->start + 1, pdev->name);
+       if (r == NULL) {
+               dev_err(&pdev->dev, "failed to request memory resource\n");
+               ret = -EBUSY;
+               goto fail_put_clk;
+       }
+
+       info->mmio_base = ioremap(r->start, r->end - r->start + 1);
+       if (info->mmio_base == NULL) {
+               dev_err(&pdev->dev, "ioremap() failed\n");
+               ret = -ENODEV;
+               goto fail_free_res;
+       }
+
+       ret = pxa3xx_nand_init_buff(info);
+       if (ret)
+               goto fail_free_io;
+
+       ret = request_irq(IRQ_NAND, pxa3xx_nand_irq, IRQF_DISABLED,
+                               pdev->name, info);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to request IRQ\n");
+               goto fail_free_buf;
+       }
+
+       ret = pxa3xx_nand_detect_flash(info);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to detect flash\n");
+               ret = -ENODEV;
+               goto fail_free_irq;
+       }
+
+       pxa3xx_nand_init_mtd(mtd, info);
+
+       platform_set_drvdata(pdev, mtd);
+
+       if (nand_scan(mtd, 1)) {
+               dev_err(&pdev->dev, "failed to scan nand\n");
+               ret = -ENXIO;
+               goto fail_free_irq;
+       }
+
+       return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
+
+fail_free_irq:
+       free_irq(IRQ_NAND, info);
+fail_free_buf:
+       if (use_dma) {
+               pxa_free_dma(info->data_dma_ch);
+               dma_free_coherent(&pdev->dev, info->data_buff_size,
+                       info->data_buff, info->data_buff_phys);
+       } else
+               kfree(info->data_buff);
+fail_free_io:
+       iounmap(info->mmio_base);
+fail_free_res:
+       release_mem_region(r->start, r->end - r->start + 1);
+fail_put_clk:
+       clk_disable(info->clk);
+       clk_put(info->clk);
+fail_free_mtd:
+       kfree(mtd);
+       return ret;
+}
+
+static int pxa3xx_nand_remove(struct platform_device *pdev)
+{
+       struct mtd_info *mtd = platform_get_drvdata(pdev);
+       struct pxa3xx_nand_info *info = mtd->priv;
+
+       platform_set_drvdata(pdev, NULL);
+
+       del_mtd_device(mtd);
+       del_mtd_partitions(mtd);
+       free_irq(IRQ_NAND, info);
+       if (use_dma) {
+               pxa_free_dma(info->data_dma_ch);
+               dma_free_writecombine(&pdev->dev, info->data_buff_size,
+                               info->data_buff, info->data_buff_phys);
+       } else
+               kfree(info->data_buff);
+       kfree(mtd);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
+       struct pxa3xx_nand_info *info = mtd->priv;
+
+       if (info->state != STATE_READY) {
+               dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
+               return -EAGAIN;
+       }
+
+       return 0;
+}
+
+static int pxa3xx_nand_resume(struct platform_device *pdev)
+{
+       struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
+       struct pxa3xx_nand_info *info = mtd->priv;
+
+       clk_enable(info->clk);
+
+       return pxa3xx_nand_config_flash(info);
+}
+#else
+#define pxa3xx_nand_suspend    NULL
+#define pxa3xx_nand_resume     NULL
+#endif
+
+static struct platform_driver pxa3xx_nand_driver = {
+       .driver = {
+               .name   = "pxa3xx-nand",
+       },
+       .probe          = pxa3xx_nand_probe,
+       .remove         = pxa3xx_nand_remove,
+       .suspend        = pxa3xx_nand_suspend,
+       .resume         = pxa3xx_nand_resume,
+};
+
+static int __init pxa3xx_nand_init(void)
+{
+       return platform_driver_register(&pxa3xx_nand_driver);
+}
+module_init(pxa3xx_nand_init);
+
+static void __exit pxa3xx_nand_exit(void)
+{
+       platform_driver_unregister(&pxa3xx_nand_driver);
+}
+module_exit(pxa3xx_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PXA3xx NAND controller driver");
index 0f6ac250f434909708bb6a5206ceb1b5c6ae3fad..26f88215bc47d48c12ff9768da72829366d4ac76 100644 (file)
@@ -478,6 +478,7 @@ static int __init rtc_from4_init(void)
        struct nand_chip *this;
        unsigned short bcr1, bcr2, wcr2;
        int i;
+       int ret;
 
        /* Allocate memory for MTD device structure and private data */
        rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
@@ -537,6 +538,22 @@ static int __init rtc_from4_init(void)
        this->ecc.hwctl = rtc_from4_enable_hwecc;
        this->ecc.calculate = rtc_from4_calculate_ecc;
        this->ecc.correct = rtc_from4_correct_data;
+
+       /* We could create the decoder on demand, if memory is a concern.
+        * This way we have it handy, if an error happens
+        *
+        * Symbolsize is 10 (bits)
+        * Primitve polynomial is x^10+x^3+1
+        * first consecutive root is 0
+        * primitve element to generate roots = 1
+        * generator polinomial degree = 6
+        */
+       rs_decoder = init_rs(10, 0x409, 0, 1, 6);
+       if (!rs_decoder) {
+               printk(KERN_ERR "Could not create a RS decoder\n");
+               ret = -ENOMEM;
+               goto err_1;
+       }
 #else
        printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n");
 
@@ -549,8 +566,8 @@ static int __init rtc_from4_init(void)
 
        /* Scan to find existence of the device */
        if (nand_scan(rtc_from4_mtd, RTC_FROM4_MAX_CHIPS)) {
-               kfree(rtc_from4_mtd);
-               return -ENXIO;
+               ret = -ENXIO;
+               goto err_2;
        }
 
        /* Perform 'device recovery' for each chip in case there was a power loss. */
@@ -566,28 +583,19 @@ static int __init rtc_from4_init(void)
 #endif
 
        /* Register the partitions */
-       add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS);
+       ret = add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS);
+       if (ret)
+               goto err_3;
 
-#ifdef RTC_FROM4_HWECC
-       /* We could create the decoder on demand, if memory is a concern.
-        * This way we have it handy, if an error happens
-        *
-        * Symbolsize is 10 (bits)
-        * Primitve polynomial is x^10+x^3+1
-        * first consecutive root is 0
-        * primitve element to generate roots = 1
-        * generator polinomial degree = 6
-        */
-       rs_decoder = init_rs(10, 0x409, 0, 1, 6);
-       if (!rs_decoder) {
-               printk(KERN_ERR "Could not create a RS decoder\n");
-               nand_release(rtc_from4_mtd);
-               kfree(rtc_from4_mtd);
-               return -ENOMEM;
-       }
-#endif
        /* Return happy */
        return 0;
+err_3:
+       nand_release(rtc_from4_mtd);
+err_2:
+       free_rs(rs_decoder);
+err_1:
+       kfree(rtc_from4_mtd);
+       return ret;
 }
 
 module_init(rtc_from4_init);
index 9260ad947524f4f4a28959a3b843f48a8069c7f8..b34a460ab67915afe3812d6ced1410cfff6c16b7 100644 (file)
@@ -119,8 +119,7 @@ struct s3c2410_nand_info {
        void __iomem                    *sel_reg;
        int                             sel_bit;
        int                             mtd_count;
-
-       unsigned long                   save_nfconf;
+       unsigned long                   save_sel;
 
        enum s3c_cpu_type               cpu_type;
 };
@@ -358,6 +357,14 @@ static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
        if (diff0 == 0 && diff1 == 0 && diff2 == 0)
                return 0;               /* ECC is ok */
 
+       /* sometimes people do not think about using the ECC, so check
+        * to see if we have an 0xff,0xff,0xff read ECC and then ignore
+        * the error, on the assumption that this is an un-eccd page.
+        */
+       if (read_ecc[0] == 0xff && read_ecc[1] == 0xff && read_ecc[2] == 0xff
+           && info->platform->ignore_unset_ecc)
+               return 0;
+
        /* Can we correct this ECC (ie, one row and column change).
         * Note, this is similar to the 256 error code on smartmedia */
 
@@ -473,7 +480,7 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u
        ecc_code[1] = ecc >> 8;
        ecc_code[2] = ecc >> 16;
 
-       pr_debug("%s: returning ecc %06lx\n", __func__, ecc);
+       pr_debug("%s: returning ecc %06lx\n", __func__, ecc & 0xffffff);
 
        return 0;
 }
@@ -644,9 +651,6 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
                chip->ecc.calculate = s3c2410_nand_calculate_ecc;
                chip->ecc.correct   = s3c2410_nand_correct_data;
                chip->ecc.mode      = NAND_ECC_HW;
-               chip->ecc.size      = 512;
-               chip->ecc.bytes     = 3;
-               chip->ecc.layout    = &nand_hw_eccoob;
 
                switch (info->cpu_type) {
                case TYPE_S3C2410:
@@ -668,6 +672,40 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
        } else {
                chip->ecc.mode      = NAND_ECC_SOFT;
        }
+
+       if (set->ecc_layout != NULL)
+               chip->ecc.layout = set->ecc_layout;
+
+       if (set->disable_ecc)
+               chip->ecc.mode  = NAND_ECC_NONE;
+}
+
+/* s3c2410_nand_update_chip
+ *
+ * post-probe chip update, to change any items, such as the
+ * layout for large page nand
+ */
+
+static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
+                                    struct s3c2410_nand_mtd *nmtd)
+{
+       struct nand_chip *chip = &nmtd->chip;
+
+       printk("%s: chip %p: %d\n", __func__, chip, chip->page_shift);
+
+       if (hardware_ecc) {
+               /* change the behaviour depending on wether we are using
+                * the large or small page nand device */
+
+               if (chip->page_shift > 10) {
+                       chip->ecc.size      = 256;
+                       chip->ecc.bytes     = 3;
+               } else {
+                       chip->ecc.size      = 512;
+                       chip->ecc.bytes     = 3;
+                       chip->ecc.layout    = &nand_hw_eccoob;
+               }
+       }
 }
 
 /* s3c2410_nand_probe
@@ -776,9 +814,12 @@ static int s3c24xx_nand_probe(struct platform_device *pdev,
 
                s3c2410_nand_init_chip(info, nmtd, sets);
 
-               nmtd->scan_res = nand_scan(&nmtd->mtd, (sets) ? sets->nr_chips : 1);
+               nmtd->scan_res = nand_scan_ident(&nmtd->mtd,
+                                                (sets) ? sets->nr_chips : 1);
 
                if (nmtd->scan_res == 0) {
+                       s3c2410_nand_update_chip(info, nmtd);
+                       nand_scan_tail(&nmtd->mtd);
                        s3c2410_nand_add_partition(info, nmtd, sets);
                }
 
@@ -810,15 +851,14 @@ static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm)
        struct s3c2410_nand_info *info = platform_get_drvdata(dev);
 
        if (info) {
-               info->save_nfconf = readl(info->regs + S3C2410_NFCONF);
+               info->save_sel = readl(info->sel_reg);
 
                /* For the moment, we must ensure nFCE is high during
                 * the time we are suspended. This really should be
                 * handled by suspending the MTDs we are using, but
                 * that is currently not the case. */
 
-               writel(info->save_nfconf | info->sel_bit,
-                      info->regs + S3C2410_NFCONF);
+               writel(info->save_sel | info->sel_bit, info->sel_reg);
 
                if (!allow_clk_stop(info))
                        clk_disable(info->clk);
@@ -830,7 +870,7 @@ static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm)
 static int s3c24xx_nand_resume(struct platform_device *dev)
 {
        struct s3c2410_nand_info *info = platform_get_drvdata(dev);
-       unsigned long nfconf;
+       unsigned long sel;
 
        if (info) {
                clk_enable(info->clk);
@@ -838,10 +878,10 @@ static int s3c24xx_nand_resume(struct platform_device *dev)
 
                /* Restore the state of the nFCE line. */
 
-               nfconf = readl(info->regs + S3C2410_NFCONF);
-               nfconf &= ~info->sel_bit;
-               nfconf |= info->save_nfconf & info->sel_bit;
-               writel(nfconf, info->regs + S3C2410_NFCONF);
+               sel = readl(info->sel_reg);
+               sel &= ~info->sel_bit;
+               sel |= info->save_sel & info->sel_bit;
+               writel(sel, info->sel_reg);
 
                if (allow_clk_stop(info))
                        clk_disable(info->clk);
@@ -927,3 +967,6 @@ module_exit(s3c2410_nand_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("S3C24XX MTD NAND driver");
+MODULE_ALIAS("platform:s3c2410-nand");
+MODULE_ALIAS("platform:s3c2412-nand");
+MODULE_ALIAS("platform:s3c2440-nand");
index 0513cbc8834d66b78d7e0c85d1f6532447048044..345e6eff89ce5929c3548d1874b6363b102ae554 100644 (file)
 
 char nftlmountrev[]="$Revision: 1.41 $";
 
-extern int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
-                        size_t *retlen, uint8_t *buf);
-extern int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
-                         size_t *retlen, uint8_t *buf);
-
 /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the
  *     various device information of the NFTL partition and Bad Unit Table. Update
  *     the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[]
index f86e06934cd8d2cb37b64e5c5064ab5125a60978..4f80c2fd89af71a0a0c9e5bae77c013a663a4c7b 100644 (file)
@@ -72,3 +72,5 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
        return nr_parts;
 }
 EXPORT_SYMBOL(of_mtd_parse_partitions);
+
+MODULE_LICENSE("GPL");
index 8d7d21be1541867aca5a494b3965d49c6316c0bd..5d7965f7e9ce6a3f8232a53cb2c0e2a243f13379 100644 (file)
@@ -329,6 +329,21 @@ static int onenand_wait(struct mtd_info *mtd, int state)
                printk(KERN_ERR "onenand_wait: controller error = 0x%04x\n", ctrl);
                if (ctrl & ONENAND_CTRL_LOCK)
                        printk(KERN_ERR "onenand_wait: it's locked error.\n");
+               if (state == FL_READING) {
+                       /*
+                        * A power loss while writing can result in a page
+                        * becoming unreadable.  When the device is mounted
+                        * again, reading that page gives controller errors.
+                        * Upper level software like JFFS2 treat -EIO as fatal,
+                        * refusing to mount at all.  That means it is necessary
+                        * to treat the error as an ECC error to allow recovery.
+                        * Note that typically in this case, the eraseblock can
+                        * still be erased and rewritten i.e. it has not become
+                        * a bad block.
+                        */
+                       mtd->ecc_stats.failed++;
+                       return -EBADMSG;
+               }
                return -EIO;
        }
 
@@ -1336,7 +1351,7 @@ static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
        }
 
        /* Reject writes, which are not page aligned */
-        if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
+        if (unlikely(NOTALIGNED(to) || NOTALIGNED(len))) {
                 printk(KERN_ERR "onenand_panic_write: Attempt to write not page aligned data\n");
                 return -EINVAL;
         }
@@ -1466,7 +1481,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
        }
 
        /* Reject writes, which are not page aligned */
-        if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
+        if (unlikely(NOTALIGNED(to) || NOTALIGNED(len))) {
                 printk(KERN_ERR "onenand_write_ops_nolock: Attempt to write not page aligned data\n");
                 return -EINVAL;
         }
@@ -2052,7 +2067,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
  *
  * Check lock status
  */
-static void onenand_check_lock_status(struct onenand_chip *this)
+static int onenand_check_lock_status(struct onenand_chip *this)
 {
        unsigned int value, block, status;
        unsigned int end;
@@ -2070,9 +2085,13 @@ static void onenand_check_lock_status(struct onenand_chip *this)
 
                /* Check lock status */
                status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
-               if (!(status & ONENAND_WP_US))
+               if (!(status & ONENAND_WP_US)) {
                        printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status);
+                       return 0;
+               }
        }
+
+       return 1;
 }
 
 /**
@@ -2081,9 +2100,11 @@ static void onenand_check_lock_status(struct onenand_chip *this)
  *
  * Unlock all blocks
  */
-static int onenand_unlock_all(struct mtd_info *mtd)
+static void onenand_unlock_all(struct mtd_info *mtd)
 {
        struct onenand_chip *this = mtd->priv;
+       loff_t ofs = 0;
+       size_t len = this->chipsize;
 
        if (this->options & ONENAND_HAS_UNLOCK_ALL) {
                /* Set start block address */
@@ -2099,23 +2120,19 @@ static int onenand_unlock_all(struct mtd_info *mtd)
                    & ONENAND_CTRL_ONGO)
                        continue;
 
+               /* Check lock status */
+               if (onenand_check_lock_status(this))
+                       return;
+
                /* Workaround for all block unlock in DDP */
                if (ONENAND_IS_DDP(this)) {
-                       /* 1st block on another chip */
-                       loff_t ofs = this->chipsize >> 1;
-                       size_t len = mtd->erasesize;
-
-                       onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
+                       /* All blocks on another chip */
+                       ofs = this->chipsize >> 1;
+                       len = this->chipsize >> 1;
                }
-
-               onenand_check_lock_status(this);
-
-               return 0;
        }
 
-       onenand_do_lock_cmd(mtd, 0x0, this->chipsize, ONENAND_CMD_UNLOCK);
-
-       return 0;
+       onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
 }
 
 #ifdef CONFIG_MTD_ONENAND_OTP
index aecdd50a1781354556c9948ed86b4a1f09e52c36..2f53b51c68054cb5a11aa17bf9646c56c7d975e3 100644 (file)
@@ -17,9 +17,6 @@
 #include <linux/mtd/onenand.h>
 #include <linux/mtd/compatmac.h>
 
-extern int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
-                               struct mtd_oob_ops *ops);
-
 /**
  * check_short_pattern - [GENERIC] check if a pattern is in the buffer
  * @param buf          the buffer to search
index 823fba4e6d2fa99c5c5ea2049edd820c9fda1c5c..c84e45465499dba5ad0117c1fc213b4104705171 100644 (file)
@@ -823,7 +823,7 @@ static void rfd_ftl_remove_dev(struct mtd_blktrans_dev *dev)
        kfree(part);
 }
 
-struct mtd_blktrans_ops rfd_ftl_tr = {
+static struct mtd_blktrans_ops rfd_ftl_tr = {
        .name           = "rfd",
        .major          = RFD_FTL_MAJOR,
        .part_bits      = PART_BITS,
index b9daf159a4a721a0228a59203309120930468ac1..3f063108e95fe3f987c9bdaa8e3a8f2c9255c402 100644 (file)
@@ -24,8 +24,13 @@ config MTD_UBI_WL_THRESHOLD
          erase counter value and the lowest erase counter value of eraseblocks
          of UBI devices. When this threshold is exceeded, UBI starts performing
          wear leveling by means of moving data from eraseblock with low erase
-         counter to eraseblocks with high erase counter. Leave the default
-         value if unsure.
+         counter to eraseblocks with high erase counter.
+
+         The default value should be OK for SLC NAND flashes, NOR flashes and
+         other flashes which have eraseblock life-cycle 100000 or more.
+         However, in case of MLC NAND flashes which typically have eraseblock
+         life-cycle less then 10000, the threshold should be lessened (e.g.,
+         to 128 or 256, although it does not have to be power of 2).
 
 config MTD_UBI_BEB_RESERVE
        int "Percentage of reserved eraseblocks for bad eraseblocks handling"
index 2759604629703e6ea9d9c2e6735478a9cd5a9e1c..961416ac06167350bf689c631a85b0ece7f067ec 100644 (file)
@@ -606,8 +606,16 @@ static int io_init(struct ubi_device *ubi)
                ubi->ro_mode = 1;
        }
 
-       dbg_msg("leb_size         %d", ubi->leb_size);
-       dbg_msg("ro_mode          %d", ubi->ro_mode);
+       ubi_msg("physical eraseblock size:   %d bytes (%d KiB)",
+               ubi->peb_size, ubi->peb_size >> 10);
+       ubi_msg("logical eraseblock size:    %d bytes", ubi->leb_size);
+       ubi_msg("smallest flash I/O unit:    %d", ubi->min_io_size);
+       if (ubi->hdrs_min_io_size != ubi->min_io_size)
+               ubi_msg("sub-page size:              %d",
+                       ubi->hdrs_min_io_size);
+       ubi_msg("VID header offset:          %d (aligned %d)",
+               ubi->vid_hdr_offset, ubi->vid_hdr_aloffset);
+       ubi_msg("data offset:                %d", ubi->leb_start);
 
        /*
         * Note, ideally, we have to initialize ubi->bad_peb_count here. But
@@ -755,8 +763,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
        mutex_init(&ubi->volumes_mutex);
        spin_lock_init(&ubi->volumes_lock);
 
-       dbg_msg("attaching mtd%d to ubi%d: VID header offset %d",
-               mtd->index, ubi_num, vid_hdr_offset);
+       ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
 
        err = io_init(ubi);
        if (err)
@@ -804,15 +811,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
        ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi_num);
        ubi_msg("MTD device name:            \"%s\"", mtd->name);
        ubi_msg("MTD device size:            %llu MiB", ubi->flash_size >> 20);
-       ubi_msg("physical eraseblock size:   %d bytes (%d KiB)",
-               ubi->peb_size, ubi->peb_size >> 10);
-       ubi_msg("logical eraseblock size:    %d bytes", ubi->leb_size);
        ubi_msg("number of good PEBs:        %d", ubi->good_peb_count);
        ubi_msg("number of bad PEBs:         %d", ubi->bad_peb_count);
-       ubi_msg("smallest flash I/O unit:    %d", ubi->min_io_size);
-       ubi_msg("VID header offset:          %d (aligned %d)",
-               ubi->vid_hdr_offset, ubi->vid_hdr_aloffset);
-       ubi_msg("data offset:                %d", ubi->leb_start);
        ubi_msg("max. allowed volumes:       %d", ubi->vtbl_slots);
        ubi_msg("wear-leveling threshold:    %d", CONFIG_MTD_UBI_WL_THRESHOLD);
        ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT);
@@ -950,8 +950,7 @@ static int __init ubi_init(void)
        BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64);
 
        if (mtd_devs > UBI_MAX_DEVICES) {
-               printk(KERN_ERR "UBI error: too many MTD devices, "
-                      "maximum is %d\n", UBI_MAX_DEVICES);
+               ubi_err("too many MTD devices, maximum is %d", UBI_MAX_DEVICES);
                return -EINVAL;
        }
 
@@ -959,25 +958,25 @@ static int __init ubi_init(void)
        ubi_class = class_create(THIS_MODULE, UBI_NAME_STR);
        if (IS_ERR(ubi_class)) {
                err = PTR_ERR(ubi_class);
-               printk(KERN_ERR "UBI error: cannot create UBI class\n");
+               ubi_err("cannot create UBI class");
                goto out;
        }
 
        err = class_create_file(ubi_class, &ubi_version);
        if (err) {
-               printk(KERN_ERR "UBI error: cannot create sysfs file\n");
+               ubi_err("cannot create sysfs file");
                goto out_class;
        }
 
        err = misc_register(&ubi_ctrl_cdev);
        if (err) {
-               printk(KERN_ERR "UBI error: cannot register device\n");
+               ubi_err("cannot register device");
                goto out_version;
        }
 
        ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab",
-                                               sizeof(struct ubi_wl_entry),
-                                               0, 0, NULL);
+                                             sizeof(struct ubi_wl_entry),
+                                             0, 0, NULL);
        if (!ubi_wl_entry_slab)
                goto out_dev_unreg;
 
@@ -1000,8 +999,7 @@ static int __init ubi_init(void)
                mutex_unlock(&ubi_devices_mutex);
                if (err < 0) {
                        put_mtd_device(mtd);
-                       printk(KERN_ERR "UBI error: cannot attach mtd%d\n",
-                              mtd->index);
+                       ubi_err("cannot attach mtd%d", mtd->index);
                        goto out_detach;
                }
        }
@@ -1023,7 +1021,7 @@ out_version:
 out_class:
        class_destroy(ubi_class);
 out:
-       printk(KERN_ERR "UBI error: cannot initialize UBI, error %d\n", err);
+       ubi_err("UBI error: cannot initialize UBI, error %d", err);
        return err;
 }
 module_init(ubi_init);
index 51c40b17f1ec5c967994666ad0f7f3ce4b689f39..8ea99d8c9e1f0459862b77bbd54918e3b68bf88a 100644 (file)
@@ -41,7 +41,7 @@
 /* Generic debugging message */
 #define dbg_msg(fmt, ...)                                    \
        printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \
-              current->pid, __FUNCTION__, ##__VA_ARGS__)
+              current->pid, __func__, ##__VA_ARGS__)
 
 #define ubi_dbg_dump_stack() dump_stack()
 
@@ -99,8 +99,10 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
 #ifdef CONFIG_MTD_UBI_DEBUG_MSG_BLD
 /* Initialization and build messages */
 #define dbg_bld(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
+#define UBI_IO_DEBUG 1
 #else
 #define dbg_bld(fmt, ...) ({})
+#define UBI_IO_DEBUG 0
 #endif
 
 #ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS
index d397219238d3b8ede00b4075b1468c1922963d79..e909b390069a263e63d5d80a9a8bdf239644fb9f 100644 (file)
@@ -291,11 +291,12 @@ int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol)
        /*
         * In case of dynamic volume, MTD device size is just volume size. In
         * case of a static volume the size is equivalent to the amount of data
-        * bytes, which is zero at this moment and will be changed after volume
-        * update.
+        * bytes.
         */
        if (vol->vol_type == UBI_DYNAMIC_VOLUME)
                mtd->size = vol->usable_leb_size * vol->reserved_pebs;
+       else
+               mtd->size = vol->used_bytes;
 
        if (add_mtd_device(mtd)) {
                ubi_err("cannot not add MTD device\n");
index db3efdef2433884eccc04ad03a9de9d63f4d9af2..4ac11df7b048d3a24684744c4f399f13b81653ea 100644 (file)
@@ -631,6 +631,8 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
 
        dbg_io("read EC header from PEB %d", pnum);
        ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
+       if (UBI_IO_DEBUG)
+               verbose = 1;
 
        err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
        if (err) {
@@ -904,6 +906,8 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
 
        dbg_io("read VID header from PEB %d", pnum);
        ubi_assert(pnum >= 0 &&  pnum < ubi->peb_count);
+       if (UBI_IO_DEBUG)
+               verbose = 1;
 
        p = (char *)vid_hdr - ubi->vid_hdr_shift;
        err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
index 05aa3e7daba1edefb88a3b97befb6d4f717fc25c..96d410e106ab1cb72cf9f6bda211e756eaa8c98d 100644 (file)
@@ -42,6 +42,7 @@
 
 #include <linux/err.h>
 #include <linux/crc32.h>
+#include <asm/div64.h>
 #include "ubi.h"
 
 #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
@@ -91,27 +92,6 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
        return 0;
 }
 
-/**
- * commit_to_mean_value - commit intermediate results to the final mean erase
- * counter value.
- * @si: scanning information
- *
- * This is a helper function which calculates partial mean erase counter mean
- * value and adds it to the resulting mean value. As we can work only in
- * integer arithmetic and we want to calculate the mean value of erase counter
- * accurately, we first sum erase counter values in @si->ec_sum variable and
- * count these components in @si->ec_count. If this temporary @si->ec_sum is
- * going to overflow, we calculate the partial mean value
- * (@si->ec_sum/@si->ec_count) and add it to @si->mean_ec.
- */
-static void commit_to_mean_value(struct ubi_scan_info *si)
-{
-       si->ec_sum /= si->ec_count;
-       if (si->ec_sum % si->ec_count >= si->ec_count / 2)
-               si->mean_ec += 1;
-       si->mean_ec += si->ec_sum;
-}
-
 /**
  * validate_vid_hdr - check that volume identifier header is correct and
  * consistent.
@@ -901,15 +881,8 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum
 
 adjust_mean_ec:
        if (!ec_corr) {
-               if (si->ec_sum + ec < ec) {
-                       commit_to_mean_value(si);
-                       si->ec_sum = 0;
-                       si->ec_count = 0;
-               } else {
-                       si->ec_sum += ec;
-                       si->ec_count += 1;
-               }
-
+               si->ec_sum += ec;
+               si->ec_count += 1;
                if (ec > si->max_ec)
                        si->max_ec = ec;
                if (ec < si->min_ec)
@@ -965,9 +938,11 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
 
        dbg_msg("scanning is finished");
 
-       /* Finish mean erase counter calculations */
-       if (si->ec_count)
-               commit_to_mean_value(si);
+       /* Calculate mean erase counter */
+       if (si->ec_count) {
+               do_div(si->ec_sum, si->ec_count);
+               si->mean_ec = si->ec_sum;
+       }
 
        if (si->is_empty)
                ubi_msg("empty MTD device detected");
index 46d444af471a24a094fc3c0aa54d76e91dda94bd..966b9b682a423819921f69ca02e626ad0c89772b 100644 (file)
@@ -124,7 +124,7 @@ struct ubi_scan_info {
        int max_ec;
        unsigned long long max_sqnum;
        int mean_ec;
-       int ec_sum;
+       uint64_t ec_sum;
        int ec_count;
 };
 
similarity index 99%
rename from include/mtd/ubi-header.h
rename to drivers/mtd/ubi/ubi-media.h
index 292f916ea5642178947204ba04a1d0f2d5b26c64..c3185d9fd048836dfd09c52e266e1875e9571337 100644 (file)
 
 /*
  * This file defines the layout of UBI headers and all the other UBI on-flash
- * data structures. May be included by user-space.
+ * data structures.
  */
 
-#ifndef __UBI_HEADER_H__
-#define __UBI_HEADER_H__
+#ifndef __UBI_MEDIA_H__
+#define __UBI_MEDIA_H__
 
 #include <asm/byteorder.h>
 
@@ -369,4 +369,4 @@ struct ubi_vtbl_record {
        __be32  crc;
 } __attribute__ ((packed));
 
-#endif /* !__UBI_HEADER_H__ */
+#endif /* !__UBI_MEDIA_H__ */
index a548c1d28fa818a5485aa5524a2527eff269edf0..67dcbd11c15c27c10cfd4349ede90c96ec11ea59 100644 (file)
 #include <linux/string.h>
 #include <linux/vmalloc.h>
 #include <linux/mtd/mtd.h>
-
-#include <mtd/ubi-header.h>
 #include <linux/mtd/ubi.h>
 
+#include "ubi-media.h"
 #include "scan.h"
 #include "debug.h"
 
 #define ubi_msg(fmt, ...) printk(KERN_NOTICE "UBI: " fmt "\n", ##__VA_ARGS__)
 /* UBI warning messages */
 #define ubi_warn(fmt, ...) printk(KERN_WARNING "UBI warning: %s: " fmt "\n", \
-                                 __FUNCTION__, ##__VA_ARGS__)
+                                 __func__, ##__VA_ARGS__)
 /* UBI error messages */
 #define ubi_err(fmt, ...) printk(KERN_ERR "UBI error: %s: " fmt "\n", \
-                                __FUNCTION__, ##__VA_ARGS__)
+                                __func__, ##__VA_ARGS__)
 
 /* Lowest number PEBs reserved for bad PEB handling */
 #define MIN_RESEVED_PEBS 2
index 015e163259738af5ba3e74dfd69da9bda5d350f2..8082c1d142df7e4c15982a40436c9e2110723644 100644 (file)
@@ -2011,7 +2011,7 @@ config E1000_DISABLE_PACKET_SPLIT
 
 config E1000E
        tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"
-       depends on PCI
+       depends on PCI && (!SPARC32 || BROKEN)
        ---help---
          This driver supports the PCI-Express Intel(R) PRO/1000 gigabit
          ethernet family of adapters. For PCI or PCI-X e1000 adapters,
@@ -2278,6 +2278,7 @@ config TSI108_ETH
 config GELIC_NET
        tristate "PS3 Gigabit Ethernet driver"
        depends on PPC_PS3
+       select PS3_SYS_MANAGER
        help
          This driver supports the network device on the PS3 game
          console.  This driver has built-in support for Ethernet.
index ba6bd03a015ff6afad60ae65d8c614b35a6671d4..a637910b02dd74766f4c79ebed4385dea8fb18f4 100644 (file)
@@ -693,11 +693,15 @@ static int __init am79c961_probe(struct platform_device *pdev)
         * done by the ether bootp loader.
         */
        dev->base_addr = res->start;
-       dev->irq = platform_get_irq(pdev, 0);
+       ret = platform_get_irq(pdev, 0);
 
-       ret = -ENODEV;
-       if (dev->irq < 0)
+       if (ret < 0) {
+               ret = -ENODEV;
                goto nodev;
+       }
+       dev->irq = ret;
+
+       ret = -ENODEV;
        if (!request_region(dev->base_addr, 0x18, dev->name))
                goto nodev;
 
index 978e20a1791bda8239cbc213b0e0afebab4461b4..1e39e78f1778c5228d7e6345005e900a347ccbff 100644 (file)
@@ -1248,3 +1248,4 @@ module_exit(at91ether_exit)
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver");
 MODULE_AUTHOR("Andrew Victor");
+MODULE_ALIAS("platform:" DRV_NAME);
index 91a6590d107b181177a74e0bcd71003e9c4a906c..ecd8fc6146e9faa710351eb8765c8538807bcc51 100644 (file)
@@ -897,6 +897,7 @@ static struct platform_driver ep93xx_eth_driver = {
        .remove         = ep93xx_eth_remove,
        .driver         = {
                .name   = "ep93xx-eth",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -914,3 +915,4 @@ static void __exit ep93xx_eth_cleanup_module(void)
 module_init(ep93xx_eth_init_module);
 module_exit(ep93xx_eth_cleanup_module);
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ep93xx-eth");
index 5586fc62468880a0df991cd72d461bf6e5ab77a3..0afe522b8f7b901e2a078ff33739a0a9866299c3 100644 (file)
 /* Temporary hack for merging atl1 and atl2 */
 #include "atlx.c"
 
+/*
+ * This is the only thing that needs to be changed to adjust the
+ * maximum number of ports that the driver can manage.
+ */
+#define ATL1_MAX_NIC 4
+
+#define OPTION_UNSET    -1
+#define OPTION_DISABLED 0
+#define OPTION_ENABLED  1
+
+#define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET }
+
+/*
+ * Interrupt Moderate Timer in units of 2 us
+ *
+ * Valid Range: 10-65535
+ *
+ * Default Value: 100 (200us)
+ */
+static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
+static int num_int_mod_timer;
+module_param_array_named(int_mod_timer, int_mod_timer, int,
+       &num_int_mod_timer, 0);
+MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer");
+
+#define DEFAULT_INT_MOD_CNT    100     /* 200us */
+#define MAX_INT_MOD_CNT                65000
+#define MIN_INT_MOD_CNT                50
+
+struct atl1_option {
+       enum { enable_option, range_option, list_option } type;
+       char *name;
+       char *err;
+       int def;
+       union {
+               struct {        /* range_option info */
+                       int min;
+                       int max;
+               } r;
+               struct {        /* list_option info */
+                       int nr;
+                       struct atl1_opt_list {
+                               int i;
+                               char *str;
+                       } *p;
+               } l;
+       } arg;
+};
+
+static int __devinit atl1_validate_option(int *value, struct atl1_option *opt,
+       struct pci_dev *pdev)
+{
+       if (*value == OPTION_UNSET) {
+               *value = opt->def;
+               return 0;
+       }
+
+       switch (opt->type) {
+       case enable_option:
+               switch (*value) {
+               case OPTION_ENABLED:
+                       dev_info(&pdev->dev, "%s enabled\n", opt->name);
+                       return 0;
+               case OPTION_DISABLED:
+                       dev_info(&pdev->dev, "%s disabled\n", opt->name);
+                       return 0;
+               }
+               break;
+       case range_option:
+               if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+                       dev_info(&pdev->dev, "%s set to %i\n", opt->name,
+                               *value);
+                       return 0;
+               }
+               break;
+       case list_option:{
+                       int i;
+                       struct atl1_opt_list *ent;
+
+                       for (i = 0; i < opt->arg.l.nr; i++) {
+                               ent = &opt->arg.l.p[i];
+                               if (*value == ent->i) {
+                                       if (ent->str[0] != '\0')
+                                               dev_info(&pdev->dev, "%s\n",
+                                                       ent->str);
+                                       return 0;
+                               }
+                       }
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       dev_info(&pdev->dev, "invalid %s specified (%i) %s\n",
+               opt->name, *value, opt->err);
+       *value = opt->def;
+       return -1;
+}
+
+/*
+ * atl1_check_options - Range Checking for Command Line Parameters
+ * @adapter: board private structure
+ *
+ * This routine checks all command line parameters for valid user
+ * input.  If an invalid value is given, or if no user specified
+ * value exists, a default value is used.  The final value is stored
+ * in a variable in the adapter structure.
+ */
+void __devinit atl1_check_options(struct atl1_adapter *adapter)
+{
+       struct pci_dev *pdev = adapter->pdev;
+       int bd = adapter->bd_number;
+       if (bd >= ATL1_MAX_NIC) {
+               dev_notice(&pdev->dev, "no configuration for board#%i\n", bd);
+               dev_notice(&pdev->dev, "using defaults for all values\n");
+       }
+       {                       /* Interrupt Moderate Timer */
+               struct atl1_option opt = {
+                       .type = range_option,
+                       .name = "Interrupt Moderator Timer",
+                       .err = "using default of "
+                               __MODULE_STRING(DEFAULT_INT_MOD_CNT),
+                       .def = DEFAULT_INT_MOD_CNT,
+                       .arg = {.r = {.min = MIN_INT_MOD_CNT,
+                                       .max = MAX_INT_MOD_CNT} }
+               };
+               int val;
+               if (num_int_mod_timer > bd) {
+                       val = int_mod_timer[bd];
+                       atl1_validate_option(&val, &opt, pdev);
+                       adapter->imt = (u16) val;
+               } else
+                       adapter->imt = (u16) (opt.def);
+       }
+}
+
 /*
  * atl1_pci_tbl - PCI Device ID Table
  */
index 4186326d1b9426d5c4f00c5324daf2919ceffeed..f06b854e2501b88ed7f3799bc53438357876add4 100644 (file)
@@ -253,181 +253,4 @@ static void atlx_restore_vlan(struct atlx_adapter *adapter)
        atlx_vlan_rx_register(adapter->netdev, adapter->vlgrp);
 }
 
-/*
- * This is the only thing that needs to be changed to adjust the
- * maximum number of ports that the driver can manage.
- */
-#define ATL1_MAX_NIC 4
-
-#define OPTION_UNSET    -1
-#define OPTION_DISABLED 0
-#define OPTION_ENABLED  1
-
-#define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET }
-
-/*
- * Interrupt Moderate Timer in units of 2 us
- *
- * Valid Range: 10-65535
- *
- * Default Value: 100 (200us)
- */
-static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
-static int num_int_mod_timer;
-module_param_array_named(int_mod_timer, int_mod_timer, int,
-       &num_int_mod_timer, 0);
-MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer");
-
-/*
- * flash_vendor
- *
- * Valid Range: 0-2
- *
- * 0 - Atmel
- * 1 - SST
- * 2 - ST
- *
- * Default Value: 0
- */
-static int __devinitdata flash_vendor[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
-static int num_flash_vendor;
-module_param_array_named(flash_vendor, flash_vendor, int, &num_flash_vendor, 0);
-MODULE_PARM_DESC(flash_vendor, "SPI flash vendor");
-
-#define DEFAULT_INT_MOD_CNT    100     /* 200us */
-#define MAX_INT_MOD_CNT                65000
-#define MIN_INT_MOD_CNT                50
-
-#define FLASH_VENDOR_DEFAULT   0
-#define FLASH_VENDOR_MIN       0
-#define FLASH_VENDOR_MAX       2
-
-struct atl1_option {
-       enum { enable_option, range_option, list_option } type;
-       char *name;
-       char *err;
-       int def;
-       union {
-               struct {        /* range_option info */
-                       int min;
-                       int max;
-               } r;
-               struct {        /* list_option info */
-                       int nr;
-                       struct atl1_opt_list {
-                               int i;
-                               char *str;
-                       } *p;
-               } l;
-       } arg;
-};
-
-static int __devinit atl1_validate_option(int *value, struct atl1_option *opt,
-       struct pci_dev *pdev)
-{
-       if (*value == OPTION_UNSET) {
-               *value = opt->def;
-               return 0;
-       }
-
-       switch (opt->type) {
-       case enable_option:
-               switch (*value) {
-               case OPTION_ENABLED:
-                       dev_info(&pdev->dev, "%s enabled\n", opt->name);
-                       return 0;
-               case OPTION_DISABLED:
-                       dev_info(&pdev->dev, "%s disabled\n", opt->name);
-                       return 0;
-               }
-               break;
-       case range_option:
-               if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
-                       dev_info(&pdev->dev, "%s set to %i\n", opt->name,
-                               *value);
-                       return 0;
-               }
-               break;
-       case list_option:{
-                       int i;
-                       struct atl1_opt_list *ent;
-
-                       for (i = 0; i < opt->arg.l.nr; i++) {
-                               ent = &opt->arg.l.p[i];
-                               if (*value == ent->i) {
-                                       if (ent->str[0] != '\0')
-                                               dev_info(&pdev->dev, "%s\n",
-                                                       ent->str);
-                                       return 0;
-                               }
-                       }
-               }
-               break;
-
-       default:
-               break;
-       }
-
-       dev_info(&pdev->dev, "invalid %s specified (%i) %s\n",
-               opt->name, *value, opt->err);
-       *value = opt->def;
-       return -1;
-}
-
-/*
- * atl1_check_options - Range Checking for Command Line Parameters
- * @adapter: board private structure
- *
- * This routine checks all command line parameters for valid user
- * input.  If an invalid value is given, or if no user specified
- * value exists, a default value is used.  The final value is stored
- * in a variable in the adapter structure.
- */
-void __devinit atl1_check_options(struct atl1_adapter *adapter)
-{
-       struct pci_dev *pdev = adapter->pdev;
-       int bd = adapter->bd_number;
-       if (bd >= ATL1_MAX_NIC) {
-               dev_notice(&pdev->dev, "no configuration for board#%i\n", bd);
-               dev_notice(&pdev->dev, "using defaults for all values\n");
-       }
-       {                       /* Interrupt Moderate Timer */
-               struct atl1_option opt = {
-                       .type = range_option,
-                       .name = "Interrupt Moderator Timer",
-                       .err = "using default of "
-                               __MODULE_STRING(DEFAULT_INT_MOD_CNT),
-                       .def = DEFAULT_INT_MOD_CNT,
-                       .arg = {.r = {.min = MIN_INT_MOD_CNT,
-                                       .max = MAX_INT_MOD_CNT} }
-               };
-               int val;
-               if (num_int_mod_timer > bd) {
-                       val = int_mod_timer[bd];
-                       atl1_validate_option(&val, &opt, pdev);
-                       adapter->imt = (u16) val;
-               } else
-                       adapter->imt = (u16) (opt.def);
-       }
-
-       {                       /* Flash Vendor */
-               struct atl1_option opt = {
-                       .type = range_option,
-                       .name = "SPI Flash Vendor",
-                       .err = "using default of "
-                               __MODULE_STRING(FLASH_VENDOR_DEFAULT),
-                       .def = DEFAULT_INT_MOD_CNT,
-                       .arg = {.r = {.min = FLASH_VENDOR_MIN,
-                                       .max = FLASH_VENDOR_MAX} }
-               };
-               int val;
-               if (num_flash_vendor > bd) {
-                       val = flash_vendor[bd];
-                       atl1_validate_option(&val, &opt, pdev);
-                       adapter->hw.flash_vendor = (u8) val;
-               } else
-                       adapter->hw.flash_vendor = (u8) (opt.def);
-       }
-}
-
 #endif /* ATLX_C */
index 194949afacd05142655f7d1a42e00b8b894f6697..0b4adf4a0f7da9ab772ca84bc1d4738ca034c263 100644 (file)
@@ -1005,3 +1005,4 @@ module_exit(axdrv_exit);
 MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:ax88796");
index 717dcc1aa1e97acb8bfddf2e44e97cc51cb8a8f7..4fec8581bfd7bb80e5c7a49ae7c548532f263cf7 100644 (file)
@@ -47,6 +47,7 @@
 MODULE_AUTHOR(DRV_AUTHOR);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION(DRV_DESC);
+MODULE_ALIAS("platform:bfin_mac");
 
 #if defined(CONFIG_BFIN_MAC_USE_L1)
 # define bfin_mac_alloc(dma_handle, size)  l1_data_sram_zalloc(size)
@@ -1089,8 +1090,9 @@ static struct platform_driver bfin_mac_driver = {
        .resume = bfin_mac_resume,
        .suspend = bfin_mac_suspend,
        .driver = {
-                  .name = DRV_NAME,
-                  },
+               .name = DRV_NAME,
+               .owner  = THIS_MODULE,
+       },
 };
 
 static int __init bfin_mac_init(void)
@@ -1106,3 +1108,4 @@ static void __exit bfin_mac_cleanup(void)
 }
 
 module_exit(bfin_mac_cleanup);
+
index 9da7ff437031fec11854152851c344608ec183ff..2b5740b3d1825dee5b91f9b3862060e71c266f8b 100644 (file)
@@ -42,6 +42,7 @@
 MODULE_AUTHOR("Eugene Konev <ejka@imfi.kspu.ru>");
 MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:cpmac");
 
 static int debug_level = 8;
 static int dumb_switch;
@@ -1103,6 +1104,7 @@ static int __devexit cpmac_remove(struct platform_device *pdev)
 
 static struct platform_driver cpmac_driver = {
        .driver.name = "cpmac",
+       .driver.owner = THIS_MODULE,
        .probe = cpmac_probe,
        .remove = __devexit_p(cpmac_remove),
 };
index d63cc93f055dfd2be2c8a493a514b20a743fd9fa..e6fe2614ea6dc3a9f2db6928cce6393b75498475 100644 (file)
@@ -1418,3 +1418,4 @@ module_exit(dm9000_cleanup);
 MODULE_AUTHOR("Sascha Hauer, Ben Dooks");
 MODULE_DESCRIPTION("Davicom DM9000 network driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:dm9000");
index 01c88664bad30934e11d3c7ad9d4164d8e73bf7e..462351ca2c81ac991a088b971a0bc46b1f51c5a7 100644 (file)
@@ -1326,12 +1326,10 @@ struct e1000_info e1000_82571_info = {
        .mac                    = e1000_82571,
        .flags                  = FLAG_HAS_HW_VLAN_FILTER
                                  | FLAG_HAS_JUMBO_FRAMES
-                                 | FLAG_HAS_STATS_PTC_PRC
                                  | FLAG_HAS_WOL
                                  | FLAG_APME_IN_CTRL3
                                  | FLAG_RX_CSUM_ENABLED
                                  | FLAG_HAS_CTRLEXT_ON_LOAD
-                                 | FLAG_HAS_STATS_ICR_ICT
                                  | FLAG_HAS_SMART_POWER_DOWN
                                  | FLAG_RESET_OVERWRITES_LAA /* errata */
                                  | FLAG_TARC_SPEED_MODE_BIT /* errata */
@@ -1347,12 +1345,10 @@ struct e1000_info e1000_82572_info = {
        .mac                    = e1000_82572,
        .flags                  = FLAG_HAS_HW_VLAN_FILTER
                                  | FLAG_HAS_JUMBO_FRAMES
-                                 | FLAG_HAS_STATS_PTC_PRC
                                  | FLAG_HAS_WOL
                                  | FLAG_APME_IN_CTRL3
                                  | FLAG_RX_CSUM_ENABLED
                                  | FLAG_HAS_CTRLEXT_ON_LOAD
-                                 | FLAG_HAS_STATS_ICR_ICT
                                  | FLAG_TARC_SPEED_MODE_BIT, /* errata */
        .pba                    = 38,
        .get_variants           = e1000_get_variants_82571,
@@ -1365,11 +1361,9 @@ struct e1000_info e1000_82573_info = {
        .mac                    = e1000_82573,
        .flags                  = FLAG_HAS_HW_VLAN_FILTER
                                  | FLAG_HAS_JUMBO_FRAMES
-                                 | FLAG_HAS_STATS_PTC_PRC
                                  | FLAG_HAS_WOL
                                  | FLAG_APME_IN_CTRL3
                                  | FLAG_RX_CSUM_ENABLED
-                                 | FLAG_HAS_STATS_ICR_ICT
                                  | FLAG_HAS_SMART_POWER_DOWN
                                  | FLAG_HAS_AMT
                                  | FLAG_HAS_ERT
index 572cfd44397adcf6ff506b742aebc201b1c325b6..2a53875cddbf5601ab6da33b89f36caf3e6f8650 100644 (file)
 #define E1000_SWFW_EEP_SM   0x1
 #define E1000_SWFW_PHY0_SM  0x2
 #define E1000_SWFW_PHY1_SM  0x4
+#define E1000_SWFW_CSR_SM   0x8
 
 /* Device Control */
 #define E1000_CTRL_FD       0x00000001  /* Full duplex.0=half; 1=full */
 #define PHY_ID2          0x03 /* Phy Id Reg (word 2) */
 #define PHY_AUTONEG_ADV  0x04 /* Autoneg Advertisement */
 #define PHY_LP_ABILITY   0x05 /* Link Partner Ability (Base Page) */
+#define PHY_AUTONEG_EXP  0x06 /* Autoneg Expansion Reg */
 #define PHY_1000T_CTRL   0x09 /* 1000Base-T Control Reg */
 #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
+#define PHY_EXT_STATUS   0x0F /* Extended Status Reg */
 
 /* NVM Control */
 #define E1000_EECD_SK        0x00000001 /* NVM Clock */
index 5a89dff522641c5ea28351cb06e99c19e1092a65..38bfd0d261fee3f272f80415da323311eb8ddf43 100644 (file)
@@ -64,11 +64,14 @@ struct e1000_info;
 /* Tx/Rx descriptor defines */
 #define E1000_DEFAULT_TXD              256
 #define E1000_MAX_TXD                  4096
-#define E1000_MIN_TXD                  80
+#define E1000_MIN_TXD                  64
 
 #define E1000_DEFAULT_RXD              256
 #define E1000_MAX_RXD                  4096
-#define E1000_MIN_RXD                  80
+#define E1000_MIN_RXD                  64
+
+#define E1000_MIN_ITR_USECS            10 /* 100000 irq/sec */
+#define E1000_MAX_ITR_USECS            10000 /* 100    irq/sec */
 
 /* Early Receive defines */
 #define E1000_ERT_2048                 0x100
@@ -147,6 +150,18 @@ struct e1000_ring {
        struct e1000_queue_stats stats;
 };
 
+/* PHY register snapshot values */
+struct e1000_phy_regs {
+       u16 bmcr;               /* basic mode control register    */
+       u16 bmsr;               /* basic mode status register     */
+       u16 advertise;          /* auto-negotiation advertisement */
+       u16 lpa;                /* link partner ability register  */
+       u16 expansion;          /* auto-negotiation expansion reg */
+       u16 ctrl1000;           /* 1000BASE-T control register    */
+       u16 stat1000;           /* 1000BASE-T status register     */
+       u16 estatus;            /* extended status register       */
+};
+
 /* board specific private data structure */
 struct e1000_adapter {
        struct timer_list watchdog_timer;
@@ -202,8 +217,8 @@ struct e1000_adapter {
        /* Tx stats */
        u64 tpt_old;
        u64 colc_old;
-       u64 gotcl_old;
-       u32 gotcl;
+       u32 gotc;
+       u64 gotc_old;
        u32 tx_timeout_count;
        u32 tx_fifo_head;
        u32 tx_head_addr;
@@ -227,8 +242,8 @@ struct e1000_adapter {
        u64 hw_csum_err;
        u64 hw_csum_good;
        u64 rx_hdr_split;
-       u64 gorcl_old;
-       u32 gorcl;
+       u32 gorc;
+       u64 gorc_old;
        u32 alloc_rx_buff_failed;
        u32 rx_dma_failed;
 
@@ -250,6 +265,9 @@ struct e1000_adapter {
        struct e1000_phy_info phy_info;
        struct e1000_phy_stats phy_stats;
 
+       /* Snapshot of PHY registers */
+       struct e1000_phy_regs phy_regs;
+
        struct e1000_ring test_tx_ring;
        struct e1000_ring test_rx_ring;
        u32 test_icr;
@@ -286,8 +304,6 @@ struct e1000_info {
 #define FLAG_HAS_CTRLEXT_ON_LOAD          (1 << 5)
 #define FLAG_HAS_SWSM_ON_LOAD             (1 << 6)
 #define FLAG_HAS_JUMBO_FRAMES             (1 << 7)
-#define FLAG_HAS_STATS_ICR_ICT            (1 << 9)
-#define FLAG_HAS_STATS_PTC_PRC            (1 << 10)
 #define FLAG_HAS_SMART_POWER_DOWN         (1 << 11)
 #define FLAG_IS_QUAD_PORT_A               (1 << 12)
 #define FLAG_IS_QUAD_PORT                 (1 << 13)
@@ -433,6 +449,8 @@ extern s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data);
 extern s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
                               u32 usec_interval, bool *success);
 extern s32 e1000e_phy_reset_dsp(struct e1000_hw *hw);
+extern s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
+extern s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
 extern s32 e1000e_check_downshift(struct e1000_hw *hw);
 
 static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw)
index d59a99ae44bee83b6afa7aff45315ae828f9c9b7..dc552d7d6fac5d083671f66c17b882fe505798ae 100644 (file)
@@ -41,6 +41,7 @@
 #define E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL      0x00
 #define E1000_KMRNCTRLSTA_OFFSET_INB_CTRL       0x02
 #define E1000_KMRNCTRLSTA_OFFSET_HD_CTRL        0x10
+#define E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE         0x1F
 
 #define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS   0x0008
 #define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS   0x0800
@@ -48,6 +49,7 @@
 
 #define E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004
 #define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT  0x0000
+#define E1000_KMRNCTRLSTA_OPMODE_E_IDLE                 0x2000
 
 #define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */
 #define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN       0x00010000
@@ -85,6 +87,9 @@
 /* Kumeran Mode Control Register (Page 193, Register 16) */
 #define GG82563_KMCR_PASS_FALSE_CARRIER                 0x0800
 
+/* Max number of times Kumeran read/write should be validated */
+#define GG82563_MAX_KMRN_RETRY  0x5
+
 /* Power Management Control Register (Page 193, Register 20) */
 #define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE     0x0001
                                           /* 1=Enable SERDES Electrical Idle */
@@ -270,6 +275,7 @@ static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw)
        u16 mask;
 
        mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
+       mask |= E1000_SWFW_CSR_SM;
 
        return e1000_acquire_swfw_sync_80003es2lan(hw, mask);
 }
@@ -286,6 +292,8 @@ static void e1000_release_phy_80003es2lan(struct e1000_hw *hw)
        u16 mask;
 
        mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
+       mask |= E1000_SWFW_CSR_SM;
+
        e1000_release_swfw_sync_80003es2lan(hw, mask);
 }
 
@@ -410,20 +418,27 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
        u32 page_select;
        u16 temp;
 
+       ret_val = e1000_acquire_phy_80003es2lan(hw);
+       if (ret_val)
+               return ret_val;
+
        /* Select Configuration Page */
-       if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG)
+       if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
                page_select = GG82563_PHY_PAGE_SELECT;
-       else
+       } else {
                /*
                 * Use Alternative Page Select register to access
                 * registers 30 and 31
                 */
                page_select = GG82563_PHY_PAGE_SELECT_ALT;
+       }
 
        temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
-       ret_val = e1000e_write_phy_reg_m88(hw, page_select, temp);
-       if (ret_val)
+       ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp);
+       if (ret_val) {
+               e1000_release_phy_80003es2lan(hw);
                return ret_val;
+       }
 
        /*
         * The "ready" bit in the MDIC register may be incorrectly set
@@ -433,20 +448,21 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
        udelay(200);
 
        /* ...and verify the command was successful. */
-       ret_val = e1000e_read_phy_reg_m88(hw, page_select, &temp);
+       ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp);
 
        if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
                ret_val = -E1000_ERR_PHY;
+               e1000_release_phy_80003es2lan(hw);
                return ret_val;
        }
 
        udelay(200);
 
-       ret_val = e1000e_read_phy_reg_m88(hw,
-                                        MAX_PHY_REG_ADDRESS & offset,
-                                        data);
+       ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                          data);
 
        udelay(200);
+       e1000_release_phy_80003es2lan(hw);
 
        return ret_val;
 }
@@ -467,20 +483,27 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
        u32 page_select;
        u16 temp;
 
+       ret_val = e1000_acquire_phy_80003es2lan(hw);
+       if (ret_val)
+               return ret_val;
+
        /* Select Configuration Page */
-       if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG)
+       if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
                page_select = GG82563_PHY_PAGE_SELECT;
-       else
+       } else {
                /*
                 * Use Alternative Page Select register to access
                 * registers 30 and 31
                 */
                page_select = GG82563_PHY_PAGE_SELECT_ALT;
+       }
 
        temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
-       ret_val = e1000e_write_phy_reg_m88(hw, page_select, temp);
-       if (ret_val)
+       ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp);
+       if (ret_val) {
+               e1000_release_phy_80003es2lan(hw);
                return ret_val;
+       }
 
 
        /*
@@ -491,18 +514,20 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
        udelay(200);
 
        /* ...and verify the command was successful. */
-       ret_val = e1000e_read_phy_reg_m88(hw, page_select, &temp);
+       ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp);
 
-       if (((u16)offset >> GG82563_PAGE_SHIFT) != temp)
+       if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
+               e1000_release_phy_80003es2lan(hw);
                return -E1000_ERR_PHY;
+       }
 
        udelay(200);
 
-       ret_val = e1000e_write_phy_reg_m88(hw,
-                                         MAX_PHY_REG_ADDRESS & offset,
-                                         data);
+       ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                           data);
 
        udelay(200);
+       e1000_release_phy_80003es2lan(hw);
 
        return ret_val;
 }
@@ -882,10 +907,10 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
        u32 ctrl_ext;
-       u16 data;
+       u32 i = 0;
+       u16 data, data2;
 
-       ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL,
-                                    &data);
+       ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &data);
        if (ret_val)
                return ret_val;
 
@@ -893,8 +918,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
        /* Use 25MHz for both link down and 1000Base-T for Tx clock. */
        data |= GG82563_MSCR_TX_CLK_1000MBPS_25;
 
-       ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL,
-                                     data);
+       ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL, data);
        if (ret_val)
                return ret_val;
 
@@ -954,6 +978,18 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
+       ret_val = e1000e_read_kmrn_reg(hw,
+                                      E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
+                                      &data);
+       if (ret_val)
+               return ret_val;
+       data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE;
+       ret_val = e1000e_write_kmrn_reg(hw,
+                                       E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
+                                       data);
+       if (ret_val)
+               return ret_val;
+
        ret_val = e1e_rphy(hw, GG82563_PHY_SPEC_CTRL_2, &data);
        if (ret_val)
                return ret_val;
@@ -983,9 +1019,18 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
                if (ret_val)
                        return ret_val;
 
-               ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &data);
-               if (ret_val)
-                       return ret_val;
+               do {
+                       ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                          &data);
+                       if (ret_val)
+                               return ret_val;
+
+                       ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                          &data2);
+                       if (ret_val)
+                               return ret_val;
+                       i++;
+               } while ((data != data2) && (i < GG82563_MAX_KMRN_RETRY));
 
                data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
                ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, data);
@@ -1074,7 +1119,8 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
 {
        s32 ret_val;
        u32 tipg;
-       u16 reg_data;
+       u32 i = 0;
+       u16 reg_data, reg_data2;
 
        reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT;
        ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
@@ -1088,9 +1134,16 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
        tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN;
        ew32(TIPG, tipg);
 
-       ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
-       if (ret_val)
-               return ret_val;
+       do {
+               ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
+               if (ret_val)
+                       return ret_val;
+
+               ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data2);
+               if (ret_val)
+                       return ret_val;
+               i++;
+       } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
 
        if (duplex == HALF_DUPLEX)
                reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER;
@@ -1112,8 +1165,9 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
 static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
 {
        s32 ret_val;
-       u16 reg_data;
+       u16 reg_data, reg_data2;
        u32 tipg;
+       u32 i = 0;
 
        reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT;
        ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
@@ -1127,9 +1181,16 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
        tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN;
        ew32(TIPG, tipg);
 
-       ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
-       if (ret_val)
-               return ret_val;
+       do {
+               ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
+               if (ret_val)
+                       return ret_val;
+
+               ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data2);
+               if (ret_val)
+                       return ret_val;
+               i++;
+       } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
 
        reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
        ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
@@ -1231,12 +1292,10 @@ struct e1000_info e1000_es2_info = {
        .mac                    = e1000_80003es2lan,
        .flags                  = FLAG_HAS_HW_VLAN_FILTER
                                  | FLAG_HAS_JUMBO_FRAMES
-                                 | FLAG_HAS_STATS_PTC_PRC
                                  | FLAG_HAS_WOL
                                  | FLAG_APME_IN_CTRL3
                                  | FLAG_RX_CSUM_ENABLED
                                  | FLAG_HAS_CTRLEXT_ON_LOAD
-                                 | FLAG_HAS_STATS_ICR_ICT
                                  | FLAG_RX_NEEDS_RESTART /* errata */
                                  | FLAG_TARC_SET_BIT_ZERO /* errata */
                                  | FLAG_APME_CHECK_PORT_B
index 6d1b257bbda6b37d3ea38b1034ef02f20b72f1a3..ce045acce63e99b79685e291a8993e3acd940508 100644 (file)
@@ -46,8 +46,8 @@ struct e1000_stats {
 static const struct e1000_stats e1000_gstrings_stats[] = {
        { "rx_packets", E1000_STAT(stats.gprc) },
        { "tx_packets", E1000_STAT(stats.gptc) },
-       { "rx_bytes", E1000_STAT(stats.gorcl) },
-       { "tx_bytes", E1000_STAT(stats.gotcl) },
+       { "rx_bytes", E1000_STAT(stats.gorc) },
+       { "tx_bytes", E1000_STAT(stats.gotc) },
        { "rx_broadcast", E1000_STAT(stats.bprc) },
        { "tx_broadcast", E1000_STAT(stats.bptc) },
        { "rx_multicast", E1000_STAT(stats.mprc) },
@@ -83,7 +83,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
        { "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) },
        { "tx_flow_control_xon", E1000_STAT(stats.xontxc) },
        { "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
-       { "rx_long_byte_count", E1000_STAT(stats.gorcl) },
+       { "rx_long_byte_count", E1000_STAT(stats.gorc) },
        { "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
        { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
        { "rx_header_split", E1000_STAT(rx_hdr_split) },
@@ -1770,6 +1770,47 @@ static int e1000_phys_id(struct net_device *netdev, u32 data)
        return 0;
 }
 
+static int e1000_get_coalesce(struct net_device *netdev,
+                             struct ethtool_coalesce *ec)
+{
+       struct e1000_adapter *adapter = netdev_priv(netdev);
+
+       if (adapter->itr_setting <= 3)
+               ec->rx_coalesce_usecs = adapter->itr_setting;
+       else
+               ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting;
+
+       return 0;
+}
+
+static int e1000_set_coalesce(struct net_device *netdev,
+                             struct ethtool_coalesce *ec)
+{
+       struct e1000_adapter *adapter = netdev_priv(netdev);
+       struct e1000_hw *hw = &adapter->hw;
+
+       if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) ||
+           ((ec->rx_coalesce_usecs > 3) &&
+            (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) ||
+           (ec->rx_coalesce_usecs == 2))
+               return -EINVAL;
+
+       if (ec->rx_coalesce_usecs <= 3) {
+               adapter->itr = 20000;
+               adapter->itr_setting = ec->rx_coalesce_usecs;
+       } else {
+               adapter->itr = (1000000 / ec->rx_coalesce_usecs);
+               adapter->itr_setting = adapter->itr & ~3;
+       }
+
+       if (adapter->itr_setting != 0)
+               ew32(ITR, 1000000000 / (adapter->itr * 256));
+       else
+               ew32(ITR, 0);
+
+       return 0;
+}
+
 static int e1000_nway_reset(struct net_device *netdev)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -1845,6 +1886,8 @@ static const struct ethtool_ops e1000_ethtool_ops = {
        .phys_id                = e1000_phys_id,
        .get_ethtool_stats      = e1000_get_ethtool_stats,
        .get_sset_count         = e1000e_get_sset_count,
+       .get_coalesce           = e1000_get_coalesce,
+       .set_coalesce           = e1000_set_coalesce,
 };
 
 void e1000e_set_ethtool_ops(struct net_device *netdev)
index 53f1ac6327fabcd92312ca3d4733c7bb5983f773..a930e6d9cf02bdd34d8beb88d67f84c47d8fb6d1 100644 (file)
@@ -592,10 +592,8 @@ struct e1000_hw_stats {
        u64 bprc;
        u64 mprc;
        u64 gptc;
-       u64 gorcl;
-       u64 gorch;
-       u64 gotcl;
-       u64 gotch;
+       u64 gorc;
+       u64 gotc;
        u64 rnbc;
        u64 ruc;
        u64 rfc;
@@ -604,10 +602,8 @@ struct e1000_hw_stats {
        u64 mgprc;
        u64 mgpdc;
        u64 mgptc;
-       u64 torl;
-       u64 torh;
-       u64 totl;
-       u64 toth;
+       u64 tor;
+       u64 tot;
        u64 tpr;
        u64 tpt;
        u64 ptc64;
index c8dc47fd132a47e74401a0c103efb23a18b97934..8991ab8911e2f506e1d2be85fbad7a7f4a8ad4fb 100644 (file)
@@ -46,7 +46,7 @@
 
 #include "e1000.h"
 
-#define DRV_VERSION "0.2.0"
+#define DRV_VERSION "0.2.1"
 char e1000e_driver_name[] = "e1000e";
 const char e1000e_driver_version[] = DRV_VERSION;
 
@@ -466,10 +466,10 @@ next_desc:
        if (cleaned_count)
                adapter->alloc_rx_buf(adapter, cleaned_count);
 
-       adapter->total_rx_packets += total_rx_packets;
        adapter->total_rx_bytes += total_rx_bytes;
-       adapter->net_stats.rx_packets += total_rx_packets;
+       adapter->total_rx_packets += total_rx_packets;
        adapter->net_stats.rx_bytes += total_rx_bytes;
+       adapter->net_stats.rx_packets += total_rx_packets;
        return cleaned;
 }
 
@@ -606,8 +606,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
        }
        adapter->total_tx_bytes += total_tx_bytes;
        adapter->total_tx_packets += total_tx_packets;
-       adapter->net_stats.tx_packets += total_tx_packets;
        adapter->net_stats.tx_bytes += total_tx_bytes;
+       adapter->net_stats.tx_packets += total_tx_packets;
        return cleaned;
 }
 
@@ -775,10 +775,10 @@ next_desc:
        if (cleaned_count)
                adapter->alloc_rx_buf(adapter, cleaned_count);
 
-       adapter->total_rx_packets += total_rx_packets;
        adapter->total_rx_bytes += total_rx_bytes;
-       adapter->net_stats.rx_packets += total_rx_packets;
+       adapter->total_rx_packets += total_rx_packets;
        adapter->net_stats.rx_bytes += total_rx_bytes;
+       adapter->net_stats.rx_packets += total_rx_packets;
        return cleaned;
 }
 
@@ -2506,56 +2506,27 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
 
        adapter->stats.crcerrs += er32(CRCERRS);
        adapter->stats.gprc += er32(GPRC);
-       adapter->stats.gorcl += er32(GORCL);
-       adapter->stats.gorch += er32(GORCH);
+       adapter->stats.gorc += er32(GORCL);
+       er32(GORCH); /* Clear gorc */
        adapter->stats.bprc += er32(BPRC);
        adapter->stats.mprc += er32(MPRC);
        adapter->stats.roc += er32(ROC);
 
-       if (adapter->flags & FLAG_HAS_STATS_PTC_PRC) {
-               adapter->stats.prc64 += er32(PRC64);
-               adapter->stats.prc127 += er32(PRC127);
-               adapter->stats.prc255 += er32(PRC255);
-               adapter->stats.prc511 += er32(PRC511);
-               adapter->stats.prc1023 += er32(PRC1023);
-               adapter->stats.prc1522 += er32(PRC1522);
-               adapter->stats.symerrs += er32(SYMERRS);
-               adapter->stats.sec += er32(SEC);
-       }
-
        adapter->stats.mpc += er32(MPC);
        adapter->stats.scc += er32(SCC);
        adapter->stats.ecol += er32(ECOL);
        adapter->stats.mcc += er32(MCC);
        adapter->stats.latecol += er32(LATECOL);
        adapter->stats.dc += er32(DC);
-       adapter->stats.rlec += er32(RLEC);
        adapter->stats.xonrxc += er32(XONRXC);
        adapter->stats.xontxc += er32(XONTXC);
        adapter->stats.xoffrxc += er32(XOFFRXC);
        adapter->stats.xofftxc += er32(XOFFTXC);
-       adapter->stats.fcruc += er32(FCRUC);
        adapter->stats.gptc += er32(GPTC);
-       adapter->stats.gotcl += er32(GOTCL);
-       adapter->stats.gotch += er32(GOTCH);
+       adapter->stats.gotc += er32(GOTCL);
+       er32(GOTCH); /* Clear gotc */
        adapter->stats.rnbc += er32(RNBC);
        adapter->stats.ruc += er32(RUC);
-       adapter->stats.rfc += er32(RFC);
-       adapter->stats.rjc += er32(RJC);
-       adapter->stats.torl += er32(TORL);
-       adapter->stats.torh += er32(TORH);
-       adapter->stats.totl += er32(TOTL);
-       adapter->stats.toth += er32(TOTH);
-       adapter->stats.tpr += er32(TPR);
-
-       if (adapter->flags & FLAG_HAS_STATS_PTC_PRC) {
-               adapter->stats.ptc64 += er32(PTC64);
-               adapter->stats.ptc127 += er32(PTC127);
-               adapter->stats.ptc255 += er32(PTC255);
-               adapter->stats.ptc511 += er32(PTC511);
-               adapter->stats.ptc1023 += er32(PTC1023);
-               adapter->stats.ptc1522 += er32(PTC1522);
-       }
 
        adapter->stats.mptc += er32(MPTC);
        adapter->stats.bptc += er32(BPTC);
@@ -2574,19 +2545,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
        adapter->stats.tsctc += er32(TSCTC);
        adapter->stats.tsctfc += er32(TSCTFC);
 
-       adapter->stats.iac += er32(IAC);
-
-       if (adapter->flags & FLAG_HAS_STATS_ICR_ICT) {
-               adapter->stats.icrxoc += er32(ICRXOC);
-               adapter->stats.icrxptc += er32(ICRXPTC);
-               adapter->stats.icrxatc += er32(ICRXATC);
-               adapter->stats.ictxptc += er32(ICTXPTC);
-               adapter->stats.ictxatc += er32(ICTXATC);
-               adapter->stats.ictxqec += er32(ICTXQEC);
-               adapter->stats.ictxqmtc += er32(ICTXQMTC);
-               adapter->stats.icrxdmtc += er32(ICRXDMTC);
-       }
-
        /* Fill out the OS statistics structure */
        adapter->net_stats.multicast = adapter->stats.mprc;
        adapter->net_stats.collisions = adapter->stats.colc;
@@ -2633,6 +2591,54 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
        spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
 }
 
+/**
+ * e1000_phy_read_status - Update the PHY register status snapshot
+ * @adapter: board private structure
+ **/
+static void e1000_phy_read_status(struct e1000_adapter *adapter)
+{
+       struct e1000_hw *hw = &adapter->hw;
+       struct e1000_phy_regs *phy = &adapter->phy_regs;
+       int ret_val;
+       unsigned long irq_flags;
+
+
+       spin_lock_irqsave(&adapter->stats_lock, irq_flags);
+
+       if ((er32(STATUS) & E1000_STATUS_LU) &&
+           (adapter->hw.phy.media_type == e1000_media_type_copper)) {
+               ret_val  = e1e_rphy(hw, PHY_CONTROL, &phy->bmcr);
+               ret_val |= e1e_rphy(hw, PHY_STATUS, &phy->bmsr);
+               ret_val |= e1e_rphy(hw, PHY_AUTONEG_ADV, &phy->advertise);
+               ret_val |= e1e_rphy(hw, PHY_LP_ABILITY, &phy->lpa);
+               ret_val |= e1e_rphy(hw, PHY_AUTONEG_EXP, &phy->expansion);
+               ret_val |= e1e_rphy(hw, PHY_1000T_CTRL, &phy->ctrl1000);
+               ret_val |= e1e_rphy(hw, PHY_1000T_STATUS, &phy->stat1000);
+               ret_val |= e1e_rphy(hw, PHY_EXT_STATUS, &phy->estatus);
+               if (ret_val)
+                       ndev_warn(adapter->netdev,
+                                 "Error reading PHY register\n");
+       } else {
+               /*
+                * Do not read PHY registers if link is not up
+                * Set values to typical power-on defaults
+                */
+               phy->bmcr = (BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_FULLDPLX);
+               phy->bmsr = (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL |
+                            BMSR_10HALF | BMSR_ESTATEN | BMSR_ANEGCAPABLE |
+                            BMSR_ERCAP);
+               phy->advertise = (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP |
+                                 ADVERTISE_ALL | ADVERTISE_CSMA);
+               phy->lpa = 0;
+               phy->expansion = EXPANSION_ENABLENPAGE;
+               phy->ctrl1000 = ADVERTISE_1000FULL;
+               phy->stat1000 = 0;
+               phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF);
+       }
+
+       spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
+}
+
 static void e1000_print_link_info(struct e1000_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
@@ -2745,6 +2751,7 @@ static void e1000_watchdog_task(struct work_struct *work)
                if (!netif_carrier_ok(netdev)) {
                        bool txb2b = 1;
                        /* update snapshot of PHY registers on LSC */
+                       e1000_phy_read_status(adapter);
                        mac->ops.get_link_up_info(&adapter->hw,
                                                   &adapter->link_speed,
                                                   &adapter->link_duplex);
@@ -2842,10 +2849,10 @@ link_up:
        mac->collision_delta = adapter->stats.colc - adapter->colc_old;
        adapter->colc_old = adapter->stats.colc;
 
-       adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old;
-       adapter->gorcl_old = adapter->stats.gorcl;
-       adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old;
-       adapter->gotcl_old = adapter->stats.gotcl;
+       adapter->gorc = adapter->stats.gorc - adapter->gorc_old;
+       adapter->gorc_old = adapter->stats.gorc;
+       adapter->gotc = adapter->stats.gotc - adapter->gotc_old;
+       adapter->gotc_old = adapter->stats.gotc;
 
        e1000e_update_adaptive(&adapter->hw);
 
@@ -3500,7 +3507,6 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct mii_ioctl_data *data = if_mii(ifr);
-       unsigned long irq_flags;
 
        if (adapter->hw.phy.media_type != e1000_media_type_copper)
                return -EOPNOTSUPP;
@@ -3512,13 +3518,40 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
        case SIOCGMIIREG:
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
-               spin_lock_irqsave(&adapter->stats_lock, irq_flags);
-               if (e1e_rphy(&adapter->hw, data->reg_num & 0x1F,
-                                  &data->val_out)) {
-                       spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
+               switch (data->reg_num & 0x1F) {
+               case MII_BMCR:
+                       data->val_out = adapter->phy_regs.bmcr;
+                       break;
+               case MII_BMSR:
+                       data->val_out = adapter->phy_regs.bmsr;
+                       break;
+               case MII_PHYSID1:
+                       data->val_out = (adapter->hw.phy.id >> 16);
+                       break;
+               case MII_PHYSID2:
+                       data->val_out = (adapter->hw.phy.id & 0xFFFF);
+                       break;
+               case MII_ADVERTISE:
+                       data->val_out = adapter->phy_regs.advertise;
+                       break;
+               case MII_LPA:
+                       data->val_out = adapter->phy_regs.lpa;
+                       break;
+               case MII_EXPANSION:
+                       data->val_out = adapter->phy_regs.expansion;
+                       break;
+               case MII_CTRL1000:
+                       data->val_out = adapter->phy_regs.ctrl1000;
+                       break;
+               case MII_STAT1000:
+                       data->val_out = adapter->phy_regs.stat1000;
+                       break;
+               case MII_ESTATUS:
+                       data->val_out = adapter->phy_regs.estatus;
+                       break;
+               default:
                        return -EIO;
                }
-               spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
                break;
        case SIOCSMIIREG:
        default:
@@ -3774,6 +3807,7 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
                return PCI_ERS_RESULT_DISCONNECT;
        }
        pci_set_master(pdev);
+       pci_restore_state(pdev);
 
        pci_enable_wake(pdev, PCI_D3hot, 0);
        pci_enable_wake(pdev, PCI_D3cold, 0);
@@ -3900,6 +3934,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
                goto err_pci_reg;
 
        pci_set_master(pdev);
+       pci_save_state(pdev);
 
        err = -ENOMEM;
        netdev = alloc_etherdev(sizeof(struct e1000_adapter));
index 3a4574caa75bb1fdcd824d5b3853141773fda532..e102332a6beed4e49588f2c37063a0429fef85f8 100644 (file)
@@ -116,7 +116,7 @@ s32 e1000e_phy_reset_dsp(struct e1000_hw *hw)
 }
 
 /**
- *  e1000_read_phy_reg_mdic - Read MDI control register
+ *  e1000e_read_phy_reg_mdic - Read MDI control register
  *  @hw: pointer to the HW structure
  *  @offset: register offset to be read
  *  @data: pointer to the read data
@@ -124,7 +124,7 @@ s32 e1000e_phy_reset_dsp(struct e1000_hw *hw)
  *  Reads the MDI control register in the PHY at offset and stores the
  *  information read to data.
  **/
-static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
 {
        struct e1000_phy_info *phy = &hw->phy;
        u32 i, mdic = 0;
@@ -150,7 +150,7 @@ static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
         * Increasing the time out as testing showed failures with
         * the lower time out
         */
-       for (i = 0; i < 64; i++) {
+       for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
                udelay(50);
                mdic = er32(MDIC);
                if (mdic & E1000_MDIC_READY)
@@ -170,14 +170,14 @@ static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
 }
 
 /**
- *  e1000_write_phy_reg_mdic - Write MDI control register
+ *  e1000e_write_phy_reg_mdic - Write MDI control register
  *  @hw: pointer to the HW structure
  *  @offset: register offset to write to
  *  @data: data to write to register at offset
  *
  *  Writes data to MDI control register in the PHY at offset.
  **/
-static s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
+s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
 {
        struct e1000_phy_info *phy = &hw->phy;
        u32 i, mdic = 0;
@@ -199,9 +199,13 @@ static s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
 
        ew32(MDIC, mdic);
 
-       /* Poll the ready bit to see if the MDI read completed */
-       for (i = 0; i < E1000_GEN_POLL_TIMEOUT; i++) {
-               udelay(5);
+       /*
+        * Poll the ready bit to see if the MDI read completed
+        * Increasing the time out as testing showed failures with
+        * the lower time out
+        */
+       for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
+               udelay(50);
                mdic = er32(MDIC);
                if (mdic & E1000_MDIC_READY)
                        break;
@@ -210,6 +214,10 @@ static s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
                hw_dbg(hw, "MDI Write did not complete\n");
                return -E1000_ERR_PHY;
        }
+       if (mdic & E1000_MDIC_ERROR) {
+               hw_dbg(hw, "MDI Error\n");
+               return -E1000_ERR_PHY;
+       }
 
        return 0;
 }
@@ -232,9 +240,8 @@ s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data)
        if (ret_val)
                return ret_val;
 
-       ret_val = e1000_read_phy_reg_mdic(hw,
-                                         MAX_PHY_REG_ADDRESS & offset,
-                                         data);
+       ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                          data);
 
        hw->phy.ops.release_phy(hw);
 
@@ -258,9 +265,8 @@ s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
        if (ret_val)
                return ret_val;
 
-       ret_val = e1000_write_phy_reg_mdic(hw,
-                                          MAX_PHY_REG_ADDRESS & offset,
-                                          data);
+       ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                           data);
 
        hw->phy.ops.release_phy(hw);
 
@@ -286,18 +292,17 @@ s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
                return ret_val;
 
        if (offset > MAX_PHY_MULTI_PAGE_REG) {
-               ret_val = e1000_write_phy_reg_mdic(hw,
-                                                  IGP01E1000_PHY_PAGE_SELECT,
-                                                  (u16)offset);
+               ret_val = e1000e_write_phy_reg_mdic(hw,
+                                                   IGP01E1000_PHY_PAGE_SELECT,
+                                                   (u16)offset);
                if (ret_val) {
                        hw->phy.ops.release_phy(hw);
                        return ret_val;
                }
        }
 
-       ret_val = e1000_read_phy_reg_mdic(hw,
-                                         MAX_PHY_REG_ADDRESS & offset,
-                                         data);
+       ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                          data);
 
        hw->phy.ops.release_phy(hw);
 
@@ -322,18 +327,17 @@ s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
                return ret_val;
 
        if (offset > MAX_PHY_MULTI_PAGE_REG) {
-               ret_val = e1000_write_phy_reg_mdic(hw,
-                                                  IGP01E1000_PHY_PAGE_SELECT,
-                                                  (u16)offset);
+               ret_val = e1000e_write_phy_reg_mdic(hw,
+                                                   IGP01E1000_PHY_PAGE_SELECT,
+                                                   (u16)offset);
                if (ret_val) {
                        hw->phy.ops.release_phy(hw);
                        return ret_val;
                }
        }
 
-       ret_val = e1000_write_phy_reg_mdic(hw,
-                                          MAX_PHY_REG_ADDRESS & offset,
-                                          data);
+       ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                           data);
 
        hw->phy.ops.release_phy(hw);
 
@@ -420,7 +424,9 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+       /* For newer PHYs this bit is downshift enable */
+       if (phy->type == e1000_phy_m88)
+               phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
 
        /*
         * Options:
@@ -463,7 +469,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       if (phy->revision < 4) {
+       if ((phy->type == e1000_phy_m88) && (phy->revision < 4)) {
                /*
                 * Force TX_CLK in the Extended PHY Specific Control Register
                 * to 25MHz clock.
@@ -518,8 +524,11 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw)
                return ret_val;
        }
 
-       /* Wait 15ms for MAC to configure PHY from NVM settings. */
-       msleep(15);
+       /*
+        * Wait 100ms for MAC to configure PHY from NVM settings, to avoid
+        * timeout issues when LFS is enabled.
+        */
+       msleep(100);
 
        /* disable lplu d0 during driver init */
        ret_val = e1000_set_d0_lplu_state(hw, 0);
@@ -1152,9 +1161,7 @@ s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active)
 
        if (!active) {
                data &= ~IGP02E1000_PM_D3_LPLU;
-               ret_val = e1e_wphy(hw,
-                                            IGP02E1000_PHY_POWER_MGMT,
-                                            data);
+               ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
                if (ret_val)
                        return ret_val;
                /*
index 9ff7538b75952e94ef27d9660dd31fa00f75b605..f9bc21c74b59222a7c8775dfaba80a91d9abb626 100644 (file)
@@ -2611,7 +2611,7 @@ static int ehea_stop(struct net_device *dev)
        return ret;
 }
 
-void ehea_purge_sq(struct ehea_qp *orig_qp)
+static void ehea_purge_sq(struct ehea_qp *orig_qp)
 {
        struct ehea_qp qp = *orig_qp;
        struct ehea_qp_init_attr *init_attr = &qp.init_attr;
@@ -2625,7 +2625,7 @@ void ehea_purge_sq(struct ehea_qp *orig_qp)
        }
 }
 
-void ehea_flush_sq(struct ehea_port *port)
+static void ehea_flush_sq(struct ehea_port *port)
 {
        int i;
 
index 8c4214b0ee1f2ff7d6bc7f04bd497e07ef613f35..35f66d4a4595d5148f4affbc167897c60ca49792 100644 (file)
@@ -96,6 +96,7 @@
 #define DEV_HAS_PAUSEFRAME_TX_V2   0x10000  /* device supports tx pause frames version 2 */
 #define DEV_HAS_PAUSEFRAME_TX_V3   0x20000  /* device supports tx pause frames version 3 */
 #define DEV_NEED_TX_LIMIT          0x40000  /* device needs to limit tx */
+#define DEV_HAS_GEAR_MODE          0x80000  /* device supports gear mode */
 
 enum {
        NvRegIrqStatus = 0x000,
@@ -174,11 +175,13 @@ enum {
        NvRegReceiverStatus = 0x98,
 #define NVREG_RCVSTAT_BUSY     0x01
 
-       NvRegRandomSeed = 0x9c,
-#define NVREG_RNDSEED_MASK     0x00ff
-#define NVREG_RNDSEED_FORCE    0x7f00
-#define NVREG_RNDSEED_FORCE2   0x2d00
-#define NVREG_RNDSEED_FORCE3   0x7400
+       NvRegSlotTime = 0x9c,
+#define NVREG_SLOTTIME_LEGBF_ENABLED   0x80000000
+#define NVREG_SLOTTIME_10_100_FULL     0x00007f00
+#define NVREG_SLOTTIME_1000_FULL       0x0003ff00
+#define NVREG_SLOTTIME_HALF            0x0000ff00
+#define NVREG_SLOTTIME_DEFAULT         0x00007f00
+#define NVREG_SLOTTIME_MASK            0x000000ff
 
        NvRegTxDeferral = 0xA0,
 #define NVREG_TX_DEFERRAL_DEFAULT              0x15050f
@@ -201,6 +204,11 @@ enum {
 
        NvRegPhyInterface = 0xC0,
 #define PHY_RGMII              0x10000000
+       NvRegBackOffControl = 0xC4,
+#define NVREG_BKOFFCTRL_DEFAULT                        0x70000000
+#define NVREG_BKOFFCTRL_SEED_MASK              0x000003ff
+#define NVREG_BKOFFCTRL_SELECT                 24
+#define NVREG_BKOFFCTRL_GEAR                   12
 
        NvRegTxRingPhysAddr = 0x100,
        NvRegRxRingPhysAddr = 0x104,
@@ -352,6 +360,7 @@ union ring_type {
 
 #define NV_TX_LASTPACKET       (1<<16)
 #define NV_TX_RETRYERROR       (1<<19)
+#define NV_TX_RETRYCOUNT_MASK  (0xF<<20)
 #define NV_TX_FORCED_INTERRUPT (1<<24)
 #define NV_TX_DEFERRED         (1<<26)
 #define NV_TX_CARRIERLOST      (1<<27)
@@ -362,6 +371,7 @@ union ring_type {
 
 #define NV_TX2_LASTPACKET      (1<<29)
 #define NV_TX2_RETRYERROR      (1<<18)
+#define NV_TX2_RETRYCOUNT_MASK (0xF<<19)
 #define NV_TX2_FORCED_INTERRUPT        (1<<30)
 #define NV_TX2_DEFERRED                (1<<25)
 #define NV_TX2_CARRIERLOST     (1<<26)
@@ -473,16 +483,22 @@ union ring_type {
 #define DESC_VER_3     3
 
 /* PHY defines */
-#define PHY_OUI_MARVELL        0x5043
-#define PHY_OUI_CICADA 0x03f1
-#define PHY_OUI_VITESSE        0x01c1
-#define PHY_OUI_REALTEK        0x0732
+#define PHY_OUI_MARVELL                0x5043
+#define PHY_OUI_CICADA         0x03f1
+#define PHY_OUI_VITESSE                0x01c1
+#define PHY_OUI_REALTEK                0x0732
+#define PHY_OUI_REALTEK2       0x0020
 #define PHYID1_OUI_MASK        0x03ff
 #define PHYID1_OUI_SHFT        6
 #define PHYID2_OUI_MASK        0xfc00
 #define PHYID2_OUI_SHFT        10
 #define PHYID2_MODEL_MASK              0x03f0
-#define PHY_MODEL_MARVELL_E3016                0x220
+#define PHY_MODEL_REALTEK_8211         0x0110
+#define PHY_REV_MASK                   0x0001
+#define PHY_REV_REALTEK_8211B          0x0000
+#define PHY_REV_REALTEK_8211C          0x0001
+#define PHY_MODEL_REALTEK_8201         0x0200
+#define PHY_MODEL_MARVELL_E3016                0x0220
 #define PHY_MARVELL_E3016_INITMASK     0x0300
 #define PHY_CICADA_INIT1       0x0f000
 #define PHY_CICADA_INIT2       0x0e00
@@ -509,10 +525,18 @@ union ring_type {
 #define PHY_REALTEK_INIT_REG1  0x1f
 #define PHY_REALTEK_INIT_REG2  0x19
 #define PHY_REALTEK_INIT_REG3  0x13
+#define PHY_REALTEK_INIT_REG4  0x14
+#define PHY_REALTEK_INIT_REG5  0x18
+#define PHY_REALTEK_INIT_REG6  0x11
 #define PHY_REALTEK_INIT1      0x0000
 #define PHY_REALTEK_INIT2      0x8e00
 #define PHY_REALTEK_INIT3      0x0001
 #define PHY_REALTEK_INIT4      0xad17
+#define PHY_REALTEK_INIT5      0xfb54
+#define PHY_REALTEK_INIT6      0xf5c7
+#define PHY_REALTEK_INIT7      0x1000
+#define PHY_REALTEK_INIT8      0x0003
+#define PHY_REALTEK_INIT_MSK1  0x0003
 
 #define PHY_GIGABIT    0x0100
 
@@ -691,6 +715,7 @@ struct fe_priv {
        int wolenabled;
        unsigned int phy_oui;
        unsigned int phy_model;
+       unsigned int phy_rev;
        u16 gigabit;
        int intr_test;
        int recover_error;
@@ -704,6 +729,7 @@ struct fe_priv {
        u32 txrxctl_bits;
        u32 vlanctl_bits;
        u32 driver_data;
+       u32 device_id;
        u32 register_size;
        int rx_csum;
        u32 mac_in_use;
@@ -814,6 +840,16 @@ enum {
 };
 static int dma_64bit = NV_DMA_64BIT_ENABLED;
 
+/*
+ * Crossover Detection
+ * Realtek 8201 phy + some OEM boards do not work properly.
+ */
+enum {
+       NV_CROSSOVER_DETECTION_DISABLED,
+       NV_CROSSOVER_DETECTION_ENABLED
+};
+static int phy_cross = NV_CROSSOVER_DETECTION_DISABLED;
+
 static inline struct fe_priv *get_nvpriv(struct net_device *dev)
 {
        return netdev_priv(dev);
@@ -1078,25 +1114,53 @@ static int phy_init(struct net_device *dev)
                }
        }
        if (np->phy_oui == PHY_OUI_REALTEK) {
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
-               }
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
-               }
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
-               }
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
+               if (np->phy_model == PHY_MODEL_REALTEK_8211 &&
+                   np->phy_rev == PHY_REV_REALTEK_8211B) {
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
                }
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
+               if (np->phy_model == PHY_MODEL_REALTEK_8201) {
+                       if (np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_32 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_33 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_34 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_35 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_36 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_37 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_38 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_39) {
+                               phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ);
+                               phy_reserved |= PHY_REALTEK_INIT7;
+                               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) {
+                                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                                       return PHY_ERROR;
+                               }
+                       }
                }
        }
 
@@ -1236,26 +1300,71 @@ static int phy_init(struct net_device *dev)
                }
        }
        if (np->phy_oui == PHY_OUI_REALTEK) {
-               /* reset could have cleared these out, set them back */
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
-               }
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
-               }
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
-               }
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
+               if (np->phy_model == PHY_MODEL_REALTEK_8211 &&
+                   np->phy_rev == PHY_REV_REALTEK_8211B) {
+                       /* reset could have cleared these out, set them back */
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
                }
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
+               if (np->phy_model == PHY_MODEL_REALTEK_8201) {
+                       if (np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_32 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_33 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_34 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_35 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_36 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_37 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_38 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_39) {
+                               phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ);
+                               phy_reserved |= PHY_REALTEK_INIT7;
+                               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) {
+                                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                                       return PHY_ERROR;
+                               }
+                       }
+                       if (phy_cross == NV_CROSSOVER_DETECTION_DISABLED) {
+                               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+                                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                                       return PHY_ERROR;
+                               }
+                               phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, MII_READ);
+                               phy_reserved &= ~PHY_REALTEK_INIT_MSK1;
+                               phy_reserved |= PHY_REALTEK_INIT3;
+                               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, phy_reserved)) {
+                                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                                       return PHY_ERROR;
+                               }
+                               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+                                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                                       return PHY_ERROR;
+                               }
+                       }
                }
        }
 
@@ -1769,6 +1878,115 @@ static inline u32 nv_get_empty_tx_slots(struct fe_priv *np)
        return (u32)(np->tx_ring_size - ((np->tx_ring_size + (np->put_tx_ctx - np->get_tx_ctx)) % np->tx_ring_size));
 }
 
+static void nv_legacybackoff_reseed(struct net_device *dev)
+{
+       u8 __iomem *base = get_hwbase(dev);
+       u32 reg;
+       u32 low;
+       int tx_status = 0;
+
+       reg = readl(base + NvRegSlotTime) & ~NVREG_SLOTTIME_MASK;
+       get_random_bytes(&low, sizeof(low));
+       reg |= low & NVREG_SLOTTIME_MASK;
+
+       /* Need to stop tx before change takes effect.
+        * Caller has already gained np->lock.
+        */
+       tx_status = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_START;
+       if (tx_status)
+               nv_stop_tx(dev);
+       nv_stop_rx(dev);
+       writel(reg, base + NvRegSlotTime);
+       if (tx_status)
+               nv_start_tx(dev);
+       nv_start_rx(dev);
+}
+
+/* Gear Backoff Seeds */
+#define BACKOFF_SEEDSET_ROWS   8
+#define BACKOFF_SEEDSET_LFSRS  15
+
+/* Known Good seed sets */
+static const u32 main_seedset[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] = {
+    {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874},
+    {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 385, 761, 790, 974},
+    {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874},
+    {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 386, 761, 790, 974},
+    {266, 265, 276, 585, 397, 208, 345, 355, 365, 376, 385, 396, 771, 700, 984},
+    {266, 265, 276, 586, 397, 208, 346, 355, 365, 376, 285, 396, 771, 700, 984},
+    {366, 365, 376, 686, 497, 308, 447, 455, 466, 476, 485, 496, 871, 800,  84},
+    {466, 465, 476, 786, 597, 408, 547, 555, 566, 576, 585, 597, 971, 900, 184}};
+
+static const u32 gear_seedset[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] = {
+    {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375,  30, 295},
+    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
+    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 397},
+    {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375,  30, 295},
+    {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375,  30, 295},
+    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
+    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
+    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}};
+
+static void nv_gear_backoff_reseed(struct net_device *dev)
+{
+       u8 __iomem *base = get_hwbase(dev);
+       u32 miniseed1, miniseed2, miniseed2_reversed, miniseed3, miniseed3_reversed;
+       u32 temp, seedset, combinedSeed;
+       int i;
+
+       /* Setup seed for free running LFSR */
+       /* We are going to read the time stamp counter 3 times
+          and swizzle bits around to increase randomness */
+       get_random_bytes(&miniseed1, sizeof(miniseed1));
+       miniseed1 &= 0x0fff;
+       if (miniseed1 == 0)
+               miniseed1 = 0xabc;
+
+       get_random_bytes(&miniseed2, sizeof(miniseed2));
+       miniseed2 &= 0x0fff;
+       if (miniseed2 == 0)
+               miniseed2 = 0xabc;
+       miniseed2_reversed =
+               ((miniseed2 & 0xF00) >> 8) |
+                (miniseed2 & 0x0F0) |
+                ((miniseed2 & 0x00F) << 8);
+
+       get_random_bytes(&miniseed3, sizeof(miniseed3));
+       miniseed3 &= 0x0fff;
+       if (miniseed3 == 0)
+               miniseed3 = 0xabc;
+       miniseed3_reversed =
+               ((miniseed3 & 0xF00) >> 8) |
+                (miniseed3 & 0x0F0) |
+                ((miniseed3 & 0x00F) << 8);
+
+       combinedSeed = ((miniseed1 ^ miniseed2_reversed) << 12) |
+                      (miniseed2 ^ miniseed3_reversed);
+
+       /* Seeds can not be zero */
+       if ((combinedSeed & NVREG_BKOFFCTRL_SEED_MASK) == 0)
+               combinedSeed |= 0x08;
+       if ((combinedSeed & (NVREG_BKOFFCTRL_SEED_MASK << NVREG_BKOFFCTRL_GEAR)) == 0)
+               combinedSeed |= 0x8000;
+
+       /* No need to disable tx here */
+       temp = NVREG_BKOFFCTRL_DEFAULT | (0 << NVREG_BKOFFCTRL_SELECT);
+       temp |= combinedSeed & NVREG_BKOFFCTRL_SEED_MASK;
+       temp |= combinedSeed >> NVREG_BKOFFCTRL_GEAR;
+       writel(temp,base + NvRegBackOffControl);
+
+       /* Setup seeds for all gear LFSRs. */
+       get_random_bytes(&seedset, sizeof(seedset));
+       seedset = seedset % BACKOFF_SEEDSET_ROWS;
+       for (i = 1; i <= BACKOFF_SEEDSET_LFSRS; i++)
+       {
+               temp = NVREG_BKOFFCTRL_DEFAULT | (i << NVREG_BKOFFCTRL_SELECT);
+               temp |= main_seedset[seedset][i-1] & 0x3ff;
+               temp |= ((gear_seedset[seedset][i-1] & 0x3ff) << NVREG_BKOFFCTRL_GEAR);
+               writel(temp, base + NvRegBackOffControl);
+       }
+}
+
 /*
  * nv_start_xmit: dev->hard_start_xmit function
  * Called with netif_tx_lock held.
@@ -2088,6 +2306,8 @@ static void nv_tx_done(struct net_device *dev)
                                                dev->stats.tx_fifo_errors++;
                                        if (flags & NV_TX_CARRIERLOST)
                                                dev->stats.tx_carrier_errors++;
+                                       if ((flags & NV_TX_RETRYERROR) && !(flags & NV_TX_RETRYCOUNT_MASK))
+                                               nv_legacybackoff_reseed(dev);
                                        dev->stats.tx_errors++;
                                } else {
                                        dev->stats.tx_packets++;
@@ -2103,6 +2323,8 @@ static void nv_tx_done(struct net_device *dev)
                                                dev->stats.tx_fifo_errors++;
                                        if (flags & NV_TX2_CARRIERLOST)
                                                dev->stats.tx_carrier_errors++;
+                                       if ((flags & NV_TX2_RETRYERROR) && !(flags & NV_TX2_RETRYCOUNT_MASK))
+                                               nv_legacybackoff_reseed(dev);
                                        dev->stats.tx_errors++;
                                } else {
                                        dev->stats.tx_packets++;
@@ -2144,6 +2366,15 @@ static void nv_tx_done_optimized(struct net_device *dev, int limit)
                if (flags & NV_TX2_LASTPACKET) {
                        if (!(flags & NV_TX2_ERROR))
                                dev->stats.tx_packets++;
+                       else {
+                               if ((flags & NV_TX2_RETRYERROR) && !(flags & NV_TX2_RETRYCOUNT_MASK)) {
+                                       if (np->driver_data & DEV_HAS_GEAR_MODE)
+                                               nv_gear_backoff_reseed(dev);
+                                       else
+                                               nv_legacybackoff_reseed(dev);
+                               }
+                       }
+
                        dev_kfree_skb_any(np->get_tx_ctx->skb);
                        np->get_tx_ctx->skb = NULL;
 
@@ -2905,15 +3136,14 @@ set_speed:
        }
 
        if (np->gigabit == PHY_GIGABIT) {
-               phyreg = readl(base + NvRegRandomSeed);
+               phyreg = readl(base + NvRegSlotTime);
                phyreg &= ~(0x3FF00);
-               if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10)
-                       phyreg |= NVREG_RNDSEED_FORCE3;
-               else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
-                       phyreg |= NVREG_RNDSEED_FORCE2;
+               if (((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10) ||
+                   ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100))
+                       phyreg |= NVREG_SLOTTIME_10_100_FULL;
                else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
-                       phyreg |= NVREG_RNDSEED_FORCE;
-               writel(phyreg, base + NvRegRandomSeed);
+                       phyreg |= NVREG_SLOTTIME_1000_FULL;
+               writel(phyreg, base + NvRegSlotTime);
        }
 
        phyreg = readl(base + NvRegPhyInterface);
@@ -4843,6 +5073,7 @@ static int nv_open(struct net_device *dev)
        u8 __iomem *base = get_hwbase(dev);
        int ret = 1;
        int oom, i;
+       u32 low;
 
        dprintk(KERN_DEBUG "nv_open: begin\n");
 
@@ -4902,8 +5133,20 @@ static int nv_open(struct net_device *dev)
        writel(np->rx_buf_sz, base + NvRegOffloadConfig);
 
        writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus);
-       get_random_bytes(&i, sizeof(i));
-       writel(NVREG_RNDSEED_FORCE | (i&NVREG_RNDSEED_MASK), base + NvRegRandomSeed);
+
+       get_random_bytes(&low, sizeof(low));
+       low &= NVREG_SLOTTIME_MASK;
+       if (np->desc_ver == DESC_VER_1) {
+               writel(low|NVREG_SLOTTIME_DEFAULT, base + NvRegSlotTime);
+       } else {
+               if (!(np->driver_data & DEV_HAS_GEAR_MODE)) {
+                       /* setup legacy backoff */
+                       writel(NVREG_SLOTTIME_LEGBF_ENABLED|NVREG_SLOTTIME_10_100_FULL|low, base + NvRegSlotTime);
+               } else {
+                       writel(NVREG_SLOTTIME_10_100_FULL, base + NvRegSlotTime);
+                       nv_gear_backoff_reseed(dev);
+               }
+       }
        writel(NVREG_TX_DEFERRAL_DEFAULT, base + NvRegTxDeferral);
        writel(NVREG_RX_DEFERRAL_DEFAULT, base + NvRegRxDeferral);
        if (poll_interval == -1) {
@@ -5110,6 +5353,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
 
        /* copy of driver data */
        np->driver_data = id->driver_data;
+       /* copy of device id */
+       np->device_id = id->device;
 
        /* handle different descriptor versions */
        if (id->driver_data & DEV_HAS_HIGH_DMA) {
@@ -5399,6 +5644,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                        pci_name(pci_dev), id1, id2, phyaddr);
                np->phyaddr = phyaddr;
                np->phy_oui = id1 | id2;
+
+               /* Realtek hardcoded phy id1 to all zero's on certain phys */
+               if (np->phy_oui == PHY_OUI_REALTEK2)
+                       np->phy_oui = PHY_OUI_REALTEK;
+               /* Setup phy revision for Realtek */
+               if (np->phy_oui == PHY_OUI_REALTEK && np->phy_model == PHY_MODEL_REALTEK_8211)
+                       np->phy_rev = mii_rw(dev, phyaddr, MII_RESV1, MII_READ) & PHY_REV_MASK;
+
                break;
        }
        if (i == 33) {
@@ -5477,6 +5730,28 @@ out:
        return err;
 }
 
+static void nv_restore_phy(struct net_device *dev)
+{
+       struct fe_priv *np = netdev_priv(dev);
+       u16 phy_reserved, mii_control;
+
+       if (np->phy_oui == PHY_OUI_REALTEK &&
+           np->phy_model == PHY_MODEL_REALTEK_8201 &&
+           phy_cross == NV_CROSSOVER_DETECTION_DISABLED) {
+               mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3);
+               phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, MII_READ);
+               phy_reserved &= ~PHY_REALTEK_INIT_MSK1;
+               phy_reserved |= PHY_REALTEK_INIT8;
+               mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, phy_reserved);
+               mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1);
+
+               /* restart auto negotiation */
+               mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
+               mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE);
+               mii_rw(dev, np->phyaddr, MII_BMCR, mii_control);
+       }
+}
+
 static void __devexit nv_remove(struct pci_dev *pci_dev)
 {
        struct net_device *dev = pci_get_drvdata(pci_dev);
@@ -5493,6 +5768,9 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
        writel(readl(base + NvRegTransmitPoll) & ~NVREG_TRANSMITPOLL_MAC_ADDR_REV,
               base + NvRegTransmitPoll);
 
+       /* restore any phy related changes */
+       nv_restore_phy(dev);
+
        /* free all structures */
        free_rings(dev);
        iounmap(get_hwbase(dev));
@@ -5632,83 +5910,83 @@ static struct pci_device_id pci_tbl[] = {
        },
        {       /* MCP65 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP65 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP65 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP65 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP67 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP67 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP67 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP67 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP73 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_28),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP73 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_29),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP73 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_30),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP73 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_31),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP77 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_32),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP77 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_33),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP77 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_34),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP77 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP79 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP79 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP79 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP79 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {0,},
 };
@@ -5744,6 +6022,8 @@ module_param(msix, int, 0);
 MODULE_PARM_DESC(msix, "MSIX interrupts are enabled by setting to 1 and disabled by setting to 0.");
 module_param(dma_64bit, int, 0);
 MODULE_PARM_DESC(dma_64bit, "High DMA is enabled by setting to 1 and disabled by setting to 0.");
+module_param(phy_cross, int, 0);
+MODULE_PARM_DESC(phy_cross, "Phy crossover detection for Realtek 8201 phy is enabled by setting to 1 and disabled by setting to 0.");
 
 MODULE_AUTHOR("Manfred Spraul <manfred@colorfullife.com>");
 MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver");
index c8c3df737d73582ebe15484c898ff0f2a9ac5666..99a4b990939f7720780e02da49d822dbdf2b9abd 100644 (file)
@@ -98,7 +98,6 @@
 #include "gianfar_mii.h"
 
 #define TX_TIMEOUT      (1*HZ)
-#define SKB_ALLOC_TIMEOUT 1000000
 #undef BRIEF_GFAR_ERRORS
 #undef VERBOSE_GFAR_ERRORS
 
@@ -115,7 +114,9 @@ static int gfar_enet_open(struct net_device *dev);
 static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void gfar_timeout(struct net_device *dev);
 static int gfar_close(struct net_device *dev);
-struct sk_buff *gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp);
+struct sk_buff *gfar_new_skb(struct net_device *dev);
+static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp,
+               struct sk_buff *skb);
 static int gfar_set_mac_address(struct net_device *dev);
 static int gfar_change_mtu(struct net_device *dev, int new_mtu);
 static irqreturn_t gfar_error(int irq, void *dev_id);
@@ -783,14 +784,21 @@ int startup_gfar(struct net_device *dev)
 
        rxbdp = priv->rx_bd_base;
        for (i = 0; i < priv->rx_ring_size; i++) {
-               struct sk_buff *skb = NULL;
+               struct sk_buff *skb;
 
-               rxbdp->status = 0;
+               skb = gfar_new_skb(dev);
 
-               skb = gfar_new_skb(dev, rxbdp);
+               if (!skb) {
+                       printk(KERN_ERR "%s: Can't allocate RX buffers\n",
+                                       dev->name);
+
+                       goto err_rxalloc_fail;
+               }
 
                priv->rx_skbuff[i] = skb;
 
+               gfar_new_rxbdp(dev, rxbdp, skb);
+
                rxbdp++;
        }
 
@@ -916,6 +924,7 @@ rx_irq_fail:
 tx_irq_fail:
        free_irq(priv->interruptError, dev);
 err_irq_fail:
+err_rxalloc_fail:      
 rx_skb_fail:
        free_skb_resources(priv);
 tx_skb_fail:
@@ -1328,18 +1337,37 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
+static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp,
+               struct sk_buff *skb)
+{
+       struct gfar_private *priv = netdev_priv(dev);
+       u32 * status_len = (u32 *)bdp;
+       u16 flags;
+
+       bdp->bufPtr = dma_map_single(&dev->dev, skb->data,
+                       priv->rx_buffer_size, DMA_FROM_DEVICE);
+
+       flags = RXBD_EMPTY | RXBD_INTERRUPT;
+
+       if (bdp == priv->rx_bd_base + priv->rx_ring_size - 1)
+               flags |= RXBD_WRAP;
+
+       eieio();
+
+       *status_len = (u32)flags << 16;
+}
+
+
+struct sk_buff * gfar_new_skb(struct net_device *dev)
 {
        unsigned int alignamount;
        struct gfar_private *priv = netdev_priv(dev);
        struct sk_buff *skb = NULL;
-       unsigned int timeout = SKB_ALLOC_TIMEOUT;
 
        /* We have to allocate the skb, so keep trying till we succeed */
-       while ((!skb) && timeout--)
-               skb = dev_alloc_skb(priv->rx_buffer_size + RXBUF_ALIGNMENT);
+       skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT);
 
-       if (NULL == skb)
+       if (!skb)
                return NULL;
 
        alignamount = RXBUF_ALIGNMENT -
@@ -1350,15 +1378,6 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
         */
        skb_reserve(skb, alignamount);
 
-       bdp->bufPtr = dma_map_single(&dev->dev, skb->data,
-                       priv->rx_buffer_size, DMA_FROM_DEVICE);
-
-       bdp->length = 0;
-
-       /* Mark the buffer empty */
-       eieio();
-       bdp->status |= (RXBD_EMPTY | RXBD_INTERRUPT);
-
        return skb;
 }
 
@@ -1544,10 +1563,31 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
        bdp = priv->cur_rx;
 
        while (!((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))) {
+               struct sk_buff *newskb;
                rmb();
+
+               /* Add another skb for the future */
+               newskb = gfar_new_skb(dev);
+
                skb = priv->rx_skbuff[priv->skb_currx];
 
-               if ((bdp->status & RXBD_LAST) && !(bdp->status & RXBD_ERR)) {
+               /* We drop the frame if we failed to allocate a new buffer */
+               if (unlikely(!newskb || !(bdp->status & RXBD_LAST) ||
+                                bdp->status & RXBD_ERR)) {
+                       count_errors(bdp->status, dev);
+
+                       if (unlikely(!newskb))
+                               newskb = skb;
+
+                       if (skb) {
+                               dma_unmap_single(&priv->dev->dev,
+                                               bdp->bufPtr,
+                                               priv->rx_buffer_size,
+                                               DMA_FROM_DEVICE);
+
+                               dev_kfree_skb_any(skb);
+                       }
+               } else {
                        /* Increment the number of packets */
                        dev->stats.rx_packets++;
                        howmany++;
@@ -1558,23 +1598,14 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
                        gfar_process_frame(dev, skb, pkt_len);
 
                        dev->stats.rx_bytes += pkt_len;
-               } else {
-                       count_errors(bdp->status, dev);
-
-                       if (skb)
-                               dev_kfree_skb_any(skb);
-
-                       priv->rx_skbuff[priv->skb_currx] = NULL;
                }
 
                dev->last_rx = jiffies;
 
-               /* Clear the status flags for this buffer */
-               bdp->status &= ~RXBD_STATS;
+               priv->rx_skbuff[priv->skb_currx] = newskb;
 
-               /* Add another skb for the future */
-               skb = gfar_new_skb(dev, bdp);
-               priv->rx_skbuff[priv->skb_currx] = skb;
+               /* Setup the new bdp */
+               gfar_new_rxbdp(dev, bdp, newskb);
 
                /* Update to the next pointer */
                if (bdp->status & RXBD_WRAP)
@@ -1584,9 +1615,8 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
 
                /* update to point at the next skb */
                priv->skb_currx =
-                   (priv->skb_currx +
-                    1) & RX_RING_MOD_MASK(priv->rx_ring_size);
-
+                   (priv->skb_currx + 1) &
+                   RX_RING_MOD_MASK(priv->rx_ring_size);
        }
 
        /* Update the current rxbd pointer to be the next one */
@@ -2001,12 +2031,16 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:fsl-gianfar");
+
 /* Structure for a device driver */
 static struct platform_driver gfar_driver = {
        .probe = gfar_probe,
        .remove = gfar_remove,
        .driver = {
                .name = "fsl-gianfar",
+               .owner = THIS_MODULE,
        },
 };
 
index 378a239634955163fdf6e991725179746ea651a1..5d2108c5ac7c872d32409de44edc22f07bf5620e 100644 (file)
@@ -43,6 +43,8 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
+#include <asm/dcr.h>
+#include <asm/dcr-regs.h>
 
 #include "core.h"
 
@@ -127,10 +129,35 @@ static struct device_node *emac_boot_list[EMAC_BOOT_LIST_SIZE];
 static inline void emac_report_timeout_error(struct emac_instance *dev,
                                             const char *error)
 {
-       if (net_ratelimit())
+       if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX |
+                                 EMAC_FTR_440EP_PHY_CLK_FIX))
+               DBG(dev, "%s" NL, error);
+       else if (net_ratelimit())
                printk(KERN_ERR "%s: %s\n", dev->ndev->name, error);
 }
 
+/* EMAC PHY clock workaround:
+ * 440EP/440GR has more sane SDR0_MFR register implementation than 440GX,
+ * which allows controlling each EMAC clock
+ */
+static inline void emac_rx_clk_tx(struct emac_instance *dev)
+{
+#ifdef CONFIG_PPC_DCR_NATIVE
+       if (emac_has_feature(dev, EMAC_FTR_440EP_PHY_CLK_FIX))
+               dcri_clrset(SDR0, SDR0_MFR,
+                           0, SDR0_MFR_ECS >> dev->cell_index);
+#endif
+}
+
+static inline void emac_rx_clk_default(struct emac_instance *dev)
+{
+#ifdef CONFIG_PPC_DCR_NATIVE
+       if (emac_has_feature(dev, EMAC_FTR_440EP_PHY_CLK_FIX))
+               dcri_clrset(SDR0, SDR0_MFR,
+                           SDR0_MFR_ECS >> dev->cell_index, 0);
+#endif
+}
+
 /* PHY polling intervals */
 #define PHY_POLL_LINK_ON       HZ
 #define PHY_POLL_LINK_OFF      (HZ / 5)
@@ -524,7 +551,10 @@ static int emac_configure(struct emac_instance *dev)
                rx_size = dev->rx_fifo_size_gige;
 
                if (dev->ndev->mtu > ETH_DATA_LEN) {
-                       mr1 |= EMAC_MR1_JPSM;
+                       if (emac_has_feature(dev, EMAC_FTR_EMAC4))
+                               mr1 |= EMAC4_MR1_JPSM;
+                       else
+                               mr1 |= EMAC_MR1_JPSM;
                        dev->stop_timeout = STOP_TIMEOUT_1000_JUMBO;
                } else
                        dev->stop_timeout = STOP_TIMEOUT_1000;
@@ -708,7 +738,7 @@ static int __emac_mdio_read(struct emac_instance *dev, u8 id, u8 reg)
                rgmii_get_mdio(dev->rgmii_dev, dev->rgmii_port);
 
        /* Wait for management interface to become idle */
-       n = 10;
+       n = 20;
        while (!emac_phy_done(dev, in_be32(&p->stacr))) {
                udelay(1);
                if (!--n) {
@@ -733,7 +763,7 @@ static int __emac_mdio_read(struct emac_instance *dev, u8 id, u8 reg)
        out_be32(&p->stacr, r);
 
        /* Wait for read to complete */
-       n = 100;
+       n = 200;
        while (!emac_phy_done(dev, (r = in_be32(&p->stacr)))) {
                udelay(1);
                if (!--n) {
@@ -780,7 +810,7 @@ static void __emac_mdio_write(struct emac_instance *dev, u8 id, u8 reg,
                rgmii_get_mdio(dev->rgmii_dev, dev->rgmii_port);
 
        /* Wait for management interface to be idle */
-       n = 10;
+       n = 20;
        while (!emac_phy_done(dev, in_be32(&p->stacr))) {
                udelay(1);
                if (!--n) {
@@ -806,7 +836,7 @@ static void __emac_mdio_write(struct emac_instance *dev, u8 id, u8 reg,
        out_be32(&p->stacr, r);
 
        /* Wait for write to complete */
-       n = 100;
+       n = 200;
        while (!emac_phy_done(dev, in_be32(&p->stacr))) {
                udelay(1);
                if (!--n) {
@@ -1094,9 +1124,11 @@ static int emac_open(struct net_device *ndev)
                int link_poll_interval;
                if (dev->phy.def->ops->poll_link(&dev->phy)) {
                        dev->phy.def->ops->read_link(&dev->phy);
+                       emac_rx_clk_default(dev);
                        netif_carrier_on(dev->ndev);
                        link_poll_interval = PHY_POLL_LINK_ON;
                } else {
+                       emac_rx_clk_tx(dev);
                        netif_carrier_off(dev->ndev);
                        link_poll_interval = PHY_POLL_LINK_OFF;
                }
@@ -1174,6 +1206,7 @@ static void emac_link_timer(struct work_struct *work)
 
        if (dev->phy.def->ops->poll_link(&dev->phy)) {
                if (!netif_carrier_ok(dev->ndev)) {
+                       emac_rx_clk_default(dev);
                        /* Get new link parameters */
                        dev->phy.def->ops->read_link(&dev->phy);
 
@@ -1186,6 +1219,7 @@ static void emac_link_timer(struct work_struct *work)
                link_poll_interval = PHY_POLL_LINK_ON;
        } else {
                if (netif_carrier_ok(dev->ndev)) {
+                       emac_rx_clk_tx(dev);
                        netif_carrier_off(dev->ndev);
                        netif_tx_disable(dev->ndev);
                        emac_reinitialize(dev);
@@ -2237,7 +2271,7 @@ static int __devinit emac_of_bus_notify(struct notifier_block *nb,
        return 0;
 }
 
-static struct notifier_block emac_of_bus_notifier = {
+static struct notifier_block emac_of_bus_notifier __devinitdata = {
        .notifier_call = emac_of_bus_notify
 };
 
@@ -2330,6 +2364,19 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
        dev->phy.mdio_read = emac_mdio_read;
        dev->phy.mdio_write = emac_mdio_write;
 
+       /* Enable internal clock source */
+#ifdef CONFIG_PPC_DCR_NATIVE
+       if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX))
+               dcri_clrset(SDR0, SDR0_MFR, 0, SDR0_MFR_ECS);
+#endif
+       /* PHY clock workaround */
+       emac_rx_clk_tx(dev);
+
+       /* Enable internal clock source on 440GX*/
+#ifdef CONFIG_PPC_DCR_NATIVE
+       if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX))
+               dcri_clrset(SDR0, SDR0_MFR, 0, SDR0_MFR_ECS);
+#endif
        /* Configure EMAC with defaults so we can at least use MDIO
         * This is needed mostly for 440GX
         */
@@ -2362,6 +2409,12 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
                        if (!emac_mii_phy_probe(&dev->phy, i))
                                break;
                }
+
+       /* Enable external clock source */
+#ifdef CONFIG_PPC_DCR_NATIVE
+       if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX))
+               dcri_clrset(SDR0, SDR0_MFR, SDR0_MFR_ECS, 0);
+#endif
        mutex_unlock(&emac_phy_map_lock);
        if (i == 0x20) {
                printk(KERN_WARNING "%s: can't find PHY!\n", np->full_name);
@@ -2487,8 +2540,15 @@ static int __devinit emac_init_config(struct emac_instance *dev)
        }
 
        /* Check EMAC version */
-       if (of_device_is_compatible(np, "ibm,emac4"))
+       if (of_device_is_compatible(np, "ibm,emac4")) {
                dev->features |= EMAC_FTR_EMAC4;
+               if (of_device_is_compatible(np, "ibm,emac-440gx"))
+                       dev->features |= EMAC_FTR_440GX_PHY_CLK_FIX;
+       } else {
+               if (of_device_is_compatible(np, "ibm,emac-440ep") ||
+                   of_device_is_compatible(np, "ibm,emac-440gr"))
+                       dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
+       }
 
        /* Fixup some feature bits based on the device tree */
        if (of_get_property(np, "has-inverted-stacr-oc", NULL))
@@ -2559,8 +2619,11 @@ static int __devinit emac_probe(struct of_device *ofdev,
        struct device_node **blist = NULL;
        int err, i;
 
-       /* Skip unused/unwired EMACS */
-       if (of_get_property(np, "unused", NULL))
+       /* Skip unused/unwired EMACS.  We leave the check for an unused
+        * property here for now, but new flat device trees should set a
+        * status property to "disabled" instead.
+        */
+       if (of_get_property(np, "unused", NULL) || !of_device_is_available(np))
                return -ENODEV;
 
        /* Find ourselves in the bootlist if we are there */
index 4e74d8287c65b91d25a6a95ff36de8a0d2d16a6b..1683db9870a467fdba8d591bb086c447791598d5 100644 (file)
@@ -301,6 +301,14 @@ struct emac_instance {
  * Set if we have new type STACR with STAOPC
  */
 #define EMAC_FTR_HAS_NEW_STACR         0x00000040
+/*
+ * Set if we need phy clock workaround for 440gx
+ */
+#define EMAC_FTR_440GX_PHY_CLK_FIX     0x00000080
+/*
+ * Set if we need phy clock workaround for 440ep or 440gr
+ */
+#define EMAC_FTR_440EP_PHY_CLK_FIX     0x00000100
 
 
 /* Right now, we don't quite handle the always/possible masks on the
@@ -312,8 +320,8 @@ enum {
 
        EMAC_FTRS_POSSIBLE      =
 #ifdef CONFIG_IBM_NEW_EMAC_EMAC4
-           EMAC_FTR_EMAC4      | EMAC_FTR_HAS_NEW_STACR        |
-           EMAC_FTR_STACR_OC_INVERT    |
+           EMAC_FTR_EMAC4 | EMAC_FTR_HAS_NEW_STACR |
+           EMAC_FTR_STACR_OC_INVERT | EMAC_FTR_440GX_PHY_CLK_FIX |
 #endif
 #ifdef CONFIG_IBM_NEW_EMAC_TAH
            EMAC_FTR_HAS_TAH    |
@@ -324,7 +332,7 @@ enum {
 #ifdef CONFIG_IBM_NEW_EMAC_RGMII
            EMAC_FTR_HAS_RGMII  |
 #endif
-           0,
+       EMAC_FTR_440EP_PHY_CLK_FIX,
 };
 
 static inline int emac_has_feature(struct emac_instance *dev,
index 6869f08c9dcba0188b920524e68c747d1445fb9f..10c267b2b9610b1e446a4fe32e4deba9c5700976 100644 (file)
@@ -61,8 +61,8 @@ int __devinit mal_register_commac(struct mal_instance *mal,
        return 0;
 }
 
-void __devexit mal_unregister_commac(struct mal_instance       *mal,
-                                    struct mal_commac          *commac)
+void mal_unregister_commac(struct mal_instance *mal,
+               struct mal_commac *commac)
 {
        unsigned long flags;
 
@@ -136,6 +136,14 @@ void mal_enable_rx_channel(struct mal_instance *mal, int channel)
 {
        unsigned long flags;
 
+       /*
+        * On some 4xx PPC's (e.g. 460EX/GT), the rx channel is a multiple
+        * of 8, but enabling in MAL_RXCASR needs the divided by 8 value
+        * for the bitmask
+        */
+       if (!(channel % 8))
+               channel >>= 3;
+
        spin_lock_irqsave(&mal->lock, flags);
 
        MAL_DBG(mal, "enable_rx(%d)" NL, channel);
@@ -148,6 +156,14 @@ void mal_enable_rx_channel(struct mal_instance *mal, int channel)
 
 void mal_disable_rx_channel(struct mal_instance *mal, int channel)
 {
+       /*
+        * On some 4xx PPC's (e.g. 460EX/GT), the rx channel is a multiple
+        * of 8, but enabling in MAL_RXCASR needs the divided by 8 value
+        * for the bitmask
+        */
+       if (!(channel % 8))
+               channel >>= 3;
+
        set_mal_dcrn(mal, MAL_RXCARR, MAL_CHAN_MASK(channel));
 
        MAL_DBG(mal, "disable_rx(%d)" NL, channel);
index 5757788227be8d887537b21fbaf97dd7853f55c0..e32da3de2695de79564bfcfa5707d48b507c0ebd 100644 (file)
@@ -179,7 +179,7 @@ void rgmii_put_mdio(struct of_device *ofdev, int input)
        mutex_unlock(&dev->lock);
 }
 
-void __devexit rgmii_detach(struct of_device *ofdev, int input)
+void rgmii_detach(struct of_device *ofdev, int input)
 {
        struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
        struct rgmii_regs __iomem *p = dev->base;
index b023d10d7e1c2d14ecac3f61e3af4d6501392ff1..30173a9fb557d930f543d0c237f3fff0a5cb777b 100644 (file)
@@ -35,7 +35,7 @@ int __devinit tah_attach(struct of_device *ofdev, int channel)
        return 0;
 }
 
-void __devexit tah_detach(struct of_device *ofdev, int channel)
+void tah_detach(struct of_device *ofdev, int channel)
 {
        struct tah_instance *dev = dev_get_drvdata(&ofdev->dev);
 
index 2ea472aeab06ac8c03deb714853024b8cce265f1..17b154124943e5baf89e6640f26643ade28be72c 100644 (file)
@@ -189,7 +189,7 @@ void zmii_set_speed(struct of_device *ofdev, int input, int speed)
        mutex_unlock(&dev->lock);
 }
 
-void __devexit zmii_detach(struct of_device *ofdev, int input)
+void zmii_detach(struct of_device *ofdev, int input)
 {
        struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
 
index aaee02e9e3f03c4bc0da116942964996fe061fda..ae398f04c7b44d8ef8865ed4f902dba1d12a0172 100644 (file)
@@ -871,6 +871,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
                goto err_pci_reg;
 
        pci_set_master(pdev);
+       pci_save_state(pdev);
 
        err = -ENOMEM;
        netdev = alloc_etherdev(sizeof(struct igb_adapter));
@@ -4079,6 +4080,7 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev)
                return PCI_ERS_RESULT_DISCONNECT;
        }
        pci_set_master(pdev);
+       pci_restore_state(pdev);
 
        pci_enable_wake(pdev, PCI_D3hot, 0);
        pci_enable_wake(pdev, PCI_D3cold, 0);
index 9f584521304a8a84ce5e8230f43df2fa72def8b3..083b0dd70fef1f1431e284b0aa7aa864047711b8 100644 (file)
@@ -60,6 +60,7 @@ static struct platform_driver ali_ircc_driver = {
        .resume         = ali_ircc_resume,
        .driver         = {
                .name   = ALI_IRCC_DRIVER_NAME,
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -2256,6 +2257,7 @@ static void FIR2SIR(int iobase)
 MODULE_AUTHOR("Benjamin Kong <benjamin_kong@ali.com.tw>");
 MODULE_DESCRIPTION("ALi FIR Controller Driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" ALI_IRCC_DRIVER_NAME);
 
 
 module_param_array(io, int, NULL, 0);
index 8db71ab20456b38d14ce1f8e5cd4e1e8e4c87ecf..d5c2d27f3ea4d12c8b29a7aac0f1426303f8dc42 100644 (file)
@@ -908,6 +908,7 @@ static int pxa_irda_remove(struct platform_device *_dev)
 static struct platform_driver pxa_ir_driver = {
        .driver         = {
                .name   = "pxa2xx-ir",
+               .owner  = THIS_MODULE,
        },
        .probe          = pxa_irda_probe,
        .remove         = pxa_irda_remove,
@@ -929,3 +930,4 @@ module_init(pxa_irda_init);
 module_exit(pxa_irda_exit);
 
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-ir");
index 056639f72becf049657601585f82e83c0c20a6a1..1bc8518f9197d9a00293766bc953990341b5b26f 100644 (file)
@@ -1008,6 +1008,7 @@ static struct platform_driver sa1100ir_driver = {
        .resume         = sa1100_irda_resume,
        .driver         = {
                .name   = "sa11x0-ir",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -1041,3 +1042,4 @@ MODULE_LICENSE("GPL");
 MODULE_PARM_DESC(power_level, "IrDA power level, 1 (low) to 3 (high)");
 MODULE_PARM_DESC(tx_lpm, "Enable transmitter low power (1.6us) mode");
 MODULE_PARM_DESC(max_rate, "Maximum baud rate (4000000, 115200, 57600, 38400, 19200, 9600)");
+MODULE_ALIAS("platform:sa11x0-ir");
index cb371a8c24a72244092b4353757a1e886dd4d91a..7b859220c255b3b81017f156548df2dcca2f32e7 100644 (file)
@@ -3431,6 +3431,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
        }
 
        pci_set_master(pdev);
+       pci_save_state(pdev);
 
 #ifdef CONFIG_NETDEVICES_MULTIQUEUE
        netdev = alloc_etherdev_mq(sizeof(struct ixgbe_adapter), MAX_TX_QUEUES);
@@ -3721,6 +3722,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev)
                return PCI_ERS_RESULT_DISCONNECT;
        }
        pci_set_master(pdev);
+       pci_restore_state(pdev);
 
        pci_enable_wake(pdev, PCI_D3hot, 0);
        pci_enable_wake(pdev, PCI_D3cold, 0);
index 5c154fe1385956d2797a8946000397b4558631a0..07944820f74582b5230c4a362acac0b81eccbec6 100644 (file)
@@ -249,6 +249,7 @@ out:
 MODULE_DESCRIPTION("Jazz SONIC ethernet driver");
 module_param(sonic_debug, int, 0);
 MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)");
+MODULE_ALIAS("platform:jazzsonic");
 
 #include "sonic.c"
 
@@ -271,6 +272,7 @@ static struct platform_driver jazz_sonic_driver = {
        .remove = __devexit_p(jazz_sonic_device_remove),
        .driver = {
                .name   = jazz_sonic_string,
+               .owner  = THIS_MODULE,
        },
 };
 
index 1d24a73a0e1a1d268c1d319bcd3625a63d5d47da..e18576316bda93050cdd5849da80ef67cd85333a 100644 (file)
@@ -883,7 +883,7 @@ static int korina_init(struct net_device *dev)
 static int korina_restart(struct net_device *dev)
 {
        struct korina_private *lp = netdev_priv(dev);
-       int ret = 0;
+       int ret;
 
        /*
         * Disable interrupts
@@ -987,7 +987,7 @@ static void korina_poll_controller(struct net_device *dev)
 static int korina_open(struct net_device *dev)
 {
        struct korina_private *lp = netdev_priv(dev);
-       int ret = 0;
+       int ret;
 
        /* Initialize */
        ret = korina_init(dev);
@@ -1031,6 +1031,8 @@ static int korina_open(struct net_device *dev)
                    dev->name, lp->und_irq);
                goto err_free_ovr_irq;
        }
+out:
+       return ret;
 
 err_free_ovr_irq:
        free_irq(lp->ovr_irq, dev);
@@ -1041,8 +1043,6 @@ err_free_rx_irq:
 err_release:
        korina_free_ring(dev);
        goto out;
-out:
-       return ret;
 }
 
 static int korina_close(struct net_device *dev)
@@ -1082,7 +1082,7 @@ static int korina_probe(struct platform_device *pdev)
        struct korina_private *lp;
        struct net_device *dev;
        struct resource *r;
-       int retval, err;
+       int rc;
 
        dev = alloc_etherdev(sizeof(struct korina_private));
        if (!dev) {
@@ -1106,7 +1106,7 @@ static int korina_probe(struct platform_device *pdev)
        lp->eth_regs = ioremap_nocache(r->start, r->end - r->start);
        if (!lp->eth_regs) {
                printk(KERN_ERR DRV_NAME "cannot remap registers\n");
-               retval = -ENXIO;
+               rc = -ENXIO;
                goto probe_err_out;
        }
 
@@ -1114,7 +1114,7 @@ static int korina_probe(struct platform_device *pdev)
        lp->rx_dma_regs = ioremap_nocache(r->start, r->end - r->start);
        if (!lp->rx_dma_regs) {
                printk(KERN_ERR DRV_NAME "cannot remap Rx DMA registers\n");
-               retval = -ENXIO;
+               rc = -ENXIO;
                goto probe_err_dma_rx;
        }
 
@@ -1122,14 +1122,14 @@ static int korina_probe(struct platform_device *pdev)
        lp->tx_dma_regs = ioremap_nocache(r->start, r->end - r->start);
        if (!lp->tx_dma_regs) {
                printk(KERN_ERR DRV_NAME "cannot remap Tx DMA registers\n");
-               retval = -ENXIO;
+               rc = -ENXIO;
                goto probe_err_dma_tx;
        }
 
        lp->td_ring = kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL);
        if (!lp->td_ring) {
                printk(KERN_ERR DRV_NAME "cannot allocate descriptors\n");
-               retval = -ENOMEM;
+               rc = -ENXIO;
                goto probe_err_td_ring;
        }
 
@@ -1166,14 +1166,14 @@ static int korina_probe(struct platform_device *pdev)
        lp->mii_if.phy_id_mask = 0x1f;
        lp->mii_if.reg_num_mask = 0x1f;
 
-       err = register_netdev(dev);
-       if (err) {
+       rc = register_netdev(dev);
+       if (rc < 0) {
                printk(KERN_ERR DRV_NAME
-                       ": cannot register net device %d\n", err);
-               retval = -EINVAL;
+                       ": cannot register net device %d\n", rc);
                goto probe_err_register;
        }
-       return 0;
+out:
+       return rc;
 
 probe_err_register:
        kfree(lp->td_ring);
@@ -1185,7 +1185,7 @@ probe_err_dma_rx:
        iounmap(lp->eth_regs);
 probe_err_out:
        free_netdev(dev);
-       return retval;
+       goto out;
 }
 
 static int korina_remove(struct platform_device *pdev)
@@ -1193,12 +1193,9 @@ static int korina_remove(struct platform_device *pdev)
        struct korina_device *bif = platform_get_drvdata(pdev);
        struct korina_private *lp = netdev_priv(bif->dev);
 
-       if (lp->eth_regs)
-               iounmap(lp->eth_regs);
-       if (lp->rx_dma_regs)
-               iounmap(lp->rx_dma_regs);
-       if (lp->tx_dma_regs)
-               iounmap(lp->tx_dma_regs);
+       iounmap(lp->eth_regs);
+       iounmap(lp->rx_dma_regs);
+       iounmap(lp->tx_dma_regs);
 
        platform_set_drvdata(pdev, NULL);
        unregister_netdev(bif->dev);
index d513bb8a490210c3dbaac6bfcdcd2d69b77b09de..92dccd43bdcab39fbd0bcd374d3447a33961443c 100644 (file)
@@ -1281,6 +1281,7 @@ static struct platform_driver macb_driver = {
        .remove         = __exit_p(macb_remove),
        .driver         = {
                .name           = "macb",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -1300,3 +1301,4 @@ module_exit(macb_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Atmel MACB Ethernet driver");
 MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
+MODULE_ALIAS("platform:macb");
index cdaa8fc218091a947996280d27c63caa16f56f84..0b32648a213600fcecae9eda9496a63c996b1768 100644 (file)
@@ -830,6 +830,7 @@ static struct platform_driver meth_driver = {
        .remove = __devexit_p(meth_remove),
        .driver = {
                .name   = "meth",
+               .owner  = THIS_MODULE,
        }
 };
 
@@ -855,3 +856,4 @@ module_exit(meth_exit_module);
 MODULE_AUTHOR("Ilya Volynets <ilya@theIlya.com>");
 MODULE_DESCRIPTION("SGI O2 Builtin Fast Ethernet driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:meth");
index 75ef9d0d974dc165e8b5630c28a0affc017a6969..f9d6b4dca180e49f6d16fc4ebfe594831cc0cf29 100644 (file)
@@ -196,3 +196,160 @@ void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf)
        }
 }
 EXPORT_SYMBOL_GPL(mlx4_buf_free);
+
+static struct mlx4_db_pgdir *mlx4_alloc_db_pgdir(struct device *dma_device)
+{
+       struct mlx4_db_pgdir *pgdir;
+
+       pgdir = kzalloc(sizeof *pgdir, GFP_KERNEL);
+       if (!pgdir)
+               return NULL;
+
+       bitmap_fill(pgdir->order1, MLX4_DB_PER_PAGE / 2);
+       pgdir->bits[0] = pgdir->order0;
+       pgdir->bits[1] = pgdir->order1;
+       pgdir->db_page = dma_alloc_coherent(dma_device, PAGE_SIZE,
+                                           &pgdir->db_dma, GFP_KERNEL);
+       if (!pgdir->db_page) {
+               kfree(pgdir);
+               return NULL;
+       }
+
+       return pgdir;
+}
+
+static int mlx4_alloc_db_from_pgdir(struct mlx4_db_pgdir *pgdir,
+                                   struct mlx4_db *db, int order)
+{
+       int o;
+       int i;
+
+       for (o = order; o <= 1; ++o) {
+               i = find_first_bit(pgdir->bits[o], MLX4_DB_PER_PAGE >> o);
+               if (i < MLX4_DB_PER_PAGE >> o)
+                       goto found;
+       }
+
+       return -ENOMEM;
+
+found:
+       clear_bit(i, pgdir->bits[o]);
+
+       i <<= o;
+
+       if (o > order)
+               set_bit(i ^ 1, pgdir->bits[order]);
+
+       db->u.pgdir = pgdir;
+       db->index   = i;
+       db->db      = pgdir->db_page + db->index;
+       db->dma     = pgdir->db_dma  + db->index * 4;
+       db->order   = order;
+
+       return 0;
+}
+
+int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, int order)
+{
+       struct mlx4_priv *priv = mlx4_priv(dev);
+       struct mlx4_db_pgdir *pgdir;
+       int ret = 0;
+
+       mutex_lock(&priv->pgdir_mutex);
+
+       list_for_each_entry(pgdir, &priv->pgdir_list, list)
+               if (!mlx4_alloc_db_from_pgdir(pgdir, db, order))
+                       goto out;
+
+       pgdir = mlx4_alloc_db_pgdir(&(dev->pdev->dev));
+       if (!pgdir) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       list_add(&pgdir->list, &priv->pgdir_list);
+
+       /* This should never fail -- we just allocated an empty page: */
+       WARN_ON(mlx4_alloc_db_from_pgdir(pgdir, db, order));
+
+out:
+       mutex_unlock(&priv->pgdir_mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(mlx4_db_alloc);
+
+void mlx4_db_free(struct mlx4_dev *dev, struct mlx4_db *db)
+{
+       struct mlx4_priv *priv = mlx4_priv(dev);
+       int o;
+       int i;
+
+       mutex_lock(&priv->pgdir_mutex);
+
+       o = db->order;
+       i = db->index;
+
+       if (db->order == 0 && test_bit(i ^ 1, db->u.pgdir->order0)) {
+               clear_bit(i ^ 1, db->u.pgdir->order0);
+               ++o;
+       }
+       i >>= o;
+       set_bit(i, db->u.pgdir->bits[o]);
+
+       if (bitmap_full(db->u.pgdir->order1, MLX4_DB_PER_PAGE / 2)) {
+               dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
+                                 db->u.pgdir->db_page, db->u.pgdir->db_dma);
+               list_del(&db->u.pgdir->list);
+               kfree(db->u.pgdir);
+       }
+
+       mutex_unlock(&priv->pgdir_mutex);
+}
+EXPORT_SYMBOL_GPL(mlx4_db_free);
+
+int mlx4_alloc_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres,
+                      int size, int max_direct)
+{
+       int err;
+
+       err = mlx4_db_alloc(dev, &wqres->db, 1);
+       if (err)
+               return err;
+
+       *wqres->db.db = 0;
+
+       err = mlx4_buf_alloc(dev, size, max_direct, &wqres->buf);
+       if (err)
+               goto err_db;
+
+       err = mlx4_mtt_init(dev, wqres->buf.npages, wqres->buf.page_shift,
+                           &wqres->mtt);
+       if (err)
+               goto err_buf;
+
+       err = mlx4_buf_write_mtt(dev, &wqres->mtt, &wqres->buf);
+       if (err)
+               goto err_mtt;
+
+       return 0;
+
+err_mtt:
+       mlx4_mtt_cleanup(dev, &wqres->mtt);
+err_buf:
+       mlx4_buf_free(dev, size, &wqres->buf);
+err_db:
+       mlx4_db_free(dev, &wqres->db);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_alloc_hwq_res);
+
+void mlx4_free_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres,
+                      int size)
+{
+       mlx4_mtt_cleanup(dev, &wqres->mtt);
+       mlx4_buf_free(dev, size, &wqres->buf);
+       mlx4_db_free(dev, &wqres->db);
+}
+EXPORT_SYMBOL_GPL(mlx4_free_hwq_res);
index caa5bcf54e35a6ee4ab1f033c88a41fb75ead1f3..6fda0af9d0a6e068a3b6d55cf62db88312403f57 100644 (file)
@@ -180,7 +180,7 @@ int mlx4_cq_resize(struct mlx4_dev *dev, struct mlx4_cq *cq,
        cq_context->mtt_base_addr_h = mtt_addr >> 32;
        cq_context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff);
 
-       err = mlx4_MODIFY_CQ(dev, mailbox, cq->cqn, 1);
+       err = mlx4_MODIFY_CQ(dev, mailbox, cq->cqn, 0);
 
        mlx4_free_cmd_mailbox(dev, mailbox);
        return err;
index 49a4acab5e82ab1f5d8f2075af39d953fa414f6f..a6aa49fc1d68a6654d449bcc6fa90a7ad8f40f23 100644 (file)
@@ -798,6 +798,9 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        INIT_LIST_HEAD(&priv->ctx_list);
        spin_lock_init(&priv->ctx_lock);
 
+       INIT_LIST_HEAD(&priv->pgdir_list);
+       mutex_init(&priv->pgdir_mutex);
+
        /*
         * Now reset the HCA before we touch the PCI capabilities or
         * attempt a firmware command, since a boot ROM may have left
index 73336810e6528124005cc576fd74d04b0aeed26e..a4023c2dd05092762ba3f8be32ef9fac5b1a7652 100644 (file)
@@ -257,6 +257,9 @@ struct mlx4_priv {
        struct list_head        ctx_list;
        spinlock_t              ctx_lock;
 
+       struct list_head        pgdir_list;
+       struct mutex            pgdir_mutex;
+
        struct mlx4_fw          fw;
        struct mlx4_cmd         cmd;
 
index fa24e6597591fc0f10ab11158ead02051f884a6d..ee5484c44a1833781887dbbdc42775f5d661bc60 100644 (file)
@@ -299,3 +299,34 @@ int mlx4_qp_query(struct mlx4_dev *dev, struct mlx4_qp *qp,
 }
 EXPORT_SYMBOL_GPL(mlx4_qp_query);
 
+int mlx4_qp_to_ready(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
+                    struct mlx4_qp_context *context,
+                    struct mlx4_qp *qp, enum mlx4_qp_state *qp_state)
+{
+       int err;
+       int i;
+       enum mlx4_qp_state states[] = {
+               MLX4_QP_STATE_RST,
+               MLX4_QP_STATE_INIT,
+               MLX4_QP_STATE_RTR,
+               MLX4_QP_STATE_RTS
+       };
+
+       for (i = 0; i < ARRAY_SIZE(states) - 1; i++) {
+               context->flags &= cpu_to_be32(~(0xf << 28));
+               context->flags |= cpu_to_be32(states[i + 1] << 28);
+               err = mlx4_qp_modify(dev, mtt, states[i], states[i + 1],
+                                    context, 0, 0, qp);
+               if (err) {
+                       mlx4_err(dev, "Failed to bring QP to state: "
+                                "%d with error: %d\n",
+                                states[i + 1], err);
+                       return err;
+               }
+
+               *qp_state = states[i + 1];
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_qp_to_ready);
index 601ffd69ebc8f5b260024c1197f2fdb754ed530b..381b36e5f64c2fe11f559d182b5abab91f0de388 100644 (file)
@@ -2030,6 +2030,7 @@ static struct platform_driver mv643xx_eth_driver = {
        .shutdown = mv643xx_eth_shutdown,
        .driver = {
                .name = MV643XX_ETH_NAME,
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -2038,6 +2039,7 @@ static struct platform_driver mv643xx_eth_shared_driver = {
        .remove = mv643xx_eth_shared_remove,
        .driver = {
                .name = MV643XX_ETH_SHARED_NAME,
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -2085,7 +2087,8 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR( "Rabeeh Khoury, Assaf Hoffman, Matthew Dharm, Manish Lachwani"
                " and Dale Farnsworth");
 MODULE_DESCRIPTION("Ethernet driver for Marvell MV643XX");
-MODULE_ALIAS("platform:mv643xx_eth");
+MODULE_ALIAS("platform:" MV643XX_ETH_NAME);
+MODULE_ALIAS("platform:" MV643XX_ETH_SHARED_NAME);
 
 /*
  * The second part is the low level driver of the gigE ethernet ports.
index 78d34af13a1ca8c59817a3c203b77e715ae6399d..dc442e370850bfb8d6fc73b7db960638ec00661c 100644 (file)
@@ -502,4 +502,4 @@ module_exit(netx_eth_cleanup);
 
 MODULE_AUTHOR("Sascha Hauer, Pengutronix");
 MODULE_LICENSE("GPL");
-
+MODULE_ALIAS("platform:" CARDNAME);
index 05748ca6f216831543574dda76d0778883365865..af7356468251ec4fc5aedb23a263a2cc7f70a1e5 100644 (file)
@@ -1132,8 +1132,8 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
        u32 fw_minor = 0;
        u32 fw_build = 0;
        char brd_name[NETXEN_MAX_SHORT_NAME];
-       struct netxen_new_user_info user_info;
-       int i, addr = NETXEN_USER_START;
+       char serial_num[32];
+       int i, addr;
        __le32 *ptr32;
 
        struct netxen_board_info *board_info = &(adapter->ahw.boardcfg);
@@ -1150,10 +1150,10 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
                valid = 0;
        }
        if (valid) {
-               ptr32 = (u32 *) & user_info;
-               for (i = 0;
-                    i < sizeof(struct netxen_new_user_info) / sizeof(u32);
-                    i++) {
+               ptr32 = (u32 *)&serial_num;
+               addr = NETXEN_USER_START +
+                      offsetof(struct netxen_new_user_info, serial_num);
+               for (i = 0; i < 8; i++) {
                        if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) {
                                printk("%s: ERROR reading %s board userarea.\n",
                                       netxen_nic_driver_name,
@@ -1163,10 +1163,11 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
                        ptr32++;
                        addr += sizeof(u32);
                }
+
                get_brd_name_by_type(board_info->board_type, brd_name);
 
                printk("NetXen %s Board S/N %s  Chip id 0x%x\n",
-                      brd_name, user_info.serial_num, board_info->chip_id);
+                      brd_name, serial_num, board_info->chip_id);
 
                printk("NetXen %s Board #%d, Chip id 0x%x\n",
                       board_info->board_type == 0x0b ? "XGB" : "GBE",
index 7565c2d7f30e9ce956d3e0a5c6009e1da9fb2038..4009c4ce96b4fd609425e8fe3b95d30f38d705a7 100644 (file)
@@ -33,8 +33,8 @@
 
 #define DRV_MODULE_NAME                "niu"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "0.7"
-#define DRV_MODULE_RELDATE     "February 18, 2008"
+#define DRV_MODULE_VERSION     "0.8"
+#define DRV_MODULE_RELDATE     "April 24, 2008"
 
 static char version[] __devinitdata =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -673,11 +673,16 @@ static int serdes_init_10g(struct niu *np)
        }
 
        if ((sig & mask) != val) {
+               if (np->flags & NIU_FLAGS_HOTPLUG_PHY) {
+                       np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
+                       return 0;
+               }
                dev_err(np->device, PFX "Port %u signal bits [%08x] are not "
                        "[%08x]\n", np->port, (int) (sig & mask), (int) val);
                return -ENODEV;
        }
-
+       if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
+               np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT;
        return 0;
 }
 
@@ -998,6 +1003,28 @@ static int bcm8704_user_dev3_readback(struct niu *np, int reg)
        return 0;
 }
 
+static int bcm8706_init_user_dev3(struct niu *np)
+{
+       int err;
+
+
+       err = mdio_read(np, np->phy_addr, BCM8704_USER_DEV3_ADDR,
+                       BCM8704_USER_OPT_DIGITAL_CTRL);
+       if (err < 0)
+               return err;
+       err &= ~USER_ODIG_CTRL_GPIOS;
+       err |= (0x3 << USER_ODIG_CTRL_GPIOS_SHIFT);
+       err |=  USER_ODIG_CTRL_RESV2;
+       err = mdio_write(np, np->phy_addr, BCM8704_USER_DEV3_ADDR,
+                        BCM8704_USER_OPT_DIGITAL_CTRL, err);
+       if (err)
+               return err;
+
+       mdelay(1000);
+
+       return 0;
+}
+
 static int bcm8704_init_user_dev3(struct niu *np)
 {
        int err;
@@ -1127,33 +1154,11 @@ static int xcvr_init_10g_mrvl88x2011(struct niu *np)
                          MRVL88X2011_10G_PMD_TX_DIS, MRVL88X2011_ENA_PMDTX);
 }
 
-static int xcvr_init_10g_bcm8704(struct niu *np)
+
+static int xcvr_diag_bcm870x(struct niu *np)
 {
-       struct niu_link_config *lp = &np->link_config;
        u16 analog_stat0, tx_alarm_status;
-       int err;
-
-       err = bcm8704_reset(np);
-       if (err)
-               return err;
-
-       err = bcm8704_init_user_dev3(np);
-       if (err)
-               return err;
-
-       err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
-                       MII_BMCR);
-       if (err < 0)
-               return err;
-       err &= ~BMCR_LOOPBACK;
-
-       if (lp->loopback_mode == LOOPBACK_MAC)
-               err |= BMCR_LOOPBACK;
-
-       err = mdio_write(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
-                        MII_BMCR, err);
-       if (err)
-               return err;
+       int err = 0;
 
 #if 1
        err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
@@ -1211,6 +1216,89 @@ static int xcvr_init_10g_bcm8704(struct niu *np)
        return 0;
 }
 
+static int xcvr_10g_set_lb_bcm870x(struct niu *np)
+{
+       struct niu_link_config *lp = &np->link_config;
+       int err;
+
+       err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
+                       MII_BMCR);
+       if (err < 0)
+               return err;
+
+       err &= ~BMCR_LOOPBACK;
+
+       if (lp->loopback_mode == LOOPBACK_MAC)
+               err |= BMCR_LOOPBACK;
+
+       err = mdio_write(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
+                        MII_BMCR, err);
+       if (err)
+               return err;
+
+       return 0;
+}
+
+static int xcvr_init_10g_bcm8706(struct niu *np)
+{
+       int err = 0;
+       u64 val;
+
+       if ((np->flags & NIU_FLAGS_HOTPLUG_PHY) &&
+           (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) == 0)
+                       return err;
+
+       val = nr64_mac(XMAC_CONFIG);
+       val &= ~XMAC_CONFIG_LED_POLARITY;
+       val |= XMAC_CONFIG_FORCE_LED_ON;
+       nw64_mac(XMAC_CONFIG, val);
+
+       val = nr64(MIF_CONFIG);
+       val |= MIF_CONFIG_INDIRECT_MODE;
+       nw64(MIF_CONFIG, val);
+
+       err = bcm8704_reset(np);
+       if (err)
+               return err;
+
+       err = xcvr_10g_set_lb_bcm870x(np);
+       if (err)
+               return err;
+
+       err = bcm8706_init_user_dev3(np);
+       if (err)
+               return err;
+
+       err = xcvr_diag_bcm870x(np);
+       if (err)
+               return err;
+
+       return 0;
+}
+
+static int xcvr_init_10g_bcm8704(struct niu *np)
+{
+       int err;
+
+       err = bcm8704_reset(np);
+       if (err)
+               return err;
+
+       err = bcm8704_init_user_dev3(np);
+       if (err)
+               return err;
+
+       err = xcvr_10g_set_lb_bcm870x(np);
+       if (err)
+               return err;
+
+       err =  xcvr_diag_bcm870x(np);
+       if (err)
+               return err;
+
+       return 0;
+}
+
 static int xcvr_init_10g(struct niu *np)
 {
        int phy_id, err;
@@ -1548,6 +1636,59 @@ out:
        return err;
 }
 
+static int link_status_10g_bcm8706(struct niu *np, int *link_up_p)
+{
+       int err, link_up;
+       link_up = 0;
+
+       err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
+                       BCM8704_PMD_RCV_SIGDET);
+       if (err < 0)
+               goto out;
+       if (!(err & PMD_RCV_SIGDET_GLOBAL)) {
+               err = 0;
+               goto out;
+       }
+
+       err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
+                       BCM8704_PCS_10G_R_STATUS);
+       if (err < 0)
+               goto out;
+
+       if (!(err & PCS_10G_R_STATUS_BLK_LOCK)) {
+               err = 0;
+               goto out;
+       }
+
+       err = mdio_read(np, np->phy_addr, BCM8704_PHYXS_DEV_ADDR,
+                       BCM8704_PHYXS_XGXS_LANE_STAT);
+       if (err < 0)
+               goto out;
+       if (err != (PHYXS_XGXS_LANE_STAT_ALINGED |
+                   PHYXS_XGXS_LANE_STAT_MAGIC |
+                   PHYXS_XGXS_LANE_STAT_PATTEST |
+                   PHYXS_XGXS_LANE_STAT_LANE3 |
+                   PHYXS_XGXS_LANE_STAT_LANE2 |
+                   PHYXS_XGXS_LANE_STAT_LANE1 |
+                   PHYXS_XGXS_LANE_STAT_LANE0)) {
+               err = 0;
+               np->link_config.active_speed = SPEED_INVALID;
+               np->link_config.active_duplex = DUPLEX_INVALID;
+               goto out;
+       }
+
+       link_up = 1;
+       np->link_config.active_speed = SPEED_10000;
+       np->link_config.active_duplex = DUPLEX_FULL;
+       err = 0;
+
+out:
+       *link_up_p = link_up;
+       if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
+               err = 0;
+       return err;
+}
+
 static int link_status_10g_bcom(struct niu *np, int *link_up_p)
 {
        int err, link_up;
@@ -1627,6 +1768,82 @@ static int link_status_10g(struct niu *np, int *link_up_p)
        return err;
 }
 
+static int niu_10g_phy_present(struct niu *np)
+{
+       u64 sig, mask, val;
+
+       sig = nr64(ESR_INT_SIGNALS);
+       switch (np->port) {
+       case 0:
+               mask = ESR_INT_SIGNALS_P0_BITS;
+               val = (ESR_INT_SRDY0_P0 |
+                      ESR_INT_DET0_P0 |
+                      ESR_INT_XSRDY_P0 |
+                      ESR_INT_XDP_P0_CH3 |
+                      ESR_INT_XDP_P0_CH2 |
+                      ESR_INT_XDP_P0_CH1 |
+                      ESR_INT_XDP_P0_CH0);
+               break;
+
+       case 1:
+               mask = ESR_INT_SIGNALS_P1_BITS;
+               val = (ESR_INT_SRDY0_P1 |
+                      ESR_INT_DET0_P1 |
+                      ESR_INT_XSRDY_P1 |
+                      ESR_INT_XDP_P1_CH3 |
+                      ESR_INT_XDP_P1_CH2 |
+                      ESR_INT_XDP_P1_CH1 |
+                      ESR_INT_XDP_P1_CH0);
+               break;
+
+       default:
+               return 0;
+       }
+
+       if ((sig & mask) != val)
+               return 0;
+       return 1;
+}
+
+static int link_status_10g_hotplug(struct niu *np, int *link_up_p)
+{
+       unsigned long flags;
+       int err = 0;
+       int phy_present;
+       int phy_present_prev;
+
+       spin_lock_irqsave(&np->lock, flags);
+
+       if (np->link_config.loopback_mode == LOOPBACK_DISABLED) {
+               phy_present_prev = (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) ?
+                       1 : 0;
+               phy_present = niu_10g_phy_present(np);
+               if (phy_present != phy_present_prev) {
+                       /* state change */
+                       if (phy_present) {
+                               np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT;
+                               if (np->phy_ops->xcvr_init)
+                                       err = np->phy_ops->xcvr_init(np);
+                               if (err) {
+                                       /* debounce */
+                                       np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
+                               }
+                       } else {
+                               np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
+                               *link_up_p = 0;
+                               niuwarn(LINK, "%s: Hotplug PHY Removed\n",
+                                       np->dev->name);
+                       }
+               }
+               if (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT)
+                       err = link_status_10g_bcm8706(np, link_up_p);
+       }
+
+       spin_unlock_irqrestore(&np->lock, flags);
+
+       return err;
+}
+
 static int link_status_1g(struct niu *np, int *link_up_p)
 {
        struct niu_link_config *lp = &np->link_config;
@@ -1761,6 +1978,12 @@ static const struct niu_phy_ops phy_ops_10g_fiber = {
        .link_status            = link_status_10g,
 };
 
+static const struct niu_phy_ops phy_ops_10g_fiber_hotplug = {
+       .serdes_init            = serdes_init_10g,
+       .xcvr_init              = xcvr_init_10g_bcm8706,
+       .link_status            = link_status_10g_hotplug,
+};
+
 static const struct niu_phy_ops phy_ops_10g_copper = {
        .serdes_init            = serdes_init_10g,
        .link_status            = link_status_10g, /* XXX */
@@ -1792,6 +2015,11 @@ static const struct niu_phy_template phy_template_10g_fiber = {
        .phy_addr_base  = 8,
 };
 
+static const struct niu_phy_template phy_template_10g_fiber_hotplug = {
+       .ops            = &phy_ops_10g_fiber_hotplug,
+       .phy_addr_base  = 8,
+};
+
 static const struct niu_phy_template phy_template_10g_copper = {
        .ops            = &phy_ops_10g_copper,
        .phy_addr_base  = 10,
@@ -1996,6 +2224,13 @@ static int niu_determine_phy_disposition(struct niu *np)
                            plat_type == PLAT_TYPE_VF_P1)
                                phy_addr_off = 8;
                        phy_addr_off += np->port;
+                       if (np->flags & NIU_FLAGS_HOTPLUG_PHY) {
+                               tp = &phy_template_10g_fiber_hotplug;
+                               if (np->port == 0)
+                                       phy_addr_off = 8;
+                               if (np->port == 1)
+                                       phy_addr_off = 12;
+                       }
                        break;
 
                case NIU_FLAGS_10G | NIU_FLAGS_XCVR_SERDES:
@@ -6773,6 +7008,37 @@ static int __devinit niu_phy_type_prop_decode(struct niu *np,
        return 0;
 }
 
+/* niu board models have a trailing dash version incremented
+ * with HW rev change. Need to ingnore the  dash version while
+ * checking for match
+ *
+ * for example, for the 10G card the current vpd.board_model
+ * is 501-5283-04, of which -04 is the  dash version and have
+ * to be ignored
+ */
+static int niu_board_model_match(struct niu *np, const char *model)
+{
+       return !strncmp(np->vpd.board_model, model, strlen(model));
+}
+
+static int niu_pci_vpd_get_nports(struct niu *np)
+{
+       int ports = 0;
+
+       if ((niu_board_model_match(np, NIU_QGC_LP_BM_STR)) ||
+           (niu_board_model_match(np, NIU_QGC_PEM_BM_STR)) ||
+           (niu_board_model_match(np, NIU_ALONSO_BM_STR))) {
+               ports = 4;
+       } else if ((niu_board_model_match(np, NIU_2XGF_LP_BM_STR)) ||
+                  (niu_board_model_match(np, NIU_2XGF_PEM_BM_STR)) ||
+                  (niu_board_model_match(np, NIU_FOXXY_BM_STR)) ||
+                  (niu_board_model_match(np, NIU_2XGF_MRVL_BM_STR))) {
+               ports = 2;
+       }
+
+       return ports;
+}
+
 static void __devinit niu_pci_vpd_validate(struct niu *np)
 {
        struct net_device *dev = np->dev;
@@ -6799,6 +7065,9 @@ static void __devinit niu_pci_vpd_validate(struct niu *np)
                }
                if (np->flags & NIU_FLAGS_10G)
                         np->mac_xcvr = MAC_XCVR_XPCS;
+       } else if (niu_board_model_match(np, NIU_FOXXY_BM_STR)) {
+               np->flags |= (NIU_FLAGS_10G | NIU_FLAGS_FIBER |
+                             NIU_FLAGS_HOTPLUG_PHY);
        } else if (niu_phy_type_prop_decode(np, np->vpd.phy_type)) {
                dev_err(np->device, PFX "Illegal phy string [%s].\n",
                        np->vpd.phy_type);
@@ -6987,11 +7256,17 @@ static int __devinit niu_get_and_validate_port(struct niu *np)
                if (parent->plat_type == PLAT_TYPE_NIU) {
                        parent->num_ports = 2;
                } else {
-                       parent->num_ports = nr64(ESPC_NUM_PORTS_MACS) &
-                               ESPC_NUM_PORTS_MACS_VAL;
-
-                       if (!parent->num_ports)
-                               parent->num_ports = 4;
+                       parent->num_ports = niu_pci_vpd_get_nports(np);
+                       if (!parent->num_ports) {
+                               /* Fall back to SPROM as last resort.
+                                * This will fail on most cards.
+                                */
+                               parent->num_ports = nr64(ESPC_NUM_PORTS_MACS) &
+                                       ESPC_NUM_PORTS_MACS_VAL;
+
+                               if (!parent->num_ports)
+                                       return -ENODEV;
+                       }
                }
        }
 
@@ -7015,7 +7290,8 @@ static int __devinit phy_record(struct niu_parent *parent,
                return 0;
        if (type == PHY_TYPE_PMA_PMD || type == PHY_TYPE_PCS) {
                if (((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8704) &&
-                   ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_MRVL88X2011))
+                   ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_MRVL88X2011) &&
+                   ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8706))
                        return 0;
        } else {
                if ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM5464R)
@@ -7262,7 +7538,6 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent)
        u32 val;
        int err;
 
-
        if (!strcmp(np->vpd.model, "SUNW,CP3220") ||
            !strcmp(np->vpd.model, "SUNW,CP3260")) {
                num_10g = 0;
@@ -7273,6 +7548,12 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent)
                       phy_encode(PORT_TYPE_1G, 1) |
                       phy_encode(PORT_TYPE_1G, 2) |
                       phy_encode(PORT_TYPE_1G, 3));
+       } else if (niu_board_model_match(np, NIU_FOXXY_BM_STR)) {
+               num_10g = 2;
+               num_1g = 0;
+               parent->num_ports = 2;
+               val = (phy_encode(PORT_TYPE_10G, 0) |
+                      phy_encode(PORT_TYPE_10G, 1));
        } else {
                err = fill_phy_probe_info(np, parent, info);
                if (err)
@@ -7733,15 +8014,16 @@ static int __devinit niu_get_invariants(struct niu *np)
 
        have_props = !err;
 
-       err = niu_get_and_validate_port(np);
-       if (err)
-               return err;
-
        err = niu_init_mac_ipp_pcs_base(np);
        if (err)
                return err;
 
-       if (!have_props) {
+       if (have_props) {
+               err = niu_get_and_validate_port(np);
+               if (err)
+                       return err;
+
+       } else  {
                if (np->parent->plat_type == PLAT_TYPE_NIU)
                        return -EINVAL;
 
@@ -7753,10 +8035,17 @@ static int __devinit niu_get_invariants(struct niu *np)
                        niu_pci_vpd_fetch(np, offset);
                nw64(ESPC_PIO_EN, 0);
 
-               if (np->flags & NIU_FLAGS_VPD_VALID)
+               if (np->flags & NIU_FLAGS_VPD_VALID) {
                        niu_pci_vpd_validate(np);
+                       err = niu_get_and_validate_port(np);
+                       if (err)
+                               return err;
+               }
 
                if (!(np->flags & NIU_FLAGS_VPD_VALID)) {
+                       err = niu_get_and_validate_port(np);
+                       if (err)
+                               return err;
                        err = niu_pci_probe_sprom(np);
                        if (err)
                                return err;
index 336aed08b27507964394f3cca929c1c2b4112dd4..97ffbe137bcbaa20fbea8ae4eeedf54c9b9ac7a8 100644 (file)
@@ -2537,6 +2537,7 @@ struct fcram_hash_ipv6 {
 
 #define NIU_PHY_ID_MASK                        0xfffff0f0
 #define NIU_PHY_ID_BCM8704             0x00206030
+#define NIU_PHY_ID_BCM8706             0x00206035
 #define NIU_PHY_ID_BCM5464R            0x002060b0
 #define NIU_PHY_ID_MRVL88X2011         0x01410020
 
@@ -2937,6 +2938,15 @@ struct rx_ring_info {
 
 #define NIU_MAX_MTU            9216
 
+/* VPD strings */
+#define        NIU_QGC_LP_BM_STR       "501-7606"
+#define        NIU_2XGF_LP_BM_STR      "501-7283"
+#define        NIU_QGC_PEM_BM_STR      "501-7765"
+#define        NIU_2XGF_PEM_BM_STR     "501-7626"
+#define        NIU_ALONSO_BM_STR       "373-0202"
+#define        NIU_FOXXY_BM_STR        "501-7961"
+#define        NIU_2XGF_MRVL_BM_STR    "SK-6E82"
+
 #define NIU_VPD_MIN_MAJOR      3
 #define NIU_VPD_MIN_MINOR      4
 
@@ -3199,6 +3209,8 @@ struct niu {
        struct niu_parent               *parent;
 
        u32                             flags;
+#define NIU_FLAGS_HOTPLUG_PHY_PRESENT  0x02000000 /* Removebale PHY detected*/
+#define NIU_FLAGS_HOTPLUG_PHY          0x01000000 /* Removebale PHY */
 #define NIU_FLAGS_VPD_VALID            0x00800000 /* VPD has valid version */
 #define NIU_FLAGS_MSIX                 0x00400000 /* MSI-X in use */
 #define NIU_FLAGS_MCAST                        0x00200000 /* multicast filter enabled */
index 963630c65ca940d9dfc59ed57370c54dbfed7847..94e0b7ed76f16ff8c2c2a7f43aaf341c4cace12d 100644 (file)
@@ -89,6 +89,9 @@ int mdiobus_register(struct mii_bus *bus)
 
                        phydev->bus = bus;
 
+                       /* Run all of the fixups for this PHY */
+                       phy_scan_fixups(phydev);
+
                        err = device_register(&phydev->dev);
 
                        if (err) {
index 12fccb1c76dc0c147e3291aaad803c8d5dbc9caf..3c18bb594957a3e2e0320274ff88897189d8b594 100644 (file)
@@ -406,8 +406,10 @@ int phy_mii_ioctl(struct phy_device *phydev,
                
                if (mii_data->reg_num == MII_BMCR 
                                && val & BMCR_RESET
-                               && phydev->drv->config_init)
+                               && phydev->drv->config_init) {
+                       phy_scan_fixups(phydev);
                        phydev->drv->config_init(phydev);
+               }
                break;
 
        default:
index 8b1121b02f9806d9323cfea84fb157bc83c5ae08..ddf8d51832a679dcd7b2767bd8c9793d5b2a8a23 100644 (file)
@@ -53,6 +53,96 @@ static void phy_device_release(struct device *dev)
        phy_device_free(to_phy_device(dev));
 }
 
+static LIST_HEAD(phy_fixup_list);
+static DEFINE_MUTEX(phy_fixup_lock);
+
+/*
+ * Creates a new phy_fixup and adds it to the list
+ * @bus_id: A string which matches phydev->dev.bus_id (or PHY_ANY_ID)
+ * @phy_uid: Used to match against phydev->phy_id (the UID of the PHY)
+ *     It can also be PHY_ANY_UID
+ * @phy_uid_mask: Applied to phydev->phy_id and fixup->phy_uid before
+ *     comparison
+ * @run: The actual code to be run when a matching PHY is found
+ */
+int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
+               int (*run)(struct phy_device *))
+{
+       struct phy_fixup *fixup;
+
+       fixup = kzalloc(sizeof(struct phy_fixup), GFP_KERNEL);
+       if (!fixup)
+               return -ENOMEM;
+
+       strncpy(fixup->bus_id, bus_id, BUS_ID_SIZE);
+       fixup->phy_uid = phy_uid;
+       fixup->phy_uid_mask = phy_uid_mask;
+       fixup->run = run;
+
+       mutex_lock(&phy_fixup_lock);
+       list_add_tail(&fixup->list, &phy_fixup_list);
+       mutex_unlock(&phy_fixup_lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(phy_register_fixup);
+
+/* Registers a fixup to be run on any PHY with the UID in phy_uid */
+int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
+               int (*run)(struct phy_device *))
+{
+       return phy_register_fixup(PHY_ANY_ID, phy_uid, phy_uid_mask, run);
+}
+EXPORT_SYMBOL(phy_register_fixup_for_uid);
+
+/* Registers a fixup to be run on the PHY with id string bus_id */
+int phy_register_fixup_for_id(const char *bus_id,
+               int (*run)(struct phy_device *))
+{
+       return phy_register_fixup(bus_id, PHY_ANY_UID, 0xffffffff, run);
+}
+EXPORT_SYMBOL(phy_register_fixup_for_id);
+
+/*
+ * Returns 1 if fixup matches phydev in bus_id and phy_uid.
+ * Fixups can be set to match any in one or more fields.
+ */
+static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup)
+{
+       if (strcmp(fixup->bus_id, phydev->dev.bus_id) != 0)
+               if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0)
+                       return 0;
+
+       if ((fixup->phy_uid & fixup->phy_uid_mask) !=
+                       (phydev->phy_id & fixup->phy_uid_mask))
+               if (fixup->phy_uid != PHY_ANY_UID)
+                       return 0;
+
+       return 1;
+}
+
+/* Runs any matching fixups for this phydev */
+int phy_scan_fixups(struct phy_device *phydev)
+{
+       struct phy_fixup *fixup;
+
+       mutex_lock(&phy_fixup_lock);
+       list_for_each_entry(fixup, &phy_fixup_list, list) {
+               if (phy_needs_fixup(phydev, fixup)) {
+                       int err;
+
+                       err = fixup->run(phydev);
+
+                       if (err < 0)
+                               return err;
+               }
+       }
+       mutex_unlock(&phy_fixup_lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(phy_scan_fixups);
+
 struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
 {
        struct phy_device *dev;
@@ -179,13 +269,13 @@ void phy_prepare_link(struct phy_device *phydev,
  *   choose to call only the subset of functions which provide
  *   the desired functionality.
  */
-struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
+struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
                void (*handler)(struct net_device *), u32 flags,
                phy_interface_t interface)
 {
        struct phy_device *phydev;
 
-       phydev = phy_attach(dev, phy_id, flags, interface);
+       phydev = phy_attach(dev, bus_id, flags, interface);
 
        if (IS_ERR(phydev))
                return phydev;
@@ -226,7 +316,7 @@ static int phy_compare_id(struct device *dev, void *data)
 /**
  * phy_attach - attach a network device to a particular PHY device
  * @dev: network device to attach
- * @phy_id: PHY device to attach
+ * @bus_id: PHY device to attach
  * @flags: PHY device's dev_flags
  * @interface: PHY device's interface
  *
@@ -238,7 +328,7 @@ static int phy_compare_id(struct device *dev, void *data)
  *     change.  The phy_device is returned to the attaching driver.
  */
 struct phy_device *phy_attach(struct net_device *dev,
-               const char *phy_id, u32 flags, phy_interface_t interface)
+               const char *bus_id, u32 flags, phy_interface_t interface)
 {
        struct bus_type *bus = &mdio_bus_type;
        struct phy_device *phydev;
@@ -246,12 +336,12 @@ struct phy_device *phy_attach(struct net_device *dev,
 
        /* Search the list of PHY devices on the mdio bus for the
         * PHY with the requested name */
-       d = bus_find_device(bus, NULL, (void *)phy_id, phy_compare_id);
+       d = bus_find_device(bus, NULL, (void *)bus_id, phy_compare_id);
 
        if (d) {
                phydev = to_phy_device(d);
        } else {
-               printk(KERN_ERR "%s not found\n", phy_id);
+               printk(KERN_ERR "%s not found\n", bus_id);
                return ERR_PTR(-ENODEV);
        }
 
@@ -271,7 +361,7 @@ struct phy_device *phy_attach(struct net_device *dev,
 
        if (phydev->attached_dev) {
                printk(KERN_ERR "%s: %s already attached\n",
-                               dev->name, phy_id);
+                               dev->name, bus_id);
                return ERR_PTR(-EBUSY);
        }
 
@@ -287,6 +377,11 @@ struct phy_device *phy_attach(struct net_device *dev,
        if (phydev->drv->config_init) {
                int err;
 
+               err = phy_scan_fixups(phydev);
+
+               if (err < 0)
+                       return ERR_PTR(err);
+
                err = phydev->drv->config_init(phydev);
 
                if (err < 0)
@@ -395,6 +490,7 @@ EXPORT_SYMBOL(genphy_config_advert);
  */
 int genphy_setup_forced(struct phy_device *phydev)
 {
+       int err;
        int ctl = 0;
 
        phydev->pause = phydev->asym_pause = 0;
@@ -407,17 +503,26 @@ int genphy_setup_forced(struct phy_device *phydev)
        if (DUPLEX_FULL == phydev->duplex)
                ctl |= BMCR_FULLDPLX;
        
-       ctl = phy_write(phydev, MII_BMCR, ctl);
+       err = phy_write(phydev, MII_BMCR, ctl);
 
-       if (ctl < 0)
-               return ctl;
+       if (err < 0)
+               return err;
+
+       /*
+        * Run the fixups on this PHY, just in case the
+        * board code needs to change something after a reset
+        */
+       err = phy_scan_fixups(phydev);
+
+       if (err < 0)
+               return err;
 
        /* We just reset the device, so we'd better configure any
         * settings the PHY requires to operate */
        if (phydev->drv->config_init)
-               ctl = phydev->drv->config_init(phydev);
+               err = phydev->drv->config_init(phydev);
 
-       return ctl;
+       return err;
 }
 
 
index dcbe01b0ca0de05d3c21d75f5661858d88157232..157fd932e95140ce54936e3d0a79bdb30cd25048 100644 (file)
@@ -86,7 +86,7 @@
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "2.0.26.20"
+#define DRV_VERSION "2.0.26.22"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
@@ -117,20 +117,6 @@ static inline int RXD_IS_UP2DT(struct RxD_t *rxdp)
 
 #define LINK_IS_UP(val64) (!(val64 & (ADAPTER_STATUS_RMAC_REMOTE_FAULT | \
                                      ADAPTER_STATUS_RMAC_LOCAL_FAULT)))
-#define TASKLET_IN_USE test_and_set_bit(0, (&sp->tasklet_status))
-#define PANIC  1
-#define LOW    2
-static inline int rx_buffer_level(struct s2io_nic * sp, int rxb_size, int ring)
-{
-       struct mac_info *mac_control;
-
-       mac_control = &sp->mac_control;
-       if (rxb_size <= rxd_count[sp->rxd_mode])
-               return PANIC;
-       else if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16)
-               return  LOW;
-       return 0;
-}
 
 static inline int is_s2io_card_up(const struct s2io_nic * sp)
 {
@@ -2458,7 +2444,7 @@ static void free_tx_buffers(struct s2io_nic *nic)
        for (i = 0; i < config->tx_fifo_num; i++) {
                unsigned long flags;
                spin_lock_irqsave(&mac_control->fifos[i].tx_lock, flags);
-               for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) {
+               for (j = 0; j < config->tx_cfg[i].fifo_len; j++) {
                        txdp = (struct TxD *) \
                        mac_control->fifos[i].list_info[j].list_virt_addr;
                        skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j);
@@ -2544,7 +2530,6 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
        struct config_param *config;
        u64 tmp;
        struct buffAdd *ba;
-       unsigned long flags;
        struct RxD_t *first_rxdp = NULL;
        u64 Buffer0_ptr = 0, Buffer1_ptr = 0;
        struct RxD1 *rxdp1;
@@ -2592,15 +2577,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                        DBG_PRINT(INTR_DBG, "%s: Next block at: %p\n",
                                  dev->name, rxdp);
                }
-               if(!napi) {
-                       spin_lock_irqsave(&nic->put_lock, flags);
-                       mac_control->rings[ring_no].put_pos =
-                       (block_no * (rxd_count[nic->rxd_mode] + 1)) + off;
-                       spin_unlock_irqrestore(&nic->put_lock, flags);
-               } else {
-                       mac_control->rings[ring_no].put_pos =
-                       (block_no * (rxd_count[nic->rxd_mode] + 1)) + off;
-               }
+
                if ((rxdp->Control_1 & RXD_OWN_XENA) &&
                        ((nic->rxd_mode == RXD_MODE_3B) &&
                                (rxdp->Control_2 & s2BIT(0)))) {
@@ -2978,7 +2955,7 @@ static void rx_intr_handler(struct ring_info *ring_data)
 {
        struct s2io_nic *nic = ring_data->nic;
        struct net_device *dev = (struct net_device *) nic->dev;
-       int get_block, put_block, put_offset;
+       int get_block, put_block;
        struct rx_curr_get_info get_info, put_info;
        struct RxD_t *rxdp;
        struct sk_buff *skb;
@@ -2987,19 +2964,11 @@ static void rx_intr_handler(struct ring_info *ring_data)
        struct RxD1* rxdp1;
        struct RxD3* rxdp3;
 
-       spin_lock(&nic->rx_lock);
-
        get_info = ring_data->rx_curr_get_info;
        get_block = get_info.block_index;
        memcpy(&put_info, &ring_data->rx_curr_put_info, sizeof(put_info));
        put_block = put_info.block_index;
        rxdp = ring_data->rx_blocks[get_block].rxds[get_info.offset].virt_addr;
-       if (!napi) {
-               spin_lock(&nic->put_lock);
-               put_offset = ring_data->put_pos;
-               spin_unlock(&nic->put_lock);
-       } else
-               put_offset = ring_data->put_pos;
 
        while (RXD_IS_UP2DT(rxdp)) {
                /*
@@ -3016,7 +2985,6 @@ static void rx_intr_handler(struct ring_info *ring_data)
                        DBG_PRINT(ERR_DBG, "%s: The skb is ",
                                  dev->name);
                        DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
-                       spin_unlock(&nic->rx_lock);
                        return;
                }
                if (nic->rxd_mode == RXD_MODE_1) {
@@ -3072,8 +3040,6 @@ static void rx_intr_handler(struct ring_info *ring_data)
                        }
                }
        }
-
-       spin_unlock(&nic->rx_lock);
 }
 
 /**
@@ -4105,7 +4071,6 @@ static int s2io_close(struct net_device *dev)
                        do_s2io_delete_unicast_mc(sp, tmp64);
        }
 
-       /* Reset card, kill tasklet and free Tx and Rx buffers. */
        s2io_card_down(sp);
 
        return 0;
@@ -4370,29 +4335,9 @@ s2io_alarm_handle(unsigned long data)
 
 static int s2io_chk_rx_buffers(struct s2io_nic *sp, int rng_n)
 {
-       int rxb_size, level;
-
-       if (!sp->lro) {
-               rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
-               level = rx_buffer_level(sp, rxb_size, rng_n);
-
-               if ((level == PANIC) && (!TASKLET_IN_USE)) {
-                       int ret;
-                       DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__);
-                       DBG_PRINT(INTR_DBG, "PANIC levels\n");
-                       if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) {
-                               DBG_PRINT(INFO_DBG, "Out of memory in %s",
-                                         __FUNCTION__);
-                               clear_bit(0, (&sp->tasklet_status));
-                               return -1;
-                       }
-                       clear_bit(0, (&sp->tasklet_status));
-               } else if (level == LOW)
-                       tasklet_schedule(&sp->task);
-
-       } else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) {
-                       DBG_PRINT(INFO_DBG, "%s:Out of memory", sp->dev->name);
-                       DBG_PRINT(INFO_DBG, " in Rx Intr!!\n");
+       if (fill_rx_buffers(sp, rng_n) == -ENOMEM) {
+               DBG_PRINT(INFO_DBG, "%s:Out of memory", sp->dev->name);
+               DBG_PRINT(INFO_DBG, " in Rx Intr!!\n");
        }
        return 0;
 }
@@ -6769,49 +6714,6 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
        return ret;
 }
 
-/**
- *  s2io_tasklet - Bottom half of the ISR.
- *  @dev_adr : address of the device structure in dma_addr_t format.
- *  Description:
- *  This is the tasklet or the bottom half of the ISR. This is
- *  an extension of the ISR which is scheduled by the scheduler to be run
- *  when the load on the CPU is low. All low priority tasks of the ISR can
- *  be pushed into the tasklet. For now the tasklet is used only to
- *  replenish the Rx buffers in the Rx buffer descriptors.
- *  Return value:
- *  void.
- */
-
-static void s2io_tasklet(unsigned long dev_addr)
-{
-       struct net_device *dev = (struct net_device *) dev_addr;
-       struct s2io_nic *sp = dev->priv;
-       int i, ret;
-       struct mac_info *mac_control;
-       struct config_param *config;
-
-       mac_control = &sp->mac_control;
-       config = &sp->config;
-
-       if (!TASKLET_IN_USE) {
-               for (i = 0; i < config->rx_ring_num; i++) {
-                       ret = fill_rx_buffers(sp, i);
-                       if (ret == -ENOMEM) {
-                               DBG_PRINT(INFO_DBG, "%s: Out of ",
-                                         dev->name);
-                               DBG_PRINT(INFO_DBG, "memory in tasklet\n");
-                               break;
-                       } else if (ret == -EFILL) {
-                               DBG_PRINT(INFO_DBG,
-                                         "%s: Rx Ring %d is full\n",
-                                         dev->name, i);
-                               break;
-                       }
-               }
-               clear_bit(0, (&sp->tasklet_status));
-       }
-}
-
 /**
  * s2io_set_link - Set the LInk status
  * @data: long pointer to device private structue
@@ -7161,7 +7063,6 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
 {
        int cnt = 0;
        struct XENA_dev_config __iomem *bar0 = sp->bar0;
-       unsigned long flags;
        register u64 val64 = 0;
        struct config_param *config;
        config = &sp->config;
@@ -7186,9 +7087,6 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
 
        s2io_rem_isr(sp);
 
-       /* Kill tasklet. */
-       tasklet_kill(&sp->task);
-
        /* Check if the device is Quiescent and then Reset the NIC */
        while(do_io) {
                /* As per the HW requirement we need to replenish the
@@ -7223,9 +7121,7 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
        free_tx_buffers(sp);
 
        /* Free all Rx buffers */
-       spin_lock_irqsave(&sp->rx_lock, flags);
        free_rx_buffers(sp);
-       spin_unlock_irqrestore(&sp->rx_lock, flags);
 
        clear_bit(__S2IO_STATE_LINK_TASK, &(sp->state));
 }
@@ -7314,9 +7210,6 @@ static int s2io_card_up(struct s2io_nic * sp)
 
        S2IO_TIMER_CONF(sp->alarm_timer, s2io_alarm_handle, sp, (HZ/2));
 
-       /* Enable tasklet for the device */
-       tasklet_init(&sp->task, s2io_tasklet, (unsigned long) dev);
-
        /*  Enable select interrupts */
        en_dis_err_alarms(sp, ENA_ALL_INTRS, ENABLE_INTRS);
        if (sp->config.intr_type != INTA)
@@ -8119,20 +8012,15 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        s2io_reset(sp);
 
        /*
-        * Initialize the tasklet status and link state flags
+        * Initialize link state flags
         * and the card state parameter
         */
-       sp->tasklet_status = 0;
        sp->state = 0;
 
        /* Initialize spinlocks */
        for (i = 0; i < sp->config.tx_fifo_num; i++)
                spin_lock_init(&mac_control->fifos[i].tx_lock);
 
-       if (!napi)
-               spin_lock_init(&sp->put_lock);
-       spin_lock_init(&sp->rx_lock);
-
        /*
         * SXE-002: Configure link and activity LED to init state
         * on driver load.
index e68fdf7e42600558ff7114772b58c8ed65c3ece7..ce53a02105f25ab99aee4e017c74b4c04a2e2600 100644 (file)
@@ -703,9 +703,6 @@ struct ring_info {
         */
        struct rx_curr_get_info rx_curr_get_info;
 
-       /* Index to the absolute position of the put pointer of Rx ring */
-       int put_pos;
-
        /* Buffer Address store. */
        struct buffAdd **ba;
        struct s2io_nic *nic;
@@ -868,8 +865,6 @@ struct s2io_nic {
        int device_enabled_once;
 
        char name[60];
-       struct tasklet_struct task;
-       volatile unsigned long tasklet_status;
 
        /* Timer that handles I/O errors/exceptions */
        struct timer_list alarm_timer;
@@ -879,8 +874,6 @@ struct s2io_nic {
 
        atomic_t rx_bufs_left[MAX_RX_RINGS];
 
-       spinlock_t put_lock;
-
 #define PROMISC     1
 #define ALL_MULTI   2
 
@@ -964,7 +957,6 @@ struct s2io_nic {
        u8              lro;
        u16             lro_max_aggr_per_sess;
        volatile unsigned long state;
-       spinlock_t      rx_lock;
        u64             general_int_mask;
 #define VPD_STRING_LEN 80
        u8  product_name[VPD_STRING_LEN];
@@ -1094,7 +1086,6 @@ static void s2io_handle_errors(void * dev_id);
 static int s2io_starter(void);
 static void s2io_closer(void);
 static void s2io_tx_watchdog(struct net_device *dev);
-static void s2io_tasklet(unsigned long dev_addr);
 static void s2io_set_multicast(struct net_device *dev);
 static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp);
 static void s2io_link(struct s2io_nic * sp, int link);
index 78994ede0cb0666945dc3d35e1061b1cc3cc8aee..6261201403cdd143ca592a880ca5052c167522d9 100644 (file)
@@ -825,7 +825,8 @@ static struct platform_driver sgiseeq_driver = {
        .probe  = sgiseeq_probe,
        .remove = __devexit_p(sgiseeq_remove),
        .driver = {
-               .name   = "sgiseeq"
+               .name   = "sgiseeq",
+               .owner  = THIS_MODULE,
        }
 };
 
@@ -850,3 +851,4 @@ module_exit(sgiseeq_module_exit);
 MODULE_DESCRIPTION("SGI Seeq 8003 driver");
 MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips@linux-mips.org>");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:sgiseeq");
index 76cc1d3adf715fc635a58db2c2b9df40789f7a56..4e28002051899c21f0a6050b5b32f14b6f2c6dec 100644 (file)
@@ -92,6 +92,7 @@ module_param(tx_fifo_kb, int, 0400);
 MODULE_PARM_DESC(tx_fifo_kb,"transmit FIFO size in KB (1<x<15)(default=8)");
 
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:smc911x");
 
 /*
  * The internal workings of the driver.  If you are changing anything
@@ -243,7 +244,7 @@ static void smc911x_reset(struct net_device *dev)
                do {
                        udelay(10);
                        reg = SMC_GET_PMT_CTRL() & PMT_CTRL_READY_;
-               } while ( timeout-- && !reg);
+               } while (--timeout && !reg);
                if (timeout == 0) {
                        PRINTK("%s: smc911x_reset timeout waiting for PM restore\n", dev->name);
                        return;
@@ -267,7 +268,7 @@ static void smc911x_reset(struct net_device *dev)
                                resets++;
                                break;
                        }
-               } while ( timeout-- && (reg & HW_CFG_SRST_));
+               } while (--timeout && (reg & HW_CFG_SRST_));
        }
        if (timeout == 0) {
                PRINTK("%s: smc911x_reset timeout waiting for reset\n", dev->name);
@@ -413,7 +414,7 @@ static inline void smc911x_drop_pkt(struct net_device *dev)
                do {
                        udelay(10);
                        reg = SMC_GET_RX_DP_CTRL() & RX_DP_CTRL_FFWD_BUSY_;
-               } while ( timeout-- && reg);
+               } while (--timeout && reg);
                if (timeout == 0) {
                        PRINTK("%s: timeout waiting for RX fast forward\n", dev->name);
                }
@@ -2262,6 +2263,7 @@ static struct platform_driver smc911x_driver = {
        .resume  = smc911x_drv_resume,
        .driver  = {
                .name    = CARDNAME,
+               .owner  = THIS_MODULE,
        },
 };
 
index 600b92af33349c1d5a2ed782f0aba89f0fa4a229..a188e33484e631326f366edd68b33f635fce94e6 100644 (file)
@@ -132,6 +132,7 @@ module_param(watchdog, int, 0400);
 MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
 
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:smc91x");
 
 /*
  * The internal workings of the driver.  If you are changing anything
@@ -2308,6 +2309,7 @@ static struct platform_driver smc_driver = {
        .resume         = smc_drv_resume,
        .driver         = {
                .name   = CARDNAME,
+               .owner  = THIS_MODULE,
        },
 };
 
index 2cf6794acb4f9368a8f99ca94952c3766395fc97..854ccf2b4105efd1958a46eb942bb96928d511d2 100644 (file)
@@ -44,6 +44,7 @@ static const char sni_82596_string[] = "snirm_82596";
 MODULE_AUTHOR("Thomas Bogendoerfer");
 MODULE_DESCRIPTION("i82596 driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:snirm_82596");
 module_param(i596_debug, int, 0);
 MODULE_PARM_DESC(i596_debug, "82596 debug mask");
 
@@ -166,6 +167,7 @@ static struct platform_driver sni_82596_driver = {
        .remove = __devexit_p(sni_82596_driver_remove),
        .driver = {
                .name   = sni_82596_string,
+               .owner  = THIS_MODULE,
        },
 };
 
index 17585e5eed5379c2299f85f92a3956768850161e..e83b166aa6b9a53aeeb00a70224d10e46660f638 100644 (file)
@@ -625,6 +625,12 @@ static void __init bdx_firmware_endianess(void)
                s_firmLoad[i] = CPU_CHIP_SWAP32(s_firmLoad[i]);
 }
 
+static int bdx_range_check(struct bdx_priv *priv, u32 offset)
+{
+       return (offset > (u32) (BDX_REGS_SIZE / priv->nic->port_num)) ?
+               -EINVAL : 0;
+}
+
 static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
 {
        struct bdx_priv *priv = ndev->priv;
@@ -643,9 +649,15 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
                DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]);
        }
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        switch (data[0]) {
 
        case BDX_OP_READ:
+               error = bdx_range_check(priv, data[1]);
+               if (error < 0)
+                       return error;
                data[2] = READ_REG(priv, data[1]);
                DBG("read_reg(0x%x)=0x%x (dec %d)\n", data[1], data[2],
                    data[2]);
@@ -655,6 +667,9 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
                break;
 
        case BDX_OP_WRITE:
+               error = bdx_range_check(priv, data[1]);
+               if (error < 0)
+                       return error;
                WRITE_REG(priv, data[1], data[2]);
                DBG("write_reg(0x%x, 0x%x)\n", data[1], data[2]);
                break;
index bc4c62b8e81a4d7be3441bdc578daf3689646ab2..e3f74c9f78bd848f1e61aa6647f7109e7282fd7c 100644 (file)
@@ -4017,6 +4017,8 @@ static int tg3_halt(struct tg3 *, int, int);
  * Invoked with tp->lock held.
  */
 static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
+       __releases(tp->lock)
+       __acquires(tp->lock)
 {
        int err;
 
index 6f33f84d37b0631652d04825b58a554cc7477dc7..6017d5267d08f4c80939834385cc7d3c591ca8be 100644 (file)
@@ -162,6 +162,7 @@ static struct platform_driver tsi_eth_driver = {
        .remove = tsi108_ether_remove,
        .driver = {
                .name = "tsi-ethernet",
+               .owner = THIS_MODULE,
        },
 };
 
@@ -1729,3 +1730,4 @@ module_exit(tsi108_ether_exit);
 MODULE_AUTHOR("Tundra Semiconductor Corporation");
 MODULE_DESCRIPTION("Tsi108 Gigabit Ethernet driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:tsi-ethernet");
index 333961bb7873973df7c75e5870aaee1f458ec47f..c0dd25ba7a18dcd9cc7969e85f1e02ce954af797 100644 (file)
@@ -2183,7 +2183,6 @@ typhoon_resume(struct pci_dev *pdev)
        }
 
        netif_device_attach(dev);
-       netif_start_queue(dev);
        return 0;
 
 reset:
index 2f11254bcc077fa22f506a1481221150429d3bee..281ce3d395324787c8b986f0dae5648e793aa853 100644 (file)
@@ -3932,7 +3932,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
        ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);
        fixed_link = of_get_property(np, "fixed-link", NULL);
        if (fixed_link) {
-               ug_info->mdio_bus = 0;
+               snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "0");
                ug_info->phy_address = fixed_link[0];
                phy = NULL;
        } else {
index ed1afaf683a4bb96481325165929542bf04e6db8..6b8d882d197b4c450e25c302e238d462718226c8 100644 (file)
@@ -605,7 +605,6 @@ static void __devinit velocity_get_options(struct velocity_opt *opts, int index,
 static void velocity_init_cam_filter(struct velocity_info *vptr)
 {
        struct mac_regs __iomem * regs = vptr->mac_regs;
-       unsigned short vid;
 
        /* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */
        WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, &regs->MCFG);
@@ -617,29 +616,33 @@ static void velocity_init_cam_filter(struct velocity_info *vptr)
        mac_set_vlan_cam_mask(regs, vptr->vCAMmask);
        mac_set_cam_mask(regs, vptr->mCAMmask);
 
-       /* Enable first VCAM */
+       /* Enable VCAMs */
        if (vptr->vlgrp) {
-               for (vid = 0; vid < VLAN_VID_MASK; vid++) {
-                       if (vlan_group_get_device(vptr->vlgrp, vid)) {
-                               /* If Tagging option is enabled and
-                                  VLAN ID is not zero, then
-                                  turn on MCFG_RTGOPT also */
-                               if (vid != 0)
-                                       WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);
+               unsigned int vid, i = 0;
+
+               if (!vlan_group_get_device(vptr->vlgrp, 0))
+                       WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);
 
-                               mac_set_vlan_cam(regs, 0, (u8 *) &vid);
+               for (vid = 1; (vid < VLAN_VID_MASK); vid++) {
+                       if (vlan_group_get_device(vptr->vlgrp, vid)) {
+                               mac_set_vlan_cam(regs, i, (u8 *) &vid);
+                               vptr->vCAMmask[i / 8] |= 0x1 << (i % 8);
+                               if (++i >= VCAM_SIZE)
+                                       break;
                        }
                }
-               vptr->vCAMmask[0] |= 1;
                mac_set_vlan_cam_mask(regs, vptr->vCAMmask);
-       } else {
-               u16 temp = 0;
-               mac_set_vlan_cam(regs, 0, (u8 *) &temp);
-               temp = 1;
-               mac_set_vlan_cam_mask(regs, (u8 *) &temp);
        }
 }
 
+static void velocity_vlan_rx_register(struct net_device *dev,
+                                     struct vlan_group *grp)
+{
+       struct velocity_info *vptr = netdev_priv(dev);
+
+       vptr->vlgrp = grp;
+}
+
 static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 {
        struct velocity_info *vptr = netdev_priv(dev);
@@ -959,11 +962,13 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
 
        dev->vlan_rx_add_vid = velocity_vlan_rx_add_vid;
        dev->vlan_rx_kill_vid = velocity_vlan_rx_kill_vid;
+       dev->vlan_rx_register = velocity_vlan_rx_register;
 
 #ifdef  VELOCITY_ZERO_COPY_SUPPORT
        dev->features |= NETIF_F_SG;
 #endif
-       dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER;
+       dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER |
+               NETIF_F_HW_VLAN_RX;
 
        if (vptr->flags & VELOCITY_FLAGS_TX_CSUM)
                dev->features |= NETIF_F_IP_CSUM;
@@ -1597,8 +1602,13 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
        skb_put(skb, pkt_len - 4);
        skb->protocol = eth_type_trans(skb, vptr->dev);
 
+       if (vptr->vlgrp && (rd->rdesc0.RSR & RSR_DETAG)) {
+               vlan_hwaccel_rx(skb, vptr->vlgrp,
+                               swab16(le16_to_cpu(rd->rdesc1.PQTAG)));
+       } else
+               netif_rx(skb);
+
        stats->rx_bytes += pkt_len;
-       netif_rx(skb);
 
        return 0;
 }
index c4c8eab8574f79bb36fc3352648d8df09ab579fb..c2cc42f723d5fdd517ca209183b0b147645cff4b 100644 (file)
@@ -402,7 +402,7 @@ static int __init c101_init(void)
 #ifdef MODULE
                printk(KERN_INFO "c101: no card initialized\n");
 #endif
-               return -ENOSYS; /* no parameters specified, abort */
+               return -EINVAL; /* no parameters specified, abort */
        }
 
        printk(KERN_INFO "%s\n", version);
@@ -420,11 +420,11 @@ static int __init c101_init(void)
                        c101_run(irq, ram);
 
                if (*hw == '\x0')
-                       return first_card ? 0 : -ENOSYS;
+                       return first_card ? 0 : -EINVAL;
        }while(*hw++ == ':');
 
        printk(KERN_ERR "c101: invalid hardware parameters\n");
-       return first_card ? 0 : -ENOSYS;
+       return first_card ? 0 : -EINVAL;
 }
 
 
index c4ab0326f91103b03dcd01dd7b1a153101ef4ea9..520bb0b1a9a2f6f1c6a74d00d9200631fda23bf5 100644 (file)
@@ -1090,10 +1090,6 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
        pvc_device *pvc = NULL;
        struct net_device *dev;
        int result, used;
-       char * prefix = "pvc%d";
-
-       if (type == ARPHRD_ETHER)
-               prefix = "pvceth%d";
 
        if ((pvc = add_pvc(frad, dlci)) == NULL) {
                printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n",
index 7483d45bc5bccffefd18b4fa94122eb78d40460f..e62018a36133604bf5fdcae1a95268bb0c8531b6 100644 (file)
@@ -1809,3 +1809,5 @@ module_exit(netif_exit);
 
 MODULE_DESCRIPTION("Xen virtual network device frontend");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("xen:vif");
+MODULE_ALIAS("xennet");
index 631689171159fd8d590eb5d3d58c8d55d16ccf46..715a444716177a9dfb4f5cdff90700ca31776ebd 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/i2c.h>
 #include <linux/of.h>
+#include <linux/module.h>
 
 struct i2c_driver_device {
        char    *of_device;
@@ -113,3 +114,5 @@ void of_register_i2c_devices(struct i2c_adapter *adap,
        }
 }
 EXPORT_SYMBOL(of_register_i2c_devices);
+
+MODULE_LICENSE("GPL");
index 301c68fab03befa1c10d60d8fe6d9d65fcd9583d..1fd8bb7657024c2629858940fc050a35fc3acab7 100644 (file)
@@ -1905,32 +1905,31 @@ get_valid_domain_for_dev(struct pci_dev *pdev)
        return domain;
 }
 
-static dma_addr_t intel_map_single(struct device *hwdev, void *addr,
-       size_t size, int dir)
+static dma_addr_t
+intel_map_single(struct device *hwdev, phys_addr_t paddr, size_t size, int dir)
 {
        struct pci_dev *pdev = to_pci_dev(hwdev);
-       int ret;
        struct dmar_domain *domain;
-       unsigned long start_addr;
+       unsigned long start_paddr;
        struct iova *iova;
        int prot = 0;
+       int ret;
 
        BUG_ON(dir == DMA_NONE);
        if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
-               return virt_to_bus(addr);
+               return paddr;
 
        domain = get_valid_domain_for_dev(pdev);
        if (!domain)
                return 0;
 
-       addr = (void *)virt_to_phys(addr);
-       size = aligned_size((u64)addr, size);
+       size = aligned_size((u64)paddr, size);
 
        iova = __intel_alloc_iova(hwdev, domain, size);
        if (!iova)
                goto error;
 
-       start_addr = iova->pfn_lo << PAGE_SHIFT_4K;
+       start_paddr = iova->pfn_lo << PAGE_SHIFT_4K;
 
        /*
         * Check if DMAR supports zero-length reads on write only
@@ -1942,33 +1941,33 @@ static dma_addr_t intel_map_single(struct device *hwdev, void *addr,
        if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
                prot |= DMA_PTE_WRITE;
        /*
-        * addr - (addr + size) might be partial page, we should map the whole
+        * paddr - (paddr + size) might be partial page, we should map the whole
         * page.  Note: if two part of one page are separately mapped, we
-        * might have two guest_addr mapping to the same host addr, but this
+        * might have two guest_addr mapping to the same host paddr, but this
         * is not a big problem
         */
-       ret = domain_page_mapping(domain, start_addr,
-               ((u64)addr) & PAGE_MASK_4K, size, prot);
+       ret = domain_page_mapping(domain, start_paddr,
+               ((u64)paddr) & PAGE_MASK_4K, size, prot);
        if (ret)
                goto error;
 
        pr_debug("Device %s request: %lx@%llx mapping: %lx@%llx, dir %d\n",
-               pci_name(pdev), size, (u64)addr,
-               size, (u64)start_addr, dir);
+               pci_name(pdev), size, (u64)paddr,
+               size, (u64)start_paddr, dir);
 
        /* it's a non-present to present mapping */
        ret = iommu_flush_iotlb_psi(domain->iommu, domain->id,
-                       start_addr, size >> PAGE_SHIFT_4K, 1);
+                       start_paddr, size >> PAGE_SHIFT_4K, 1);
        if (ret)
                iommu_flush_write_buffer(domain->iommu);
 
-       return (start_addr + ((u64)addr & (~PAGE_MASK_4K)));
+       return (start_paddr + ((u64)paddr & (~PAGE_MASK_4K)));
 
 error:
        if (iova)
                __free_iova(&domain->iovad, iova);
        printk(KERN_ERR"Device %s request: %lx@%llx dir %d --- failed\n",
-               pci_name(pdev), size, (u64)addr, dir);
+               pci_name(pdev), size, (u64)paddr, dir);
        return 0;
 }
 
@@ -2082,7 +2081,7 @@ static void * intel_alloc_coherent(struct device *hwdev, size_t size,
                return NULL;
        memset(vaddr, 0, size);
 
-       *dma_handle = intel_map_single(hwdev, vaddr, size, DMA_BIDIRECTIONAL);
+       *dma_handle = intel_map_single(hwdev, virt_to_bus(vaddr), size, DMA_BIDIRECTIONAL);
        if (*dma_handle)
                return vaddr;
        free_pages((unsigned long)vaddr, order);
index 5a888704a8d002ca0d846308f51e052ec4a3301b..4f4e7cf105d4985c425aedf30f79a72ed3fb3ab6 100644 (file)
@@ -5,7 +5,7 @@
 CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
 
 obj-y += s390mach.o sysinfo.o s390_rdev.o
-obj-y += cio/ block/ char/ crypto/ net/ scsi/
+obj-y += cio/ block/ char/ crypto/ net/ scsi/ kvm/
 
 drivers-y += drivers/s390/built-in.o
 
diff --git a/drivers/s390/kvm/Makefile b/drivers/s390/kvm/Makefile
new file mode 100644 (file)
index 0000000..4a5ec39
--- /dev/null
@@ -0,0 +1,9 @@
+# Makefile for kvm guest drivers on s390
+#
+# Copyright IBM Corp. 2008
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License (version 2 only)
+# as published by the Free Software Foundation.
+
+obj-$(CONFIG_VIRTIO) += kvm_virtio.o
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
new file mode 100644 (file)
index 0000000..bbef376
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ * kvm_virtio.c - virtio for kvm on s390
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
+ */
+
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/err.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+#include <linux/interrupt.h>
+#include <linux/virtio_ring.h>
+#include <asm/io.h>
+#include <asm/kvm_para.h>
+#include <asm/kvm_virtio.h>
+#include <asm/setup.h>
+#include <asm/s390_ext.h>
+
+#define VIRTIO_SUBCODE_64 0x0D00
+
+/*
+ * The pointer to our (page) of device descriptions.
+ */
+static void *kvm_devices;
+
+/*
+ * Unique numbering for kvm devices.
+ */
+static unsigned int dev_index;
+
+struct kvm_device {
+       struct virtio_device vdev;
+       struct kvm_device_desc *desc;
+};
+
+#define to_kvmdev(vd) container_of(vd, struct kvm_device, vdev)
+
+/*
+ * memory layout:
+ * - kvm_device_descriptor
+ *        struct kvm_device_desc
+ * - configuration
+ *        struct kvm_vqconfig
+ * - feature bits
+ * - config space
+ */
+static struct kvm_vqconfig *kvm_vq_config(const struct kvm_device_desc *desc)
+{
+       return (struct kvm_vqconfig *)(desc + 1);
+}
+
+static u8 *kvm_vq_features(const struct kvm_device_desc *desc)
+{
+       return (u8 *)(kvm_vq_config(desc) + desc->num_vq);
+}
+
+static u8 *kvm_vq_configspace(const struct kvm_device_desc *desc)
+{
+       return kvm_vq_features(desc) + desc->feature_len * 2;
+}
+
+/*
+ * The total size of the config page used by this device (incl. desc)
+ */
+static unsigned desc_size(const struct kvm_device_desc *desc)
+{
+       return sizeof(*desc)
+               + desc->num_vq * sizeof(struct kvm_vqconfig)
+               + desc->feature_len * 2
+               + desc->config_len;
+}
+
+/*
+ * This tests (and acknowleges) a feature bit.
+ */
+static bool kvm_feature(struct virtio_device *vdev, unsigned fbit)
+{
+       struct kvm_device_desc *desc = to_kvmdev(vdev)->desc;
+       u8 *features;
+
+       if (fbit / 8 > desc->feature_len)
+               return false;
+
+       features = kvm_vq_features(desc);
+       if (!(features[fbit / 8] & (1 << (fbit % 8))))
+               return false;
+
+       /*
+        * We set the matching bit in the other half of the bitmap to tell the
+        * Host we want to use this feature.
+        */
+       features[desc->feature_len + fbit / 8] |= (1 << (fbit % 8));
+       return true;
+}
+
+/*
+ * Reading and writing elements in config space
+ */
+static void kvm_get(struct virtio_device *vdev, unsigned int offset,
+                  void *buf, unsigned len)
+{
+       struct kvm_device_desc *desc = to_kvmdev(vdev)->desc;
+
+       BUG_ON(offset + len > desc->config_len);
+       memcpy(buf, kvm_vq_configspace(desc) + offset, len);
+}
+
+static void kvm_set(struct virtio_device *vdev, unsigned int offset,
+                  const void *buf, unsigned len)
+{
+       struct kvm_device_desc *desc = to_kvmdev(vdev)->desc;
+
+       BUG_ON(offset + len > desc->config_len);
+       memcpy(kvm_vq_configspace(desc) + offset, buf, len);
+}
+
+/*
+ * The operations to get and set the status word just access
+ * the status field of the device descriptor. set_status will also
+ * make a hypercall to the host, to tell about status changes
+ */
+static u8 kvm_get_status(struct virtio_device *vdev)
+{
+       return to_kvmdev(vdev)->desc->status;
+}
+
+static void kvm_set_status(struct virtio_device *vdev, u8 status)
+{
+       BUG_ON(!status);
+       to_kvmdev(vdev)->desc->status = status;
+       kvm_hypercall1(KVM_S390_VIRTIO_SET_STATUS,
+                      (unsigned long) to_kvmdev(vdev)->desc);
+}
+
+/*
+ * To reset the device, we use the KVM_VIRTIO_RESET hypercall, using the
+ * descriptor address. The Host will zero the status and all the
+ * features.
+ */
+static void kvm_reset(struct virtio_device *vdev)
+{
+       kvm_hypercall1(KVM_S390_VIRTIO_RESET,
+                      (unsigned long) to_kvmdev(vdev)->desc);
+}
+
+/*
+ * When the virtio_ring code wants to notify the Host, it calls us here and we
+ * make a hypercall.  We hand the address  of the virtqueue so the Host
+ * knows which virtqueue we're talking about.
+ */
+static void kvm_notify(struct virtqueue *vq)
+{
+       struct kvm_vqconfig *config = vq->priv;
+
+       kvm_hypercall1(KVM_S390_VIRTIO_NOTIFY, config->address);
+}
+
+/*
+ * This routine finds the first virtqueue described in the configuration of
+ * this device and sets it up.
+ */
+static struct virtqueue *kvm_find_vq(struct virtio_device *vdev,
+                                   unsigned index,
+                                   void (*callback)(struct virtqueue *vq))
+{
+       struct kvm_device *kdev = to_kvmdev(vdev);
+       struct kvm_vqconfig *config;
+       struct virtqueue *vq;
+       int err;
+
+       if (index >= kdev->desc->num_vq)
+               return ERR_PTR(-ENOENT);
+
+       config = kvm_vq_config(kdev->desc)+index;
+
+       if (add_shared_memory(config->address,
+                               vring_size(config->num, PAGE_SIZE))) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       vq = vring_new_virtqueue(config->num, vdev, (void *) config->address,
+                                kvm_notify, callback);
+       if (!vq) {
+               err = -ENOMEM;
+               goto unmap;
+       }
+
+       /*
+        * register a callback token
+        * The host will sent this via the external interrupt parameter
+        */
+       config->token = (u64) vq;
+
+       vq->priv = config;
+       return vq;
+unmap:
+       remove_shared_memory(config->address, vring_size(config->num,
+                            PAGE_SIZE));
+out:
+       return ERR_PTR(err);
+}
+
+static void kvm_del_vq(struct virtqueue *vq)
+{
+       struct kvm_vqconfig *config = vq->priv;
+
+       vring_del_virtqueue(vq);
+       remove_shared_memory(config->address,
+                            vring_size(config->num, PAGE_SIZE));
+}
+
+/*
+ * The config ops structure as defined by virtio config
+ */
+static struct virtio_config_ops kvm_vq_configspace_ops = {
+       .feature = kvm_feature,
+       .get = kvm_get,
+       .set = kvm_set,
+       .get_status = kvm_get_status,
+       .set_status = kvm_set_status,
+       .reset = kvm_reset,
+       .find_vq = kvm_find_vq,
+       .del_vq = kvm_del_vq,
+};
+
+/*
+ * The root device for the kvm virtio devices.
+ * This makes them appear as /sys/devices/kvm_s390/0,1,2 not /sys/devices/0,1,2.
+ */
+static struct device kvm_root = {
+       .parent = NULL,
+       .bus_id = "kvm_s390",
+};
+
+/*
+ * adds a new device and register it with virtio
+ * appropriate drivers are loaded by the device model
+ */
+static void add_kvm_device(struct kvm_device_desc *d)
+{
+       struct kvm_device *kdev;
+
+       kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
+       if (!kdev) {
+               printk(KERN_EMERG "Cannot allocate kvm dev %u\n",
+                      dev_index++);
+               return;
+       }
+
+       kdev->vdev.dev.parent = &kvm_root;
+       kdev->vdev.index = dev_index++;
+       kdev->vdev.id.device = d->type;
+       kdev->vdev.config = &kvm_vq_configspace_ops;
+       kdev->desc = d;
+
+       if (register_virtio_device(&kdev->vdev) != 0) {
+               printk(KERN_ERR "Failed to register kvm device %u\n",
+                      kdev->vdev.index);
+               kfree(kdev);
+       }
+}
+
+/*
+ * scan_devices() simply iterates through the device page.
+ * The type 0 is reserved to mean "end of devices".
+ */
+static void scan_devices(void)
+{
+       unsigned int i;
+       struct kvm_device_desc *d;
+
+       for (i = 0; i < PAGE_SIZE; i += desc_size(d)) {
+               d = kvm_devices + i;
+
+               if (d->type == 0)
+                       break;
+
+               add_kvm_device(d);
+       }
+}
+
+/*
+ * we emulate the request_irq behaviour on top of s390 extints
+ */
+static void kvm_extint_handler(u16 code)
+{
+       void *data = (void *) *(long *) __LC_PFAULT_INTPARM;
+       u16 subcode = S390_lowcore.cpu_addr;
+
+       if ((subcode & 0xff00) != VIRTIO_SUBCODE_64)
+               return;
+
+       vring_interrupt(0, data);
+}
+
+/*
+ * Init function for virtio
+ * devices are in a single page above top of "normal" mem
+ */
+static int __init kvm_devices_init(void)
+{
+       int rc;
+
+       if (!MACHINE_IS_KVM)
+               return -ENODEV;
+
+       rc = device_register(&kvm_root);
+       if (rc) {
+               printk(KERN_ERR "Could not register kvm_s390 root device");
+               return rc;
+       }
+
+       if (add_shared_memory((max_pfn) << PAGE_SHIFT, PAGE_SIZE)) {
+               device_unregister(&kvm_root);
+               return -ENOMEM;
+       }
+
+       kvm_devices  = (void *) (max_pfn << PAGE_SHIFT);
+
+       ctl_set_bit(0, 9);
+       register_external_interrupt(0x2603, kvm_extint_handler);
+
+       scan_devices();
+       return 0;
+}
+
+/*
+ * We do this after core stuff, but before the drivers.
+ */
+postcore_initcall(kvm_devices_init);
index 7c3f02816e95c35b8ed6005c9f0c7d7fa2f9fa21..9af2330f07a21c0019b0df6d5495427ae4ba38b3 100644 (file)
@@ -1927,7 +1927,8 @@ zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter,
 
        /* setup new FSF request */
        retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA,
-                                    0, NULL, &lock_flags, &fsf_req);
+                                    ZFCP_WAIT_FOR_SBAL, NULL, &lock_flags,
+                                    &fsf_req);
        if (retval) {
                ZFCP_LOG_INFO("error: Could not create exchange configuration "
                              "data request for adapter %s.\n",
@@ -2035,21 +2036,21 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
                       min(FC_SERIAL_NUMBER_SIZE, 17));
        }
 
-       ZFCP_LOG_NORMAL("The adapter %s reported the following "
-                       "characteristics:\n"
-                       "WWNN 0x%016Lx, "
-                       "WWPN 0x%016Lx, "
-                       "S_ID 0x%06x,\n"
-                       "adapter version 0x%x, "
-                       "LIC version 0x%x, "
-                       "FC link speed %d Gb/s\n",
-                       zfcp_get_busid_by_adapter(adapter),
-                       (wwn_t) fc_host_node_name(shost),
-                       (wwn_t) fc_host_port_name(shost),
-                       fc_host_port_id(shost),
-                       adapter->hydra_version,
-                       adapter->fsf_lic_version,
-                       fc_host_speed(shost));
+       if (fsf_req->erp_action)
+               ZFCP_LOG_NORMAL("The adapter %s reported the following "
+                               "characteristics:\n"
+                               "WWNN 0x%016Lx, WWPN 0x%016Lx, "
+                               "S_ID 0x%06x,\n"
+                               "adapter version 0x%x, "
+                               "LIC version 0x%x, "
+                               "FC link speed %d Gb/s\n",
+                               zfcp_get_busid_by_adapter(adapter),
+                               (wwn_t) fc_host_node_name(shost),
+                               (wwn_t) fc_host_port_name(shost),
+                               fc_host_port_id(shost),
+                               adapter->hydra_version,
+                               adapter->fsf_lic_version,
+                               fc_host_speed(shost));
        if (ZFCP_QTCB_VERSION < bottom->low_qtcb_version) {
                ZFCP_LOG_NORMAL("error: the adapter %s "
                                "only supports newer control block "
@@ -2114,8 +2115,10 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
                        zfcp_erp_adapter_shutdown(adapter, 0, 127, fsf_req);
                        return -EIO;
                case FC_PORTTYPE_NPORT:
-                       ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
-                                       "network detected at adapter %s.\n",
+                       if (fsf_req->erp_action)
+                               ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
+                                               "network detected at adapter "
+                                               "%s.\n",
                                        zfcp_get_busid_by_adapter(adapter));
                        break;
                default:
index 8cce5cc11d50c23e0df383ad08d65ee5ab67136f..099970b2700175f01bbbad8de08e96871f108a7e 100644 (file)
 #define FSF_FEATURE_HBAAPI_MANAGEMENT           0x00000010
 #define FSF_FEATURE_ELS_CT_CHAINED_SBALS        0x00000020
 #define FSF_FEATURE_UPDATE_ALERT               0x00000100
+#define FSF_FEATURE_MEASUREMENT_DATA           0x00000200
 
 /* host connection features */
 #define FSF_FEATURE_NPIV_MODE                  0x00000001
@@ -340,6 +341,15 @@ struct fsf_qtcb_prefix {
        u8  res1[20];
 } __attribute__ ((packed));
 
+struct fsf_statistics_info {
+       u64 input_req;
+       u64 output_req;
+       u64 control_req;
+       u64 input_mb;
+       u64 output_mb;
+       u64 seconds_act;
+} __attribute__ ((packed));
+
 union fsf_status_qual {
        u8  byte[FSF_STATUS_QUALIFIER_SIZE];
        u16 halfword[FSF_STATUS_QUALIFIER_SIZE / sizeof (u16)];
@@ -436,7 +446,8 @@ struct fsf_qtcb_bottom_config {
        u32 hardware_version;
        u8 serial_number[32];
        struct fsf_nport_serv_param plogi_payload;
-       u8 res4[160];
+       struct fsf_statistics_info stat_info;
+       u8 res4[112];
 } __attribute__ ((packed));
 
 struct fsf_qtcb_bottom_port {
@@ -469,7 +480,10 @@ struct fsf_qtcb_bottom_port {
        u64 control_requests;
        u64 input_mb;           /* where 1 MByte == 1.000.000 Bytes */
        u64 output_mb;          /* where 1 MByte == 1.000.000 Bytes */
-       u8 res2[256];
+       u8 cp_util;
+       u8 cb_util;
+       u8 a_util;
+       u8 res2[253];
 } __attribute__ ((packed));
 
 union fsf_qtcb_bottom {
index f81850624eedc5b5ca0e33119275e4964acaaebb..01687559dc06094fc4f81d89ab6256e2717a56a7 100644 (file)
@@ -40,6 +40,7 @@ static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int,
                                          unsigned int, unsigned int);
 
 static struct device_attribute *zfcp_sysfs_sdev_attrs[];
+static struct device_attribute *zfcp_a_stats_attrs[];
 
 struct zfcp_data zfcp_data = {
        .scsi_host_template = {
@@ -61,6 +62,7 @@ struct zfcp_data zfcp_data = {
                .use_clustering         = 1,
                .sdev_attrs             = zfcp_sysfs_sdev_attrs,
                .max_sectors            = ZFCP_MAX_SECTORS,
+               .shost_attrs            = zfcp_a_stats_attrs,
        },
        .driver_version = ZFCP_VERSION,
 };
@@ -809,4 +811,116 @@ static struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
        NULL
 };
 
+static ssize_t zfcp_sysfs_adapter_util_show(struct device *dev,
+                                           struct device_attribute *attr,
+                                           char *buf)
+{
+       struct Scsi_Host *scsi_host = dev_to_shost(dev);
+       struct fsf_qtcb_bottom_port *qtcb_port;
+       int retval;
+       struct zfcp_adapter *adapter;
+
+       adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
+       if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
+               return -EOPNOTSUPP;
+
+       qtcb_port = kzalloc(sizeof(struct fsf_qtcb_bottom_port), GFP_KERNEL);
+       if (!qtcb_port)
+               return -ENOMEM;
+
+       retval = zfcp_fsf_exchange_port_data_sync(adapter, qtcb_port);
+       if (!retval)
+               retval = sprintf(buf, "%u %u %u\n", qtcb_port->cp_util,
+                                qtcb_port->cb_util, qtcb_port->a_util);
+       kfree(qtcb_port);
+       return retval;
+}
+
+static int zfcp_sysfs_adapter_ex_config(struct device *dev,
+                                       struct fsf_statistics_info *stat_inf)
+{
+       int retval;
+       struct fsf_qtcb_bottom_config *qtcb_config;
+       struct Scsi_Host *scsi_host = dev_to_shost(dev);
+       struct zfcp_adapter *adapter;
+
+       adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
+       if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
+               return -EOPNOTSUPP;
+
+       qtcb_config = kzalloc(sizeof(struct fsf_qtcb_bottom_config),
+                              GFP_KERNEL);
+       if (!qtcb_config)
+               return -ENOMEM;
+
+       retval = zfcp_fsf_exchange_config_data_sync(adapter, qtcb_config);
+       if (!retval)
+               *stat_inf = qtcb_config->stat_info;
+
+       kfree(qtcb_config);
+       return retval;
+}
+
+static ssize_t zfcp_sysfs_adapter_request_show(struct device *dev,
+                                              struct device_attribute *attr,
+                                              char *buf)
+{
+       struct fsf_statistics_info stat_info;
+       int retval;
+
+       retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
+       if (retval)
+               return retval;
+
+       return sprintf(buf, "%llu %llu %llu\n",
+                      (unsigned long long) stat_info.input_req,
+                      (unsigned long long) stat_info.output_req,
+                      (unsigned long long) stat_info.control_req);
+}
+
+static ssize_t zfcp_sysfs_adapter_mb_show(struct device *dev,
+                                         struct device_attribute *attr,
+                                         char *buf)
+{
+       struct fsf_statistics_info stat_info;
+       int retval;
+
+       retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
+       if (retval)
+               return retval;
+
+       return sprintf(buf, "%llu %llu\n",
+                      (unsigned long long) stat_info.input_mb,
+                      (unsigned long long) stat_info.output_mb);
+}
+
+static ssize_t zfcp_sysfs_adapter_sec_active_show(struct device *dev,
+                                                 struct device_attribute *attr,
+                                                 char *buf)
+{
+       struct fsf_statistics_info stat_info;
+       int retval;
+
+       retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
+       if (retval)
+               return retval;
+
+       return sprintf(buf, "%llu\n",
+                      (unsigned long long) stat_info.seconds_act);
+}
+
+static DEVICE_ATTR(utilization, S_IRUGO, zfcp_sysfs_adapter_util_show, NULL);
+static DEVICE_ATTR(requests, S_IRUGO, zfcp_sysfs_adapter_request_show, NULL);
+static DEVICE_ATTR(megabytes, S_IRUGO, zfcp_sysfs_adapter_mb_show, NULL);
+static DEVICE_ATTR(seconds_active, S_IRUGO,
+                  zfcp_sysfs_adapter_sec_active_show, NULL);
+
+static struct device_attribute *zfcp_a_stats_attrs[] = {
+       &dev_attr_utilization,
+       &dev_attr_requests,
+       &dev_attr_megabytes,
+       &dev_attr_seconds_active,
+       NULL
+};
+
 #undef ZFCP_LOG_AREA
index b374e457e5e2ded4401697ce2e63e88252376f41..b898d382b7b0768d93ed3250bb0782ba1d38c095 100644 (file)
@@ -1499,7 +1499,7 @@ static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
        thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
        ioport = ((struct sccb_card *)pCurrCard)->ioPort;
 
-       if ((p_Sccb->TargID > MAX_SCSI_TAR) || (p_Sccb->Lun > MAX_LUN)) {
+       if ((p_Sccb->TargID >= MAX_SCSI_TAR) || (p_Sccb->Lun >= MAX_LUN)) {
 
                p_Sccb->HostStatus = SCCB_COMPLETE;
                p_Sccb->SccbStatus = SCCB_ERROR;
index 7f78e3ea517d7e9afa272af07d017c8ae26758bf..99c57b0c1d540c5d8e7d63138ebd76bc7dc4db4f 100644 (file)
@@ -1677,6 +1677,16 @@ config MAC_SCSI
          SCSI-HOWTO, available from
          <http://www.tldp.org/docs.html#howto>.
 
+config SCSI_MAC_ESP
+       tristate "Macintosh NCR53c9[46] SCSI"
+       depends on MAC && SCSI
+       help
+         This is the NCR 53c9x SCSI controller found on most of the 68040
+         based Macintoshes.
+
+         To compile this driver as a module, choose M here: the module
+         will be called mac_esp.
+
 config MVME147_SCSI
        bool "WD33C93 SCSI driver for MVME147"
        depends on MVME147 && SCSI=y
index 23e6ecbd47780bcc59a0042727e710065306b7b5..6c775e350c9842718283cbd9a6340c139e3e4914 100644 (file)
@@ -46,6 +46,7 @@ obj-$(CONFIG_MVME147_SCSI)    += mvme147.o    wd33c93.o
 obj-$(CONFIG_SGIWD93_SCSI)     += sgiwd93.o    wd33c93.o
 obj-$(CONFIG_ATARI_SCSI)       += atari_scsi.o
 obj-$(CONFIG_MAC_SCSI)         += mac_scsi.o
+obj-$(CONFIG_SCSI_MAC_ESP)     += esp_scsi.o   mac_esp.o
 obj-$(CONFIG_SUN3_SCSI)                += sun3_scsi.o  sun3_scsi_vme.o
 obj-$(CONFIG_MVME16x_SCSI)     += 53c700.o     mvme16x_scsi.o
 obj-$(CONFIG_BVME6000_SCSI)    += 53c700.o     bvme6000_scsi.o
index 6ccdc96cc480559c4e259a79d004e4589d316300..a09b2d3fdf5a30ced18a487b799fa7598be05455 100644 (file)
@@ -1432,15 +1432,10 @@ static void run(struct work_struct *work)
  */
 static irqreturn_t intr(int irqno, void *dev_id)
 {
-       struct Scsi_Host *shpnt = (struct Scsi_Host *)dev_id;
+       struct Scsi_Host *shpnt = dev_id;
        unsigned long flags;
        unsigned char rev, dmacntrl0;
 
-       if (!shpnt) {
-               printk(KERN_ERR "aha152x: catched interrupt %d for unknown controller.\n", irqno);
-               return IRQ_NONE;
-       }
-
        /*
         * Read a couple of registers that are known to not be all 1's. If
         * we read all 1's (-1), that means that either:
index 5a1471c370fa70f601a845fb66e762701bc2d1a8..80594947c6f6c1a97117be2bedde8fa9b83c75a8 100644 (file)
@@ -153,8 +153,6 @@ struct aha1542_hostdata {
 
 #define HOSTDATA(host) ((struct aha1542_hostdata *) &host->hostdata)
 
-static struct Scsi_Host *aha_host[7];  /* One for each IRQ level (9-15) */
-
 static DEFINE_SPINLOCK(aha1542_lock);
 
 
@@ -163,8 +161,7 @@ static DEFINE_SPINLOCK(aha1542_lock);
 
 static void setup_mailboxes(int base_io, struct Scsi_Host *shpnt);
 static int aha1542_restart(struct Scsi_Host *shost);
-static void aha1542_intr_handle(struct Scsi_Host *shost, void *dev_id);
-static irqreturn_t do_aha1542_intr_handle(int irq, void *dev_id);
+static void aha1542_intr_handle(struct Scsi_Host *shost);
 
 #define aha1542_intr_reset(base)  outb(IRST, CONTROL(base))
 
@@ -404,23 +401,19 @@ fail:
 }
 
 /* A quick wrapper for do_aha1542_intr_handle to grab the spin lock */
-static irqreturn_t do_aha1542_intr_handle(int irq, void *dev_id)
+static irqreturn_t do_aha1542_intr_handle(int dummy, void *dev_id)
 {
        unsigned long flags;
-       struct Scsi_Host *shost;
-
-       shost = aha_host[irq - 9];
-       if (!shost)
-               panic("Splunge!");
+       struct Scsi_Host *shost = dev_id;
 
        spin_lock_irqsave(shost->host_lock, flags);
-       aha1542_intr_handle(shost, dev_id);
+       aha1542_intr_handle(shost);
        spin_unlock_irqrestore(shost->host_lock, flags);
        return IRQ_HANDLED;
 }
 
 /* A "high" level interrupt handler */
-static void aha1542_intr_handle(struct Scsi_Host *shost, void *dev_id)
+static void aha1542_intr_handle(struct Scsi_Host *shost)
 {
        void (*my_done) (Scsi_Cmnd *) = NULL;
        int errstatus, mbi, mbo, mbistatus;
@@ -1197,7 +1190,8 @@ fail:
 
                        DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level));
                        spin_lock_irqsave(&aha1542_lock, flags);
-                       if (request_irq(irq_level, do_aha1542_intr_handle, 0, "aha1542", NULL)) {
+                       if (request_irq(irq_level, do_aha1542_intr_handle, 0,
+                                       "aha1542", shpnt)) {
                                printk(KERN_ERR "Unable to allocate IRQ for adaptec controller.\n");
                                spin_unlock_irqrestore(&aha1542_lock, flags);
                                goto unregister;
@@ -1205,7 +1199,7 @@ fail:
                        if (dma_chan != 0xFF) {
                                if (request_dma(dma_chan, "aha1542")) {
                                        printk(KERN_ERR "Unable to allocate DMA channel for Adaptec.\n");
-                                       free_irq(irq_level, NULL);
+                                       free_irq(irq_level, shpnt);
                                        spin_unlock_irqrestore(&aha1542_lock, flags);
                                        goto unregister;
                                }
@@ -1214,7 +1208,7 @@ fail:
                                        enable_dma(dma_chan);
                                }
                        }
-                       aha_host[irq_level - 9] = shpnt;
+
                        shpnt->this_id = scsi_id;
                        shpnt->unique_id = base_io;
                        shpnt->io_port = base_io;
@@ -1276,7 +1270,7 @@ unregister:
 static int aha1542_release(struct Scsi_Host *shost)
 {
        if (shost->irq)
-               free_irq(shost->irq, NULL);
+               free_irq(shost->irq, shost);
        if (shost->dma_channel != 0xff)
                free_dma(shost->dma_channel);
        if (shost->io_port && shost->n_io_port)
index 2f00467b6b8c8bd12418614d186e475f2fd24590..be5558ab84ea06622e51f3a7f176d3efcba2e3f6 100644 (file)
@@ -815,7 +815,7 @@ struct ahd_tmode_tstate {
 struct ahd_phase_table_entry {
         uint8_t phase;
         uint8_t mesg_out; /* Message response to parity errors */
-       char *phasemsg;
+       const char *phasemsg;
 };
 
 /************************** Serial EEPROM Format ******************************/
@@ -1314,7 +1314,7 @@ typedef int (ahd_device_setup_t)(struct ahd_softc *);
 struct ahd_pci_identity {
        uint64_t                 full_id;
        uint64_t                 id_mask;
-       char                    *name;
+       const char              *name;
        ahd_device_setup_t      *setup;
 };
 
@@ -1322,7 +1322,7 @@ struct ahd_pci_identity {
 struct aic7770_identity {
        uint32_t                 full_id;
        uint32_t                 id_mask;
-       char                    *name;
+       const char              *name;
        ahd_device_setup_t      *setup;
 };
 extern struct aic7770_identity aic7770_ident_table [];
@@ -1333,12 +1333,11 @@ extern const int ahd_num_aic7770_devs;
 
 /*************************** Function Declarations ****************************/
 /******************************************************************************/
-void                   ahd_reset_cmds_pending(struct ahd_softc *ahd);
 
 /***************************** PCI Front End *********************************/
-struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t);
+const struct   ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t);
 int                      ahd_pci_config(struct ahd_softc *,
-                                        struct ahd_pci_identity *);
+                                        const struct ahd_pci_identity *);
 int    ahd_pci_test_register_access(struct ahd_softc *);
 #ifdef CONFIG_PM
 void   ahd_pci_suspend(struct ahd_softc *);
@@ -1376,16 +1375,6 @@ int                       ahd_write_flexport(struct ahd_softc *ahd,
 int                     ahd_read_flexport(struct ahd_softc *ahd, u_int addr,
                                           uint8_t *value);
 
-/*************************** Interrupt Services *******************************/
-void                   ahd_run_qoutfifo(struct ahd_softc *ahd);
-#ifdef AHD_TARGET_MODE
-void                   ahd_run_tqinfifo(struct ahd_softc *ahd, int paused);
-#endif
-void                   ahd_handle_hwerrint(struct ahd_softc *ahd);
-void                   ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat);
-void                   ahd_handle_scsiint(struct ahd_softc *ahd,
-                                          u_int intstat);
-
 /***************************** Error Recovery *********************************/
 typedef enum {
        SEARCH_COMPLETE,
@@ -1479,7 +1468,7 @@ extern uint32_t ahd_debug;
 void                   ahd_print_devinfo(struct ahd_softc *ahd,
                                          struct ahd_devinfo *devinfo);
 void                   ahd_dump_card_state(struct ahd_softc *ahd);
-int                    ahd_print_register(ahd_reg_parse_entry_t *table,
+int                    ahd_print_register(const ahd_reg_parse_entry_t *table,
                                           u_int num_entries,
                                           const char *name,
                                           u_int address,
index be14e2ecb8f796b6bdaebe3c4926481160a238bd..cca16fc5b4ad746a0ec02fedb575eea6dbc7df90 100644 (file)
@@ -198,6 +198,7 @@ register SEQINTCODE {
 register CLRINT {
        address                 0x003
        access_mode     WO
+       count           19
        field   CLRHWERRINT     0x80 /* Rev B or greater */
        field   CLRBRKADRINT    0x40
        field   CLRSWTMINT      0x20
@@ -245,6 +246,7 @@ register CLRERR {
 register HCNTRL {
        address                 0x005
        access_mode     RW
+       count           12
        field   SEQ_RESET       0x80 /* Rev B or greater */
        field   POWRDN          0x40
        field   SWINT           0x10
@@ -262,6 +264,7 @@ register HNSCB_QOFF {
        address                 0x006
        access_mode     RW
        size            2
+       count           2
 }
 
 /*
@@ -270,6 +273,7 @@ register HNSCB_QOFF {
 register HESCB_QOFF {
        address                 0x008
        access_mode     RW
+       count           2
 }
 
 /*
@@ -287,6 +291,7 @@ register HS_MAILBOX {
  */
 register SEQINTSTAT {
        address                 0x00C
+       count           1
        access_mode     RO
        field   SEQ_SWTMRTO     0x10
        field   SEQ_SEQINT      0x08
@@ -332,6 +337,7 @@ register SNSCB_QOFF {
  */
 register SESCB_QOFF {
        address                 0x012
+       count           2
        access_mode     RW
        modes           M_CCHAN
 }
@@ -397,6 +403,7 @@ register DFCNTRL {
        address                 0x019
        access_mode     RW
        modes           M_DFF0, M_DFF1
+       count           11
        field   PRELOADEN       0x80
        field   SCSIENWRDIS     0x40    /* Rev B only. */
        field   SCSIEN          0x20
@@ -415,6 +422,7 @@ register DFCNTRL {
  */
 register DSCOMMAND0 {
        address                 0x019
+       count           1
        access_mode     RW
        modes           M_CFG
        field   CACHETHEN       0x80    /* Cache Threshold enable */
@@ -580,6 +588,7 @@ register DFF_THRSH {
        address                 0x088
        access_mode     RW
        modes           M_CFG
+       count           1
        field   WR_DFTHRSH      0x70 {
                WR_DFTHRSH_MIN,
                WR_DFTHRSH_25,
@@ -800,6 +809,7 @@ register PCIXCTL {
        address                 0x093
        access_mode     RW
        modes           M_CFG
+       count           1
        field   SERRPULSE       0x80
        field   UNEXPSCIEN      0x20
        field   SPLTSMADIS      0x10
@@ -844,6 +854,7 @@ register DCHSPLTSTAT0 {
        address                 0x096
        access_mode     RW
        modes           M_DFF0, M_DFF1
+       count           2
        field   STAETERM        0x80
        field   SCBCERR         0x40
        field   SCADERR         0x20
@@ -895,6 +906,7 @@ register DCHSPLTSTAT1 {
        address                 0x097
        access_mode     RW
        modes           M_DFF0, M_DFF1
+       count           2
        field   RXDATABUCKET    0x01
 }
 
@@ -1048,6 +1060,7 @@ register SGSPLTSTAT0 {
        address                 0x09E
        access_mode     RW
        modes           M_DFF0, M_DFF1
+       count           2
        field   STAETERM        0x80
        field   SCBCERR         0x40
        field   SCADERR         0x20
@@ -1065,6 +1078,7 @@ register SGSPLTSTAT1 {
        address                 0x09F
        access_mode     RW
        modes           M_DFF0, M_DFF1
+       count           2
        field   RXDATABUCKET    0x01
 }
 
@@ -1086,6 +1100,7 @@ register DF0PCISTAT {
        address                 0x0A0
        access_mode     RW
        modes           M_CFG
+       count           1
        field   DPE             0x80
        field   SSE             0x40
        field   RMA             0x20
@@ -1184,6 +1199,7 @@ register TARGPCISTAT {
        address                 0x0A7
        access_mode     RW
        modes           M_CFG
+       count           5
        field   DPE             0x80
        field   SSE             0x40
        field   STA             0x08
@@ -1198,6 +1214,7 @@ register LQIN {
        address                 0x020
        access_mode     RW
        size            20
+       count           2
        modes           M_DFF0, M_DFF1, M_SCSI
 }
 
@@ -1229,6 +1246,7 @@ register LUNPTR {
        address                 0x022
        access_mode     RW
        modes           M_CFG
+       count           2
 }
 
 /*
@@ -1259,6 +1277,7 @@ register CMDLENPTR {
        address                 0x025
        access_mode     RW
        modes           M_CFG
+       count           1
 }
 
 /*
@@ -1270,6 +1289,7 @@ register ATTRPTR {
        address                 0x026
        access_mode     RW
        modes           M_CFG
+       count           1
 }
 
 /*
@@ -1281,6 +1301,7 @@ register FLAGPTR {
        address                 0x027
        access_mode     RW
        modes           M_CFG
+       count           1
 }
 
 /*
@@ -1291,6 +1312,7 @@ register CMDPTR {
        address                 0x028
        access_mode     RW
        modes           M_CFG
+       count           1
 }
 
 /*
@@ -1301,6 +1323,7 @@ register QNEXTPTR {
        address                 0x029
        access_mode     RW
        modes           M_CFG
+       count           1
 }
 
 /*
@@ -1323,6 +1346,7 @@ register ABRTBYTEPTR {
        address                 0x02B
        access_mode     RW
        modes           M_CFG
+       count           1
 }
 
 /*
@@ -1333,6 +1357,7 @@ register ABRTBITPTR {
        address                 0x02C
        access_mode     RW
        modes           M_CFG
+       count           1
 }
 
 /*
@@ -1370,6 +1395,7 @@ register LUNLEN {
        address                 0x030
        access_mode     RW
        modes           M_CFG
+       count           2
        mask            ILUNLEN 0x0F
        mask            TLUNLEN 0xF0
 }
@@ -1383,6 +1409,7 @@ register CDBLIMIT {
        address                 0x031
        access_mode     RW
        modes           M_CFG
+       count           1
 }
 
 /*
@@ -1394,6 +1421,7 @@ register MAXCMD {
        address                 0x032
        access_mode     RW
        modes           M_CFG
+       count           9
 }
 
 /*
@@ -1458,6 +1486,7 @@ register LQCTL1 {
        address                 0x038
        access_mode     RW
        modes           M_DFF0, M_DFF1, M_SCSI
+       count           2
        field   PCI2PCI         0x04
        field   SINGLECMD       0x02
        field   ABORTPENDING    0x01
@@ -1470,6 +1499,7 @@ register LQCTL2 {
        address                 0x039
        access_mode     RW
        modes           M_DFF0, M_DFF1, M_SCSI
+       count           5
        field   LQIRETRY        0x80
        field   LQICONTINUE     0x40
        field   LQITOIDLE       0x20
@@ -1528,6 +1558,7 @@ register SCSISEQ1 {
        address                 0x03B
        access_mode     RW
        modes           M_DFF0, M_DFF1, M_SCSI
+       count           8
        field   MANUALCTL       0x40
        field   ENSELI          0x20
        field   ENRSELI         0x10
@@ -1667,6 +1698,9 @@ register SCSISIGO {
        }
 }
 
+/*
+ * SCSI Control Signal In
+ */
 register SCSISIGI {
        address                 0x041
        access_mode     RO
@@ -1703,6 +1737,7 @@ register MULTARGID {
        access_mode     RW
        modes           M_CFG
        size            2
+       count           2
 }
 
 /*
@@ -1758,6 +1793,7 @@ register TARGIDIN {
        address                 0x048
        access_mode     RO
        modes           M_DFF0, M_DFF1, M_SCSI
+       count           2
        field   CLKOUT          0x80
        field   TARGID          0x0F
 }
@@ -1798,6 +1834,7 @@ register OPTIONMODE {
        address                 0x04A
        access_mode     RW
        modes           M_CFG
+       count           4
        field   BIOSCANCTL              0x80
        field   AUTOACKEN               0x40
        field   BIASCANCTL              0x20
@@ -1850,6 +1887,7 @@ register SIMODE0 {
        address                 0x04B
        access_mode     RW
        modes           M_CFG
+       count           8
        field   ENSELDO         0x40
        field   ENSELDI         0x20
        field   ENSELINGO       0x10
@@ -1945,6 +1983,7 @@ register PERRDIAG {
        address                 0x04E
        access_mode     RO
        modes           M_DFF0, M_DFF1, M_SCSI
+       count           3
        field   HIZERO          0x80
        field   HIPERR          0x40
        field   PREVPHASE       0x20
@@ -1962,6 +2001,7 @@ register LQISTATE {
        address                 0x04E
        access_mode     RO
        modes           M_CFG
+       count           6
 }
 
 /*
@@ -1971,6 +2011,7 @@ register SOFFCNT {
        address                 0x04F
        access_mode     RO
        modes           M_DFF0, M_DFF1, M_SCSI
+       count           1
 }
 
 /*
@@ -1980,6 +2021,7 @@ register LQOSTATE {
        address                 0x04F
        access_mode     RO
        modes           M_CFG
+       count           2
 }
 
 /*
@@ -1989,6 +2031,7 @@ register LQISTAT0 {
        address                 0x050
        access_mode     RO
        modes           M_DFF0, M_DFF1, M_SCSI
+       count           2
        field   LQIATNQAS       0x20
        field   LQICRCT1        0x10
        field   LQICRCT2        0x08
@@ -2004,6 +2047,7 @@ register CLRLQIINT0 {
        address                 0x050
        access_mode     WO
        modes           M_DFF0, M_DFF1, M_SCSI
+       count           1
        field   CLRLQIATNQAS    0x20
        field   CLRLQICRCT1     0x10
        field   CLRLQICRCT2     0x08
@@ -2019,6 +2063,7 @@ register LQIMODE0 {
        address                 0x050
        access_mode     RW
        modes           M_CFG
+       count           3
        field   ENLQIATNQASK    0x20
        field   ENLQICRCT1      0x10
        field   ENLQICRCT2      0x08
@@ -2034,6 +2079,7 @@ register LQISTAT1 {
        address                 0x051
        access_mode     RO
        modes           M_DFF0, M_DFF1, M_SCSI
+       count           3
        field   LQIPHASE_LQ     0x80
        field   LQIPHASE_NLQ    0x40
        field   LQIABORT        0x20
@@ -2051,6 +2097,7 @@ register CLRLQIINT1 {
        address                 0x051
        access_mode     WO
        modes           M_DFF0, M_DFF1, M_SCSI
+       count           4
        field   CLRLQIPHASE_LQ  0x80
        field   CLRLQIPHASE_NLQ 0x40
        field   CLRLIQABORT     0x20
@@ -2068,6 +2115,7 @@ register LQIMODE1 {
        address                 0x051
        access_mode     RW
        modes           M_CFG
+       count           4
        field   ENLQIPHASE_LQ   0x80    /* LQIPHASE1 */
        field   ENLQIPHASE_NLQ  0x40    /* LQIPHASE2 */
        field   ENLIQABORT      0x20
@@ -2102,6 +2150,7 @@ register SSTAT3 {
        address                 0x053
        access_mode     RO
        modes           M_DFF0, M_DFF1, M_SCSI
+       count           3
        field   NTRAMPERR       0x02
        field   OSRAMPERR       0x01
 }
@@ -2113,6 +2162,7 @@ register CLRSINT3 {
        address                 0x053
        access_mode     WO
        modes           M_DFF0, M_DFF1, M_SCSI
+       count           3
        field   CLRNTRAMPERR    0x02
        field   CLROSRAMPERR    0x01
 }
@@ -2124,6 +2174,7 @@ register SIMODE3 {
        address                 0x053
        access_mode     RW
        modes           M_CFG
+       count           4
        field   ENNTRAMPERR     0x02
        field   ENOSRAMPERR     0x01
 }
@@ -2135,6 +2186,7 @@ register LQOSTAT0 {
        address                 0x054
        access_mode     RO
        modes           M_DFF0, M_DFF1, M_SCSI
+       count           2
        field   LQOTARGSCBPERR  0x10
        field   LQOSTOPT2       0x08
        field   LQOATNLQ        0x04
@@ -2149,6 +2201,7 @@ register CLRLQOINT0 {
        address                 0x054
        access_mode     WO
        modes           M_DFF0, M_DFF1, M_SCSI
+       count           3
        field   CLRLQOTARGSCBPERR       0x10
        field   CLRLQOSTOPT2            0x08
        field   CLRLQOATNLQ             0x04
@@ -2163,6 +2216,7 @@ register LQOMODE0 {
        address                 0x054
        access_mode     RW
        modes           M_CFG
+       count           4
        field   ENLQOTARGSCBPERR        0x10
        field   ENLQOSTOPT2             0x08
        field   ENLQOATNLQ              0x04
@@ -2191,6 +2245,7 @@ register CLRLQOINT1 {
        address                 0x055
        access_mode     WO
        modes           M_DFF0, M_DFF1, M_SCSI
+       count           7
        field   CLRLQOINITSCBPERR       0x10
        field   CLRLQOSTOPI2            0x08
        field   CLRLQOBADQAS            0x04
@@ -2205,6 +2260,7 @@ register LQOMODE1 {
        address                 0x055
        access_mode     RW
        modes           M_CFG
+       count           4
        field   ENLQOINITSCBPERR        0x10
        field   ENLQOSTOPI2             0x08
        field   ENLQOBADQAS             0x04
@@ -2232,6 +2288,7 @@ register OS_SPACE_CNT {
        address                 0x056
        access_mode     RO
        modes           M_CFG
+       count           2
 }
 
 /*
@@ -2286,13 +2343,19 @@ register NEXTSCB {
        modes           M_SCSI
 }
 
-/* Rev B only. */
+/*
+ * LQO SCSI Control
+ * (Rev B only.)
+ */
 register LQOSCSCTL {
        address                 0x05A
        access_mode     RW
        size            1
        modes           M_CFG
+       count           1
        field           LQOH2A_VERSION  0x80
+       field           LQOBUSETDLY     0x40
+       field           LQONOHOLDLACK   0x02
        field           LQONOCHKOVER    0x01
 }
 
@@ -2459,6 +2522,7 @@ register NEGPERIOD {
        address                 0x061
        access_mode     RW
        modes           M_SCSI
+       count           1
 }
 
 /*
@@ -2478,6 +2542,7 @@ register NEGOFFSET {
        address                 0x062
        access_mode     RW
        modes           M_SCSI
+       count           1
 }
 
 /*
@@ -2487,6 +2552,7 @@ register NEGPPROPTS {
        address                 0x063
        access_mode     RW
        modes           M_SCSI
+       count           1
        field   PPROPT_PACE     0x08
        field   PPROPT_QAS      0x04
        field   PPROPT_DT       0x02
@@ -2516,12 +2582,19 @@ register ANNEXCOL {
        address                 0x065
        access_mode     RW
        modes           M_SCSI
+       count           7
 }
 
+/*
+ * SCSI Check
+ * (Rev. B only)
+ */
 register SCSCHKN {
        address                 0x066
        access_mode     RW
        modes           M_CFG
+       count           1
+       field   BIDICHKDIS      0x80
        field   STSELSKIDDIS    0x40
        field   CURRFIFODEF     0x20
        field   WIDERESEN       0x10
@@ -2561,6 +2634,7 @@ register ANNEXDAT {
        address                 0x066
        access_mode     RW
        modes           M_SCSI
+       count           3
 }
 
 /*
@@ -2596,6 +2670,7 @@ register TOWNID {
        address                 0x069
        access_mode     RW
        modes           M_SCSI
+       count           2
 }
 
 /*
@@ -2737,6 +2812,7 @@ register SCBAUTOPTR {
        address                 0x0AB
        access_mode     RW
        modes           M_CFG
+       count           1
        field   AUSCBPTR_EN     0x80
        field   SCBPTR_ADDR     0x38
        field   SCBPTR_OFF      0x07
@@ -2881,6 +2957,7 @@ register BRDDAT {
        address                 0x0B8
        access_mode     RW
        modes           M_SCSI
+       count           2
 }
 
 /*
@@ -2890,6 +2967,7 @@ register BRDCTL {
        address                 0x0B9
        access_mode     RW
        modes           M_SCSI
+       count           7
        field   FLXARBACK       0x80
        field   FLXARBREQ       0x40
        field   BRDADDR         0x38
@@ -2905,6 +2983,7 @@ register SEEADR {
        address                 0x0BA
        access_mode     RW
        modes           M_SCSI
+       count           4
 }
 
 /*
@@ -2915,6 +2994,7 @@ register SEEDAT {
        access_mode     RW
        size            2
        modes           M_SCSI
+       count           4
 }
 
 /*
@@ -2924,6 +3004,7 @@ register SEESTAT {
        address                 0x0BE
        access_mode     RO
        modes           M_SCSI
+       count           1
        field   INIT_DONE       0x80
        field   SEEOPCODE       0x70
        field   LDALTID_L       0x08
@@ -2939,6 +3020,7 @@ register SEECTL {
        address                 0x0BE
        access_mode     RW
        modes           M_SCSI
+       count           4
        field   SEEOPCODE       0x70 {
                SEEOP_ERASE     0x70,
                SEEOP_READ      0x60,
@@ -3000,6 +3082,7 @@ register DSPDATACTL {
        address                 0x0C1
        access_mode     RW
        modes           M_CFG
+       count           3
        field   BYPASSENAB      0x80
        field   DESQDIS         0x10
        field   RCVROFFSTDIS    0x04
@@ -3058,6 +3141,7 @@ register DSPSELECT {
        address                 0x0C4
        access_mode     RW
        modes           M_CFG
+       count           1
        field   AUTOINCEN       0x80
        field   DSPSEL          0x1F
 }
@@ -3071,6 +3155,7 @@ register WRTBIASCTL {
        address                 0x0C5
        access_mode     WO
        modes           M_CFG
+       count           3
        field   AUTOXBCDIS      0x80
        field   XMITMANVAL      0x3F
 }
@@ -3196,7 +3281,8 @@ register OVLYADDR {
  */
 register SEQCTL0 {
        address                 0x0D6
-       access_mode RW
+       access_mode     RW
+       count           11
        field   PERRORDIS       0x80
        field   PAUSEDIS        0x40
        field   FAILDIS         0x20
@@ -3226,7 +3312,8 @@ register SEQCTL1 {
  */
 register FLAGS {
        address                 0x0D8
-       access_mode RO
+       access_mode     RO
+       count           23
        field   ZERO            0x02
        field   CARRY           0x01
 }
@@ -3255,7 +3342,8 @@ register SEQINTCTL {
  */
 register SEQRAM {
        address                 0x0DA
-       access_mode RW
+       access_mode     RW
+       count           2
 }
 
 /*
@@ -3266,6 +3354,7 @@ register PRGMCNT {
        address                 0x0DE
        access_mode     RW
        size            2
+       count           5
 }
 
 /*
@@ -3273,7 +3362,7 @@ register PRGMCNT {
  */
 register ACCUM {
        address                 0x0E0
-       access_mode RW
+       access_mode     RW
        accumulator
 }
 
@@ -3401,6 +3490,7 @@ register INTVEC1_ADDR {
        access_mode     RW
        size            2
        modes           M_CFG
+       count           1
 }
 
 /*
@@ -3412,6 +3502,7 @@ register CURADDR {
        access_mode     RW
        size            2
        modes           M_SCSI
+       count           2
 }
 
 /*
@@ -3423,6 +3514,7 @@ register INTVEC2_ADDR {
        access_mode     RW
        size            2
        modes           M_CFG
+       count           1
 }
 
 /*
@@ -3579,6 +3671,7 @@ scratch_ram {
        /* Parameters for DMA Logic */
        DMAPARAMS {
                size            1
+               count           8
                field   PRELOADEN       0x80
                field   WIDEODD         0x40
                field   SCSIEN          0x20
@@ -3648,9 +3741,11 @@ scratch_ram {
         */
        KERNEL_TQINPOS {
                size            1
+               count           1
        }
-       TQINPOS {                
+       TQINPOS {
                size            1
+               count           8
        }
        /*
         * Base address of our shared data with the kernel driver in host
@@ -3681,6 +3776,7 @@ scratch_ram {
        }
        ARG_2 {
                size            1
+               count           1
                alias   RETURN_2
        }
 
@@ -3698,6 +3794,7 @@ scratch_ram {
         */
        SCSISEQ_TEMPLATE {
                size            1
+               count           7
                field   MANUALCTL       0x40
                field   ENSELI          0x20
                field   ENRSELI         0x10
@@ -3711,6 +3808,7 @@ scratch_ram {
         */
        INITIATOR_TAG {
                size            1
+               count           1
        }
 
        SEQ_FLAGS2 {
@@ -3777,6 +3875,7 @@ scratch_ram {
         */
        CMDSIZE_TABLE {
                size            8
+               count           8
        }
        /*
         * When an SCB with the MK_MESSAGE flag is
@@ -3803,8 +3902,8 @@ scratch_ram {
 /************************* Hardware SCB Definition ****************************/
 scb {
        address                 0x180
-       size    64
-       modes   0, 1, 2, 3
+       size            64
+       modes           0, 1, 2, 3
        SCB_RESIDUAL_DATACNT {
                size    4
                alias   SCB_CDB_STORE
index ade0fb8fbdb23fa9264174e9b6b2c08a972e42f2..55508b0fcec4020df71de8236e854f712a952393 100644 (file)
@@ -52,7 +52,7 @@
 
 
 /***************************** Lookup Tables **********************************/
-static char *ahd_chip_names[] =
+static const char *const ahd_chip_names[] =
 {
        "NONE",
        "aic7901",
@@ -66,10 +66,10 @@ static const u_int num_chip_names = ARRAY_SIZE(ahd_chip_names);
  */
 struct ahd_hard_error_entry {
         uint8_t errno;
-       char *errmesg;
+       const char *errmesg;
 };
 
-static struct ahd_hard_error_entry ahd_hard_errors[] = {
+static const struct ahd_hard_error_entry ahd_hard_errors[] = {
        { DSCTMOUT,     "Discard Timer has timed out" },
        { ILLOPCODE,    "Illegal Opcode in sequencer program" },
        { SQPARERR,     "Sequencer Parity Error" },
@@ -79,7 +79,7 @@ static struct ahd_hard_error_entry ahd_hard_errors[] = {
 };
 static const u_int num_errors = ARRAY_SIZE(ahd_hard_errors);
 
-static struct ahd_phase_table_entry ahd_phase_table[] =
+static const struct ahd_phase_table_entry ahd_phase_table[] =
 {
        { P_DATAOUT,    MSG_NOOP,               "in Data-out phase"     },
        { P_DATAIN,     MSG_INITIATOR_DET_ERR,  "in Data-in phase"      },
@@ -213,7 +213,7 @@ static void         ahd_dumpseq(struct ahd_softc *ahd);
 #endif
 static void            ahd_loadseq(struct ahd_softc *ahd);
 static int             ahd_check_patch(struct ahd_softc *ahd,
-                                       struct patch **start_patch,
+                                       const struct patch **start_patch,
                                        u_int start_instr, u_int *skip_addr);
 static u_int           ahd_resolve_seqaddr(struct ahd_softc *ahd,
                                            u_int address);
@@ -254,7 +254,7 @@ static void         ahd_freeze_devq(struct ahd_softc *ahd,
                                        struct scb *scb);
 static void            ahd_handle_scb_status(struct ahd_softc *ahd,
                                              struct scb *scb);
-static struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase);
+static const struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase);
 static void            ahd_shutdown(void *arg);
 static void            ahd_update_coalescing_values(struct ahd_softc *ahd,
                                                     u_int timer,
@@ -266,8 +266,774 @@ static int                ahd_match_scb(struct ahd_softc *ahd, struct scb *scb,
                                      int target, char channel, int lun,
                                      u_int tag, role_t role);
 
-/******************************** Private Inlines *****************************/
+static void            ahd_reset_cmds_pending(struct ahd_softc *ahd);
+
+/*************************** Interrupt Services *******************************/
+static void            ahd_run_qoutfifo(struct ahd_softc *ahd);
+#ifdef AHD_TARGET_MODE
+static void            ahd_run_tqinfifo(struct ahd_softc *ahd, int paused);
+#endif
+static void            ahd_handle_hwerrint(struct ahd_softc *ahd);
+static void            ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat);
+static void            ahd_handle_scsiint(struct ahd_softc *ahd,
+                                          u_int intstat);
+
+/************************ Sequencer Execution Control *************************/
+void
+ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
+{
+       if (ahd->src_mode == src && ahd->dst_mode == dst)
+               return;
+#ifdef AHD_DEBUG
+       if (ahd->src_mode == AHD_MODE_UNKNOWN
+        || ahd->dst_mode == AHD_MODE_UNKNOWN)
+               panic("Setting mode prior to saving it.\n");
+       if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
+               printf("%s: Setting mode 0x%x\n", ahd_name(ahd),
+                      ahd_build_mode_state(ahd, src, dst));
+#endif
+       ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst));
+       ahd->src_mode = src;
+       ahd->dst_mode = dst;
+}
+
+static void
+ahd_update_modes(struct ahd_softc *ahd)
+{
+       ahd_mode_state mode_ptr;
+       ahd_mode src;
+       ahd_mode dst;
+
+       mode_ptr = ahd_inb(ahd, MODE_PTR);
+#ifdef AHD_DEBUG
+       if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
+               printf("Reading mode 0x%x\n", mode_ptr);
+#endif
+       ahd_extract_mode_state(ahd, mode_ptr, &src, &dst);
+       ahd_known_modes(ahd, src, dst);
+}
+
+static void
+ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode,
+                ahd_mode dstmode, const char *file, int line)
+{
+#ifdef AHD_DEBUG
+       if ((srcmode & AHD_MK_MSK(ahd->src_mode)) == 0
+        || (dstmode & AHD_MK_MSK(ahd->dst_mode)) == 0) {
+               panic("%s:%s:%d: Mode assertion failed.\n",
+                      ahd_name(ahd), file, line);
+       }
+#endif
+}
+
+#define AHD_ASSERT_MODES(ahd, source, dest) \
+       ahd_assert_modes(ahd, source, dest, __FILE__, __LINE__);
+
+ahd_mode_state
+ahd_save_modes(struct ahd_softc *ahd)
+{
+       if (ahd->src_mode == AHD_MODE_UNKNOWN
+        || ahd->dst_mode == AHD_MODE_UNKNOWN)
+               ahd_update_modes(ahd);
+
+       return (ahd_build_mode_state(ahd, ahd->src_mode, ahd->dst_mode));
+}
+
+void
+ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state)
+{
+       ahd_mode src;
+       ahd_mode dst;
+
+       ahd_extract_mode_state(ahd, state, &src, &dst);
+       ahd_set_modes(ahd, src, dst);
+}
+
+/*
+ * Determine whether the sequencer has halted code execution.
+ * Returns non-zero status if the sequencer is stopped.
+ */
+int
+ahd_is_paused(struct ahd_softc *ahd)
+{
+       return ((ahd_inb(ahd, HCNTRL) & PAUSE) != 0);
+}
+
+/*
+ * Request that the sequencer stop and wait, indefinitely, for it
+ * to stop.  The sequencer will only acknowledge that it is paused
+ * once it has reached an instruction boundary and PAUSEDIS is
+ * cleared in the SEQCTL register.  The sequencer may use PAUSEDIS
+ * for critical sections.
+ */
+void
+ahd_pause(struct ahd_softc *ahd)
+{
+       ahd_outb(ahd, HCNTRL, ahd->pause);
+
+       /*
+        * Since the sequencer can disable pausing in a critical section, we
+        * must loop until it actually stops.
+        */
+       while (ahd_is_paused(ahd) == 0)
+               ;
+}
+
+/*
+ * Allow the sequencer to continue program execution.
+ * We check here to ensure that no additional interrupt
+ * sources that would cause the sequencer to halt have been
+ * asserted.  If, for example, a SCSI bus reset is detected
+ * while we are fielding a different, pausing, interrupt type,
+ * we don't want to release the sequencer before going back
+ * into our interrupt handler and dealing with this new
+ * condition.
+ */
+void
+ahd_unpause(struct ahd_softc *ahd)
+{
+       /*
+        * Automatically restore our modes to those saved
+        * prior to the first change of the mode.
+        */
+       if (ahd->saved_src_mode != AHD_MODE_UNKNOWN
+        && ahd->saved_dst_mode != AHD_MODE_UNKNOWN) {
+               if ((ahd->flags & AHD_UPDATE_PEND_CMDS) != 0)
+                       ahd_reset_cmds_pending(ahd);
+               ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
+       }
+
+       if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0)
+               ahd_outb(ahd, HCNTRL, ahd->unpause);
+
+       ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN);
+}
+
+/*********************** Scatter Gather List Handling *************************/
+void *
+ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
+            void *sgptr, dma_addr_t addr, bus_size_t len, int last)
+{
+       scb->sg_count++;
+       if (sizeof(dma_addr_t) > 4
+        && (ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
+               struct ahd_dma64_seg *sg;
+
+               sg = (struct ahd_dma64_seg *)sgptr;
+               sg->addr = ahd_htole64(addr);
+               sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0));
+               return (sg + 1);
+       } else {
+               struct ahd_dma_seg *sg;
 
+               sg = (struct ahd_dma_seg *)sgptr;
+               sg->addr = ahd_htole32(addr & 0xFFFFFFFF);
+               sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000)
+                                   | (last ? AHD_DMA_LAST_SEG : 0));
+               return (sg + 1);
+       }
+}
+
+static void
+ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb)
+{
+       /* XXX Handle target mode SCBs. */
+       scb->crc_retry_count = 0;
+       if ((scb->flags & SCB_PACKETIZED) != 0) {
+               /* XXX what about ACA??  It is type 4, but TAG_TYPE == 0x3. */
+               scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE;
+       } else {
+               if (ahd_get_transfer_length(scb) & 0x01)
+                       scb->hscb->task_attribute = SCB_XFERLEN_ODD;
+               else
+                       scb->hscb->task_attribute = 0;
+       }
+
+       if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR
+        || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0)
+               scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr =
+                   ahd_htole32(scb->sense_busaddr);
+}
+
+static void
+ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb)
+{
+       /*
+        * Copy the first SG into the "current" data ponter area.
+        */
+       if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
+               struct ahd_dma64_seg *sg;
+
+               sg = (struct ahd_dma64_seg *)scb->sg_list;
+               scb->hscb->dataptr = sg->addr;
+               scb->hscb->datacnt = sg->len;
+       } else {
+               struct ahd_dma_seg *sg;
+               uint32_t *dataptr_words;
+
+               sg = (struct ahd_dma_seg *)scb->sg_list;
+               dataptr_words = (uint32_t*)&scb->hscb->dataptr;
+               dataptr_words[0] = sg->addr;
+               dataptr_words[1] = 0;
+               if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) {
+                       uint64_t high_addr;
+
+                       high_addr = ahd_le32toh(sg->len) & 0x7F000000;
+                       scb->hscb->dataptr |= ahd_htole64(high_addr << 8);
+               }
+               scb->hscb->datacnt = sg->len;
+       }
+       /*
+        * Note where to find the SG entries in bus space.
+        * We also set the full residual flag which the
+        * sequencer will clear as soon as a data transfer
+        * occurs.
+        */
+       scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID);
+}
+
+static void
+ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb)
+{
+       scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL);
+       scb->hscb->dataptr = 0;
+       scb->hscb->datacnt = 0;
+}
+
+/************************** Memory mapping routines ***************************/
+static void *
+ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr)
+{
+       dma_addr_t sg_offset;
+
+       /* sg_list_phys points to entry 1, not 0 */
+       sg_offset = sg_busaddr - (scb->sg_list_busaddr - ahd_sg_size(ahd));
+       return ((uint8_t *)scb->sg_list + sg_offset);
+}
+
+static uint32_t
+ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg)
+{
+       dma_addr_t sg_offset;
+
+       /* sg_list_phys points to entry 1, not 0 */
+       sg_offset = ((uint8_t *)sg - (uint8_t *)scb->sg_list)
+                 - ahd_sg_size(ahd);
+
+       return (scb->sg_list_busaddr + sg_offset);
+}
+
+static void
+ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op)
+{
+       ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat,
+                       scb->hscb_map->dmamap,
+                       /*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr,
+                       /*len*/sizeof(*scb->hscb), op);
+}
+
+void
+ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op)
+{
+       if (scb->sg_count == 0)
+               return;
+
+       ahd_dmamap_sync(ahd, ahd->scb_data.sg_dmat,
+                       scb->sg_map->dmamap,
+                       /*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd),
+                       /*len*/ahd_sg_size(ahd) * scb->sg_count, op);
+}
+
+static void
+ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op)
+{
+       ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat,
+                       scb->sense_map->dmamap,
+                       /*offset*/scb->sense_busaddr,
+                       /*len*/AHD_SENSE_BUFSIZE, op);
+}
+
+#ifdef AHD_TARGET_MODE
+static uint32_t
+ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index)
+{
+       return (((uint8_t *)&ahd->targetcmds[index])
+              - (uint8_t *)ahd->qoutfifo);
+}
+#endif
+
+/*********************** Miscelaneous Support Functions ***********************/
+/*
+ * Return pointers to the transfer negotiation information
+ * for the specified our_id/remote_id pair.
+ */
+struct ahd_initiator_tinfo *
+ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id,
+                   u_int remote_id, struct ahd_tmode_tstate **tstate)
+{
+       /*
+        * Transfer data structures are stored from the perspective
+        * of the target role.  Since the parameters for a connection
+        * in the initiator role to a given target are the same as
+        * when the roles are reversed, we pretend we are the target.
+        */
+       if (channel == 'B')
+               our_id += 8;
+       *tstate = ahd->enabled_targets[our_id];
+       return (&(*tstate)->transinfo[remote_id]);
+}
+
+uint16_t
+ahd_inw(struct ahd_softc *ahd, u_int port)
+{
+       /*
+        * Read high byte first as some registers increment
+        * or have other side effects when the low byte is
+        * read.
+        */
+       uint16_t r = ahd_inb(ahd, port+1) << 8;
+       return r | ahd_inb(ahd, port);
+}
+
+void
+ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)
+{
+       /*
+        * Write low byte first to accomodate registers
+        * such as PRGMCNT where the order maters.
+        */
+       ahd_outb(ahd, port, value & 0xFF);
+       ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
+}
+
+uint32_t
+ahd_inl(struct ahd_softc *ahd, u_int port)
+{
+       return ((ahd_inb(ahd, port))
+             | (ahd_inb(ahd, port+1) << 8)
+             | (ahd_inb(ahd, port+2) << 16)
+             | (ahd_inb(ahd, port+3) << 24));
+}
+
+void
+ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value)
+{
+       ahd_outb(ahd, port, (value) & 0xFF);
+       ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF);
+       ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF);
+       ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF);
+}
+
+uint64_t
+ahd_inq(struct ahd_softc *ahd, u_int port)
+{
+       return ((ahd_inb(ahd, port))
+             | (ahd_inb(ahd, port+1) << 8)
+             | (ahd_inb(ahd, port+2) << 16)
+             | (ahd_inb(ahd, port+3) << 24)
+             | (((uint64_t)ahd_inb(ahd, port+4)) << 32)
+             | (((uint64_t)ahd_inb(ahd, port+5)) << 40)
+             | (((uint64_t)ahd_inb(ahd, port+6)) << 48)
+             | (((uint64_t)ahd_inb(ahd, port+7)) << 56));
+}
+
+void
+ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value)
+{
+       ahd_outb(ahd, port, value & 0xFF);
+       ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
+       ahd_outb(ahd, port+2, (value >> 16) & 0xFF);
+       ahd_outb(ahd, port+3, (value >> 24) & 0xFF);
+       ahd_outb(ahd, port+4, (value >> 32) & 0xFF);
+       ahd_outb(ahd, port+5, (value >> 40) & 0xFF);
+       ahd_outb(ahd, port+6, (value >> 48) & 0xFF);
+       ahd_outb(ahd, port+7, (value >> 56) & 0xFF);
+}
+
+u_int
+ahd_get_scbptr(struct ahd_softc *ahd)
+{
+       AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
+                        ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
+       return (ahd_inb(ahd, SCBPTR) | (ahd_inb(ahd, SCBPTR + 1) << 8));
+}
+
+void
+ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr)
+{
+       AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
+                        ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
+       ahd_outb(ahd, SCBPTR, scbptr & 0xFF);
+       ahd_outb(ahd, SCBPTR+1, (scbptr >> 8) & 0xFF);
+}
+
+#if 0 /* unused */
+static u_int
+ahd_get_hnscb_qoff(struct ahd_softc *ahd)
+{
+       return (ahd_inw_atomic(ahd, HNSCB_QOFF));
+}
+#endif
+
+static void
+ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value)
+{
+       ahd_outw_atomic(ahd, HNSCB_QOFF, value);
+}
+
+#if 0 /* unused */
+static u_int
+ahd_get_hescb_qoff(struct ahd_softc *ahd)
+{
+       return (ahd_inb(ahd, HESCB_QOFF));
+}
+#endif
+
+static void
+ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value)
+{
+       ahd_outb(ahd, HESCB_QOFF, value);
+}
+
+static u_int
+ahd_get_snscb_qoff(struct ahd_softc *ahd)
+{
+       u_int oldvalue;
+
+       AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+       oldvalue = ahd_inw(ahd, SNSCB_QOFF);
+       ahd_outw(ahd, SNSCB_QOFF, oldvalue);
+       return (oldvalue);
+}
+
+static void
+ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value)
+{
+       AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+       ahd_outw(ahd, SNSCB_QOFF, value);
+}
+
+#if 0 /* unused */
+static u_int
+ahd_get_sescb_qoff(struct ahd_softc *ahd)
+{
+       AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+       return (ahd_inb(ahd, SESCB_QOFF));
+}
+#endif
+
+static void
+ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value)
+{
+       AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+       ahd_outb(ahd, SESCB_QOFF, value);
+}
+
+#if 0 /* unused */
+static u_int
+ahd_get_sdscb_qoff(struct ahd_softc *ahd)
+{
+       AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+       return (ahd_inb(ahd, SDSCB_QOFF) | (ahd_inb(ahd, SDSCB_QOFF + 1) << 8));
+}
+#endif
+
+static void
+ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value)
+{
+       AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+       ahd_outb(ahd, SDSCB_QOFF, value & 0xFF);
+       ahd_outb(ahd, SDSCB_QOFF+1, (value >> 8) & 0xFF);
+}
+
+u_int
+ahd_inb_scbram(struct ahd_softc *ahd, u_int offset)
+{
+       u_int value;
+
+       /*
+        * Workaround PCI-X Rev A. hardware bug.
+        * After a host read of SCB memory, the chip
+        * may become confused into thinking prefetch
+        * was required.  This starts the discard timer
+        * running and can cause an unexpected discard
+        * timer interrupt.  The work around is to read
+        * a normal register prior to the exhaustion of
+        * the discard timer.  The mode pointer register
+        * has no side effects and so serves well for
+        * this purpose.
+        *
+        * Razor #528
+        */
+       value = ahd_inb(ahd, offset);
+       if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0)
+               ahd_inb(ahd, MODE_PTR);
+       return (value);
+}
+
+u_int
+ahd_inw_scbram(struct ahd_softc *ahd, u_int offset)
+{
+       return (ahd_inb_scbram(ahd, offset)
+             | (ahd_inb_scbram(ahd, offset+1) << 8));
+}
+
+static uint32_t
+ahd_inl_scbram(struct ahd_softc *ahd, u_int offset)
+{
+       return (ahd_inw_scbram(ahd, offset)
+             | (ahd_inw_scbram(ahd, offset+2) << 16));
+}
+
+static uint64_t
+ahd_inq_scbram(struct ahd_softc *ahd, u_int offset)
+{
+       return (ahd_inl_scbram(ahd, offset)
+             | ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32);
+}
+
+struct scb *
+ahd_lookup_scb(struct ahd_softc *ahd, u_int tag)
+{
+       struct scb* scb;
+
+       if (tag >= AHD_SCB_MAX)
+               return (NULL);
+       scb = ahd->scb_data.scbindex[tag];
+       if (scb != NULL)
+               ahd_sync_scb(ahd, scb,
+                            BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+       return (scb);
+}
+
+static void
+ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
+{
+       struct   hardware_scb *q_hscb;
+       struct   map_node *q_hscb_map;
+       uint32_t saved_hscb_busaddr;
+
+       /*
+        * Our queuing method is a bit tricky.  The card
+        * knows in advance which HSCB (by address) to download,
+        * and we can't disappoint it.  To achieve this, the next
+        * HSCB to download is saved off in ahd->next_queued_hscb.
+        * When we are called to queue "an arbitrary scb",
+        * we copy the contents of the incoming HSCB to the one
+        * the sequencer knows about, swap HSCB pointers and
+        * finally assign the SCB to the tag indexed location
+        * in the scb_array.  This makes sure that we can still
+        * locate the correct SCB by SCB_TAG.
+        */
+       q_hscb = ahd->next_queued_hscb;
+       q_hscb_map = ahd->next_queued_hscb_map;
+       saved_hscb_busaddr = q_hscb->hscb_busaddr;
+       memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
+       q_hscb->hscb_busaddr = saved_hscb_busaddr;
+       q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
+
+       /* Now swap HSCB pointers. */
+       ahd->next_queued_hscb = scb->hscb;
+       ahd->next_queued_hscb_map = scb->hscb_map;
+       scb->hscb = q_hscb;
+       scb->hscb_map = q_hscb_map;
+
+       /* Now define the mapping from tag to SCB in the scbindex */
+       ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
+}
+
+/*
+ * Tell the sequencer about a new transaction to execute.
+ */
+void
+ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb)
+{
+       ahd_swap_with_next_hscb(ahd, scb);
+
+       if (SCBID_IS_NULL(SCB_GET_TAG(scb)))
+               panic("Attempt to queue invalid SCB tag %x\n",
+                     SCB_GET_TAG(scb));
+
+       /*
+        * Keep a history of SCBs we've downloaded in the qinfifo.
+        */
+       ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb);
+       ahd->qinfifonext++;
+
+       if (scb->sg_count != 0)
+               ahd_setup_data_scb(ahd, scb);
+       else
+               ahd_setup_noxfer_scb(ahd, scb);
+       ahd_setup_scb_common(ahd, scb);
+
+       /*
+        * Make sure our data is consistent from the
+        * perspective of the adapter.
+        */
+       ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+
+#ifdef AHD_DEBUG
+       if ((ahd_debug & AHD_SHOW_QUEUE) != 0) {
+               uint64_t host_dataptr;
+
+               host_dataptr = ahd_le64toh(scb->hscb->dataptr);
+               printf("%s: Queueing SCB %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
+                      ahd_name(ahd),
+                      SCB_GET_TAG(scb), scb->hscb->scsiid,
+                      ahd_le32toh(scb->hscb->hscb_busaddr),
+                      (u_int)((host_dataptr >> 32) & 0xFFFFFFFF),
+                      (u_int)(host_dataptr & 0xFFFFFFFF),
+                      ahd_le32toh(scb->hscb->datacnt));
+       }
+#endif
+       /* Tell the adapter about the newly queued SCB */
+       ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
+}
+
+/************************** Interrupt Processing ******************************/
+static void
+ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
+{
+       ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
+                       /*offset*/0,
+                       /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op);
+}
+
+static void
+ahd_sync_tqinfifo(struct ahd_softc *ahd, int op)
+{
+#ifdef AHD_TARGET_MODE
+       if ((ahd->flags & AHD_TARGETROLE) != 0) {
+               ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
+                               ahd->shared_data_map.dmamap,
+                               ahd_targetcmd_offset(ahd, 0),
+                               sizeof(struct target_cmd) * AHD_TMODE_CMDS,
+                               op);
+       }
+#endif
+}
+
+/*
+ * See if the firmware has posted any completed commands
+ * into our in-core command complete fifos.
+ */
+#define AHD_RUN_QOUTFIFO 0x1
+#define AHD_RUN_TQINFIFO 0x2
+static u_int
+ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
+{
+       u_int retval;
+
+       retval = 0;
+       ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
+                       /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),
+                       /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD);
+       if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag
+         == ahd->qoutfifonext_valid_tag)
+               retval |= AHD_RUN_QOUTFIFO;
+#ifdef AHD_TARGET_MODE
+       if ((ahd->flags & AHD_TARGETROLE) != 0
+        && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {
+               ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
+                               ahd->shared_data_map.dmamap,
+                               ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),
+                               /*len*/sizeof(struct target_cmd),
+                               BUS_DMASYNC_POSTREAD);
+               if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0)
+                       retval |= AHD_RUN_TQINFIFO;
+       }
+#endif
+       return (retval);
+}
+
+/*
+ * Catch an interrupt from the adapter
+ */
+int
+ahd_intr(struct ahd_softc *ahd)
+{
+       u_int   intstat;
+
+       if ((ahd->pause & INTEN) == 0) {
+               /*
+                * Our interrupt is not enabled on the chip
+                * and may be disabled for re-entrancy reasons,
+                * so just return.  This is likely just a shared
+                * interrupt.
+                */
+               return (0);
+       }
+
+       /*
+        * Instead of directly reading the interrupt status register,
+        * infer the cause of the interrupt by checking our in-core
+        * completion queues.  This avoids a costly PCI bus read in
+        * most cases.
+        */
+       if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0
+        && (ahd_check_cmdcmpltqueues(ahd) != 0))
+               intstat = CMDCMPLT;
+       else
+               intstat = ahd_inb(ahd, INTSTAT);
+
+       if ((intstat & INT_PEND) == 0)
+               return (0);
+
+       if (intstat & CMDCMPLT) {
+               ahd_outb(ahd, CLRINT, CLRCMDINT);
+
+               /*
+                * Ensure that the chip sees that we've cleared
+                * this interrupt before we walk the output fifo.
+                * Otherwise, we may, due to posted bus writes,
+                * clear the interrupt after we finish the scan,
+                * and after the sequencer has added new entries
+                * and asserted the interrupt again.
+                */
+               if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
+                       if (ahd_is_paused(ahd)) {
+                               /*
+                                * Potentially lost SEQINT.
+                                * If SEQINTCODE is non-zero,
+                                * simulate the SEQINT.
+                                */
+                               if (ahd_inb(ahd, SEQINTCODE) != NO_SEQINT)
+                                       intstat |= SEQINT;
+                       }
+               } else {
+                       ahd_flush_device_writes(ahd);
+               }
+               ahd_run_qoutfifo(ahd);
+               ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]++;
+               ahd->cmdcmplt_total++;
+#ifdef AHD_TARGET_MODE
+               if ((ahd->flags & AHD_TARGETROLE) != 0)
+                       ahd_run_tqinfifo(ahd, /*paused*/FALSE);
+#endif
+       }
+
+       /*
+        * Handle statuses that may invalidate our cached
+        * copy of INTSTAT separately.
+        */
+       if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) {
+               /* Hot eject.  Do nothing */
+       } else if (intstat & HWERRINT) {
+               ahd_handle_hwerrint(ahd);
+       } else if ((intstat & (PCIINT|SPLTINT)) != 0) {
+               ahd->bus_intr(ahd);
+       } else {
+
+               if ((intstat & SEQINT) != 0)
+                       ahd_handle_seqint(ahd, intstat);
+
+               if ((intstat & SCSIINT) != 0)
+                       ahd_handle_scsiint(ahd, intstat);
+       }
+       return (1);
+}
+
+/******************************** Private Inlines *****************************/
 static __inline void
 ahd_assert_atn(struct ahd_softc *ahd)
 {
@@ -280,7 +1046,7 @@ ahd_assert_atn(struct ahd_softc *ahd)
  * are currently in a packetized transfer.  We could
  * just as easily be sending or receiving a message.
  */
-static __inline int
+static int
 ahd_currently_packetized(struct ahd_softc *ahd)
 {
        ahd_mode_state   saved_modes;
@@ -896,7 +1662,7 @@ clrchn:
  * a copy of the first byte (little endian) of the sgptr
  * hscb field.
  */
-void
+static void
 ahd_run_qoutfifo(struct ahd_softc *ahd)
 {
        struct ahd_completion *completion;
@@ -935,7 +1701,7 @@ ahd_run_qoutfifo(struct ahd_softc *ahd)
 }
 
 /************************* Interrupt Handling *********************************/
-void
+static void
 ahd_handle_hwerrint(struct ahd_softc *ahd)
 {
        /*
@@ -1009,7 +1775,7 @@ ahd_dump_sglist(struct scb *scb)
 }
 #endif  /*  AHD_DEBUG  */
 
-void
+static void
 ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
 {
        u_int seqintcode;
@@ -1621,7 +2387,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
        ahd_unpause(ahd);
 }
 
-void
+static void
 ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
 {
        struct scb      *scb;
@@ -3571,11 +4337,11 @@ ahd_print_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
               devinfo->target, devinfo->lun);
 }
 
-static struct ahd_phase_table_entry*
+static const struct ahd_phase_table_entry*
 ahd_lookup_phase_entry(int phase)
 {
-       struct ahd_phase_table_entry *entry;
-       struct ahd_phase_table_entry *last_entry;
+       const struct ahd_phase_table_entry *entry;
+       const struct ahd_phase_table_entry *last_entry;
 
        /*
         * num_phases doesn't include the default entry which
@@ -3941,7 +4707,7 @@ ahd_clear_msg_state(struct ahd_softc *ahd)
  */
 static void
 ahd_handle_message_phase(struct ahd_softc *ahd)
-{ 
+{
        struct  ahd_devinfo devinfo;
        u_int   bus_phase;
        int     end_session;
@@ -5983,8 +6749,7 @@ found:
  */
 void
 ahd_free_scb(struct ahd_softc *ahd, struct scb *scb)
-{       
-
+{
        /* Clean up for the next user */
        scb->flags = SCB_FLAG_NONE;
        scb->hscb->control = 0;
@@ -6272,6 +7037,24 @@ static const char *termstat_strings[] = {
        "Not Configured"
 };
 
+/***************************** Timer Facilities *******************************/
+#define ahd_timer_init init_timer
+#define ahd_timer_stop del_timer_sync
+typedef void ahd_linux_callback_t (u_long);
+
+static void
+ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
+{
+       struct ahd_softc *ahd;
+
+       ahd = (struct ahd_softc *)arg;
+       del_timer(timer);
+       timer->data = (u_long)arg;
+       timer->expires = jiffies + (usec * HZ)/1000000;
+       timer->function = (ahd_linux_callback_t*)func;
+       add_timer(timer);
+}
+
 /*
  * Start the board, ready for normal operation
  */
@@ -7370,7 +8153,7 @@ ahd_qinfifo_count(struct ahd_softc *ahd)
                      + ARRAY_SIZE(ahd->qinfifo) - wrap_qinpos);
 }
 
-void
+static void
 ahd_reset_cmds_pending(struct ahd_softc *ahd)
 {
        struct          scb *scb;
@@ -8571,7 +9354,7 @@ ahd_loadseq(struct ahd_softc *ahd)
        struct  cs cs_table[num_critical_sections];
        u_int   begin_set[num_critical_sections];
        u_int   end_set[num_critical_sections];
-       struct  patch *cur_patch;
+       const struct patch *cur_patch;
        u_int   cs_count;
        u_int   cur_cs;
        u_int   i;
@@ -8726,11 +9509,11 @@ ahd_loadseq(struct ahd_softc *ahd)
 }
 
 static int
-ahd_check_patch(struct ahd_softc *ahd, struct patch **start_patch,
+ahd_check_patch(struct ahd_softc *ahd, const struct patch **start_patch,
                u_int start_instr, u_int *skip_addr)
 {
-       struct  patch *cur_patch;
-       struct  patch *last_patch;
+       const struct patch *cur_patch;
+       const struct patch *last_patch;
        u_int   num_patches;
 
        num_patches = ARRAY_SIZE(patches);
@@ -8764,7 +9547,7 @@ ahd_check_patch(struct ahd_softc *ahd, struct patch **start_patch,
 static u_int
 ahd_resolve_seqaddr(struct ahd_softc *ahd, u_int address)
 {
-       struct patch *cur_patch;
+       const struct patch *cur_patch;
        int address_offset;
        u_int skip_addr;
        u_int i;
@@ -8895,7 +9678,7 @@ sized:
 }
 
 int
-ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries,
+ahd_print_register(const ahd_reg_parse_entry_t *table, u_int num_entries,
                   const char *name, u_int address, u_int value,
                   u_int *cur_column, u_int wrap_point)
 {
@@ -9886,7 +10669,7 @@ ahd_update_scsiid(struct ahd_softc *ahd, u_int targid_mask)
 #endif
 }
 
-void
+static void
 ahd_run_tqinfifo(struct ahd_softc *ahd, int paused)
 {
        struct target_cmd *cmd;
index 45e55575a0fad6c997f725d1489e815af31c4fff..5f12cf9d99d071344b6929beeb11c3fb11edbe33 100644 (file)
@@ -63,18 +63,15 @@ static __inline ahd_mode_state ahd_build_mode_state(struct ahd_softc *ahd,
 static __inline void ahd_extract_mode_state(struct ahd_softc *ahd,
                                            ahd_mode_state state,
                                            ahd_mode *src, ahd_mode *dst);
-static __inline void ahd_set_modes(struct ahd_softc *ahd, ahd_mode src,
-                                  ahd_mode dst);
-static __inline void ahd_update_modes(struct ahd_softc *ahd);
-static __inline void ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode,
-                                     ahd_mode dstmode, const char *file,
-                                     int line);
-static __inline ahd_mode_state ahd_save_modes(struct ahd_softc *ahd);
-static __inline void ahd_restore_modes(struct ahd_softc *ahd,
-                                      ahd_mode_state state);
-static __inline int  ahd_is_paused(struct ahd_softc *ahd);
-static __inline void ahd_pause(struct ahd_softc *ahd);
-static __inline void ahd_unpause(struct ahd_softc *ahd);
+
+void ahd_set_modes(struct ahd_softc *ahd, ahd_mode src,
+                  ahd_mode dst);
+ahd_mode_state ahd_save_modes(struct ahd_softc *ahd);
+void ahd_restore_modes(struct ahd_softc *ahd,
+                      ahd_mode_state state);
+int  ahd_is_paused(struct ahd_softc *ahd);
+void ahd_pause(struct ahd_softc *ahd);
+void ahd_unpause(struct ahd_softc *ahd);
 
 static __inline void
 ahd_known_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
@@ -99,256 +96,16 @@ ahd_extract_mode_state(struct ahd_softc *ahd, ahd_mode_state state,
        *dst = (state & DST_MODE) >> DST_MODE_SHIFT;
 }
 
-static __inline void
-ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
-{
-       if (ahd->src_mode == src && ahd->dst_mode == dst)
-               return;
-#ifdef AHD_DEBUG
-       if (ahd->src_mode == AHD_MODE_UNKNOWN
-        || ahd->dst_mode == AHD_MODE_UNKNOWN)
-               panic("Setting mode prior to saving it.\n");
-       if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
-               printf("%s: Setting mode 0x%x\n", ahd_name(ahd),
-                      ahd_build_mode_state(ahd, src, dst));
-#endif
-       ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst));
-       ahd->src_mode = src;
-       ahd->dst_mode = dst;
-}
-
-static __inline void
-ahd_update_modes(struct ahd_softc *ahd)
-{
-       ahd_mode_state mode_ptr;
-       ahd_mode src;
-       ahd_mode dst;
-
-       mode_ptr = ahd_inb(ahd, MODE_PTR);
-#ifdef AHD_DEBUG
-       if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
-               printf("Reading mode 0x%x\n", mode_ptr);
-#endif
-       ahd_extract_mode_state(ahd, mode_ptr, &src, &dst);
-       ahd_known_modes(ahd, src, dst);
-}
-
-static __inline void
-ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode,
-                ahd_mode dstmode, const char *file, int line)
-{
-#ifdef AHD_DEBUG
-       if ((srcmode & AHD_MK_MSK(ahd->src_mode)) == 0
-        || (dstmode & AHD_MK_MSK(ahd->dst_mode)) == 0) {
-               panic("%s:%s:%d: Mode assertion failed.\n",
-                      ahd_name(ahd), file, line);
-       }
-#endif
-}
-
-static __inline ahd_mode_state
-ahd_save_modes(struct ahd_softc *ahd)
-{
-       if (ahd->src_mode == AHD_MODE_UNKNOWN
-        || ahd->dst_mode == AHD_MODE_UNKNOWN)
-               ahd_update_modes(ahd);
-
-       return (ahd_build_mode_state(ahd, ahd->src_mode, ahd->dst_mode));
-}
-
-static __inline void
-ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state)
-{
-       ahd_mode src;
-       ahd_mode dst;
-
-       ahd_extract_mode_state(ahd, state, &src, &dst);
-       ahd_set_modes(ahd, src, dst);
-}
-
-#define AHD_ASSERT_MODES(ahd, source, dest) \
-       ahd_assert_modes(ahd, source, dest, __FILE__, __LINE__);
-
-/*
- * Determine whether the sequencer has halted code execution.
- * Returns non-zero status if the sequencer is stopped.
- */
-static __inline int
-ahd_is_paused(struct ahd_softc *ahd)
-{
-       return ((ahd_inb(ahd, HCNTRL) & PAUSE) != 0);
-}
-
-/*
- * Request that the sequencer stop and wait, indefinitely, for it
- * to stop.  The sequencer will only acknowledge that it is paused
- * once it has reached an instruction boundary and PAUSEDIS is
- * cleared in the SEQCTL register.  The sequencer may use PAUSEDIS
- * for critical sections.
- */
-static __inline void
-ahd_pause(struct ahd_softc *ahd)
-{
-       ahd_outb(ahd, HCNTRL, ahd->pause);
-
-       /*
-        * Since the sequencer can disable pausing in a critical section, we
-        * must loop until it actually stops.
-        */
-       while (ahd_is_paused(ahd) == 0)
-               ;
-}
-
-/*
- * Allow the sequencer to continue program execution.
- * We check here to ensure that no additional interrupt
- * sources that would cause the sequencer to halt have been
- * asserted.  If, for example, a SCSI bus reset is detected
- * while we are fielding a different, pausing, interrupt type,
- * we don't want to release the sequencer before going back
- * into our interrupt handler and dealing with this new
- * condition.
- */
-static __inline void
-ahd_unpause(struct ahd_softc *ahd)
-{
-       /*
-        * Automatically restore our modes to those saved
-        * prior to the first change of the mode.
-        */
-       if (ahd->saved_src_mode != AHD_MODE_UNKNOWN
-        && ahd->saved_dst_mode != AHD_MODE_UNKNOWN) {
-               if ((ahd->flags & AHD_UPDATE_PEND_CMDS) != 0)
-                       ahd_reset_cmds_pending(ahd);
-               ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
-       }
-
-       if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0)
-               ahd_outb(ahd, HCNTRL, ahd->unpause);
-
-       ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN);
-}
-
 /*********************** Scatter Gather List Handling *************************/
-static __inline void   *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
-                                     void *sgptr, dma_addr_t addr,
-                                     bus_size_t len, int last);
-static __inline void    ahd_setup_scb_common(struct ahd_softc *ahd,
-                                             struct scb *scb);
-static __inline void    ahd_setup_data_scb(struct ahd_softc *ahd,
-                                           struct scb *scb);
-static __inline void    ahd_setup_noxfer_scb(struct ahd_softc *ahd,
-                                             struct scb *scb);
-
-static __inline void *
-ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
-            void *sgptr, dma_addr_t addr, bus_size_t len, int last)
-{
-       scb->sg_count++;
-       if (sizeof(dma_addr_t) > 4
-        && (ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
-               struct ahd_dma64_seg *sg;
-
-               sg = (struct ahd_dma64_seg *)sgptr;
-               sg->addr = ahd_htole64(addr);
-               sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0));
-               return (sg + 1);
-       } else {
-               struct ahd_dma_seg *sg;
-
-               sg = (struct ahd_dma_seg *)sgptr;
-               sg->addr = ahd_htole32(addr & 0xFFFFFFFF);
-               sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000)
-                                   | (last ? AHD_DMA_LAST_SEG : 0));
-               return (sg + 1);
-       }
-}
-
-static __inline void
-ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb)
-{
-       /* XXX Handle target mode SCBs. */
-       scb->crc_retry_count = 0;
-       if ((scb->flags & SCB_PACKETIZED) != 0) {
-               /* XXX what about ACA??  It is type 4, but TAG_TYPE == 0x3. */
-               scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE;
-       } else {
-               if (ahd_get_transfer_length(scb) & 0x01)
-                       scb->hscb->task_attribute = SCB_XFERLEN_ODD;
-               else
-                       scb->hscb->task_attribute = 0;
-       }
-
-       if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR
-        || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0)
-               scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr =
-                   ahd_htole32(scb->sense_busaddr);
-}
-
-static __inline void
-ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb)
-{
-       /*
-        * Copy the first SG into the "current" data ponter area.
-        */
-       if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
-               struct ahd_dma64_seg *sg;
-
-               sg = (struct ahd_dma64_seg *)scb->sg_list;
-               scb->hscb->dataptr = sg->addr;
-               scb->hscb->datacnt = sg->len;
-       } else {
-               struct ahd_dma_seg *sg;
-               uint32_t *dataptr_words;
-
-               sg = (struct ahd_dma_seg *)scb->sg_list;
-               dataptr_words = (uint32_t*)&scb->hscb->dataptr;
-               dataptr_words[0] = sg->addr;
-               dataptr_words[1] = 0;
-               if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) {
-                       uint64_t high_addr;
-
-                       high_addr = ahd_le32toh(sg->len) & 0x7F000000;
-                       scb->hscb->dataptr |= ahd_htole64(high_addr << 8);
-               }
-               scb->hscb->datacnt = sg->len;
-       }
-       /*
-        * Note where to find the SG entries in bus space.
-        * We also set the full residual flag which the 
-        * sequencer will clear as soon as a data transfer
-        * occurs.
-        */
-       scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID);
-}
-
-static __inline void
-ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb)
-{
-       scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL);
-       scb->hscb->dataptr = 0;
-       scb->hscb->datacnt = 0;
-}
+void   *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
+                     void *sgptr, dma_addr_t addr,
+                     bus_size_t len, int last);
 
 /************************** Memory mapping routines ***************************/
 static __inline size_t ahd_sg_size(struct ahd_softc *ahd);
-static __inline void *
-                       ahd_sg_bus_to_virt(struct ahd_softc *ahd,
-                                          struct scb *scb,
-                                          uint32_t sg_busaddr);
-static __inline uint32_t
-                       ahd_sg_virt_to_bus(struct ahd_softc *ahd,
-                                          struct scb *scb,
-                                          void *sg);
-static __inline void   ahd_sync_scb(struct ahd_softc *ahd,
-                                    struct scb *scb, int op);
-static __inline void   ahd_sync_sglist(struct ahd_softc *ahd,
-                                       struct scb *scb, int op);
-static __inline void   ahd_sync_sense(struct ahd_softc *ahd,
-                                      struct scb *scb, int op);
-static __inline uint32_t
-                       ahd_targetcmd_offset(struct ahd_softc *ahd,
-                                            u_int index);
+
+void   ahd_sync_sglist(struct ahd_softc *ahd,
+                       struct scb *scb, int op);
 
 static __inline size_t
 ahd_sg_size(struct ahd_softc *ahd)
@@ -358,104 +115,32 @@ ahd_sg_size(struct ahd_softc *ahd)
        return (sizeof(struct ahd_dma_seg));
 }
 
-static __inline void *
-ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr)
-{
-       dma_addr_t sg_offset;
-
-       /* sg_list_phys points to entry 1, not 0 */
-       sg_offset = sg_busaddr - (scb->sg_list_busaddr - ahd_sg_size(ahd));
-       return ((uint8_t *)scb->sg_list + sg_offset);
-}
-
-static __inline uint32_t
-ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg)
-{
-       dma_addr_t sg_offset;
-
-       /* sg_list_phys points to entry 1, not 0 */
-       sg_offset = ((uint8_t *)sg - (uint8_t *)scb->sg_list)
-                 - ahd_sg_size(ahd);
-
-       return (scb->sg_list_busaddr + sg_offset);
-}
-
-static __inline void
-ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op)
-{
-       ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat,
-                       scb->hscb_map->dmamap,
-                       /*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr,
-                       /*len*/sizeof(*scb->hscb), op);
-}
-
-static __inline void
-ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op)
-{
-       if (scb->sg_count == 0)
-               return;
-
-       ahd_dmamap_sync(ahd, ahd->scb_data.sg_dmat,
-                       scb->sg_map->dmamap,
-                       /*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd),
-                       /*len*/ahd_sg_size(ahd) * scb->sg_count, op);
-}
-
-static __inline void
-ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op)
-{
-       ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat,
-                       scb->sense_map->dmamap,
-                       /*offset*/scb->sense_busaddr,
-                       /*len*/AHD_SENSE_BUFSIZE, op);
-}
-
-static __inline uint32_t
-ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index)
-{
-       return (((uint8_t *)&ahd->targetcmds[index])
-              - (uint8_t *)ahd->qoutfifo);
-}
-
 /*********************** Miscellaneous Support Functions ***********************/
-static __inline struct ahd_initiator_tinfo *
-                       ahd_fetch_transinfo(struct ahd_softc *ahd,
-                                           char channel, u_int our_id,
-                                           u_int remote_id,
-                                           struct ahd_tmode_tstate **tstate);
-static __inline uint16_t
-                       ahd_inw(struct ahd_softc *ahd, u_int port);
-static __inline void   ahd_outw(struct ahd_softc *ahd, u_int port,
-                                u_int value);
-static __inline uint32_t
-                       ahd_inl(struct ahd_softc *ahd, u_int port);
-static __inline void   ahd_outl(struct ahd_softc *ahd, u_int port,
-                                uint32_t value);
-static __inline uint64_t
-                       ahd_inq(struct ahd_softc *ahd, u_int port);
-static __inline void   ahd_outq(struct ahd_softc *ahd, u_int port,
-                                uint64_t value);
-static __inline u_int  ahd_get_scbptr(struct ahd_softc *ahd);
-static __inline void   ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr);
-static __inline u_int  ahd_get_hnscb_qoff(struct ahd_softc *ahd);
-static __inline void   ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value);
-static __inline u_int  ahd_get_hescb_qoff(struct ahd_softc *ahd);
-static __inline void   ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value);
-static __inline u_int  ahd_get_snscb_qoff(struct ahd_softc *ahd);
-static __inline void   ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value);
-static __inline u_int  ahd_get_sescb_qoff(struct ahd_softc *ahd);
-static __inline void   ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value);
-static __inline u_int  ahd_get_sdscb_qoff(struct ahd_softc *ahd);
-static __inline void   ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value);
-static __inline u_int  ahd_inb_scbram(struct ahd_softc *ahd, u_int offset);
-static __inline u_int  ahd_inw_scbram(struct ahd_softc *ahd, u_int offset);
-static __inline uint32_t
-                       ahd_inl_scbram(struct ahd_softc *ahd, u_int offset);
-static __inline uint64_t
-                       ahd_inq_scbram(struct ahd_softc *ahd, u_int offset);
-static __inline void   ahd_swap_with_next_hscb(struct ahd_softc *ahd,
-                                               struct scb *scb);
-static __inline void   ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb);
+struct ahd_initiator_tinfo *
+       ahd_fetch_transinfo(struct ahd_softc *ahd,
+                           char channel, u_int our_id,
+                           u_int remote_id,
+                           struct ahd_tmode_tstate **tstate);
+uint16_t
+       ahd_inw(struct ahd_softc *ahd, u_int port);
+void   ahd_outw(struct ahd_softc *ahd, u_int port,
+                u_int value);
+uint32_t
+       ahd_inl(struct ahd_softc *ahd, u_int port);
+void   ahd_outl(struct ahd_softc *ahd, u_int port,
+                uint32_t value);
+uint64_t
+       ahd_inq(struct ahd_softc *ahd, u_int port);
+void   ahd_outq(struct ahd_softc *ahd, u_int port,
+                uint64_t value);
+u_int  ahd_get_scbptr(struct ahd_softc *ahd);
+void   ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr);
+u_int  ahd_inb_scbram(struct ahd_softc *ahd, u_int offset);
+u_int  ahd_inw_scbram(struct ahd_softc *ahd, u_int offset);
+struct scb *
+       ahd_lookup_scb(struct ahd_softc *ahd, u_int tag);
+void   ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb);
+
 static __inline uint8_t *
                        ahd_get_sense_buf(struct ahd_softc *ahd,
                                          struct scb *scb);
@@ -463,25 +148,7 @@ static __inline uint32_t
                        ahd_get_sense_bufaddr(struct ahd_softc *ahd,
                                              struct scb *scb);
 
-/*
- * Return pointers to the transfer negotiation information
- * for the specified our_id/remote_id pair.
- */
-static __inline struct ahd_initiator_tinfo *
-ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id,
-                   u_int remote_id, struct ahd_tmode_tstate **tstate)
-{
-       /*
-        * Transfer data structures are stored from the perspective
-        * of the target role.  Since the parameters for a connection
-        * in the initiator role to a given target are the same as
-        * when the roles are reversed, we pretend we are the target.
-        */
-       if (channel == 'B')
-               our_id += 8;
-       *tstate = ahd->enabled_targets[our_id];
-       return (&(*tstate)->transinfo[remote_id]);
-}
+#if 0 /* unused */
 
 #define AHD_COPY_COL_IDX(dst, src)                             \
 do {                                                           \
@@ -489,304 +156,7 @@ do {                                                              \
        dst->hscb->lun = src->hscb->lun;                        \
 } while (0)
 
-static __inline uint16_t
-ahd_inw(struct ahd_softc *ahd, u_int port)
-{
-       /*
-        * Read high byte first as some registers increment
-        * or have other side effects when the low byte is
-        * read.
-        */
-       uint16_t r = ahd_inb(ahd, port+1) << 8;
-       return r | ahd_inb(ahd, port);
-}
-
-static __inline void
-ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)
-{
-       /*
-        * Write low byte first to accomodate registers
-        * such as PRGMCNT where the order maters.
-        */
-       ahd_outb(ahd, port, value & 0xFF);
-       ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
-}
-
-static __inline uint32_t
-ahd_inl(struct ahd_softc *ahd, u_int port)
-{
-       return ((ahd_inb(ahd, port))
-             | (ahd_inb(ahd, port+1) << 8)
-             | (ahd_inb(ahd, port+2) << 16)
-             | (ahd_inb(ahd, port+3) << 24));
-}
-
-static __inline void
-ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value)
-{
-       ahd_outb(ahd, port, (value) & 0xFF);
-       ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF);
-       ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF);
-       ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF);
-}
-
-static __inline uint64_t
-ahd_inq(struct ahd_softc *ahd, u_int port)
-{
-       return ((ahd_inb(ahd, port))
-             | (ahd_inb(ahd, port+1) << 8)
-             | (ahd_inb(ahd, port+2) << 16)
-             | (ahd_inb(ahd, port+3) << 24)
-             | (((uint64_t)ahd_inb(ahd, port+4)) << 32)
-             | (((uint64_t)ahd_inb(ahd, port+5)) << 40)
-             | (((uint64_t)ahd_inb(ahd, port+6)) << 48)
-             | (((uint64_t)ahd_inb(ahd, port+7)) << 56));
-}
-
-static __inline void
-ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value)
-{
-       ahd_outb(ahd, port, value & 0xFF);
-       ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
-       ahd_outb(ahd, port+2, (value >> 16) & 0xFF);
-       ahd_outb(ahd, port+3, (value >> 24) & 0xFF);
-       ahd_outb(ahd, port+4, (value >> 32) & 0xFF);
-       ahd_outb(ahd, port+5, (value >> 40) & 0xFF);
-       ahd_outb(ahd, port+6, (value >> 48) & 0xFF);
-       ahd_outb(ahd, port+7, (value >> 56) & 0xFF);
-}
-
-static __inline u_int
-ahd_get_scbptr(struct ahd_softc *ahd)
-{
-       AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
-                        ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
-       return (ahd_inb(ahd, SCBPTR) | (ahd_inb(ahd, SCBPTR + 1) << 8));
-}
-
-static __inline void
-ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr)
-{
-       AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
-                        ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
-       ahd_outb(ahd, SCBPTR, scbptr & 0xFF);
-       ahd_outb(ahd, SCBPTR+1, (scbptr >> 8) & 0xFF);
-}
-
-static __inline u_int
-ahd_get_hnscb_qoff(struct ahd_softc *ahd)
-{
-       return (ahd_inw_atomic(ahd, HNSCB_QOFF));
-}
-
-static __inline void
-ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value)
-{
-       ahd_outw_atomic(ahd, HNSCB_QOFF, value);
-}
-
-static __inline u_int
-ahd_get_hescb_qoff(struct ahd_softc *ahd)
-{
-       return (ahd_inb(ahd, HESCB_QOFF));
-}
-
-static __inline void
-ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value)
-{
-       ahd_outb(ahd, HESCB_QOFF, value);
-}
-
-static __inline u_int
-ahd_get_snscb_qoff(struct ahd_softc *ahd)
-{
-       u_int oldvalue;
-
-       AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
-       oldvalue = ahd_inw(ahd, SNSCB_QOFF);
-       ahd_outw(ahd, SNSCB_QOFF, oldvalue);
-       return (oldvalue);
-}
-
-static __inline void
-ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value)
-{
-       AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
-       ahd_outw(ahd, SNSCB_QOFF, value);
-}
-
-static __inline u_int
-ahd_get_sescb_qoff(struct ahd_softc *ahd)
-{
-       AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
-       return (ahd_inb(ahd, SESCB_QOFF));
-}
-
-static __inline void
-ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value)
-{
-       AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
-       ahd_outb(ahd, SESCB_QOFF, value);
-}
-
-static __inline u_int
-ahd_get_sdscb_qoff(struct ahd_softc *ahd)
-{
-       AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
-       return (ahd_inb(ahd, SDSCB_QOFF) | (ahd_inb(ahd, SDSCB_QOFF + 1) << 8));
-}
-
-static __inline void
-ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value)
-{
-       AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
-       ahd_outb(ahd, SDSCB_QOFF, value & 0xFF);
-       ahd_outb(ahd, SDSCB_QOFF+1, (value >> 8) & 0xFF);
-}
-
-static __inline u_int
-ahd_inb_scbram(struct ahd_softc *ahd, u_int offset)
-{
-       u_int value;
-
-       /*
-        * Workaround PCI-X Rev A. hardware bug.
-        * After a host read of SCB memory, the chip
-        * may become confused into thinking prefetch
-        * was required.  This starts the discard timer
-        * running and can cause an unexpected discard
-        * timer interrupt.  The work around is to read
-        * a normal register prior to the exhaustion of
-        * the discard timer.  The mode pointer register
-        * has no side effects and so serves well for
-        * this purpose.
-        *
-        * Razor #528
-        */
-       value = ahd_inb(ahd, offset);
-       if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0)
-               ahd_inb(ahd, MODE_PTR);
-       return (value);
-}
-
-static __inline u_int
-ahd_inw_scbram(struct ahd_softc *ahd, u_int offset)
-{
-       return (ahd_inb_scbram(ahd, offset)
-             | (ahd_inb_scbram(ahd, offset+1) << 8));
-}
-
-static __inline uint32_t
-ahd_inl_scbram(struct ahd_softc *ahd, u_int offset)
-{
-       return (ahd_inw_scbram(ahd, offset)
-             | (ahd_inw_scbram(ahd, offset+2) << 16));
-}
-
-static __inline uint64_t
-ahd_inq_scbram(struct ahd_softc *ahd, u_int offset)
-{
-       return (ahd_inl_scbram(ahd, offset)
-             | ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32);
-}
-
-static __inline struct scb *
-ahd_lookup_scb(struct ahd_softc *ahd, u_int tag)
-{
-       struct scb* scb;
-
-       if (tag >= AHD_SCB_MAX)
-               return (NULL);
-       scb = ahd->scb_data.scbindex[tag];
-       if (scb != NULL)
-               ahd_sync_scb(ahd, scb,
-                            BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
-       return (scb);
-}
-
-static __inline void
-ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
-{
-       struct   hardware_scb *q_hscb;
-       struct   map_node *q_hscb_map;
-       uint32_t saved_hscb_busaddr;
-
-       /*
-        * Our queuing method is a bit tricky.  The card
-        * knows in advance which HSCB (by address) to download,
-        * and we can't disappoint it.  To achieve this, the next
-        * HSCB to download is saved off in ahd->next_queued_hscb.
-        * When we are called to queue "an arbitrary scb",
-        * we copy the contents of the incoming HSCB to the one
-        * the sequencer knows about, swap HSCB pointers and
-        * finally assign the SCB to the tag indexed location
-        * in the scb_array.  This makes sure that we can still
-        * locate the correct SCB by SCB_TAG.
-        */
-       q_hscb = ahd->next_queued_hscb;
-       q_hscb_map = ahd->next_queued_hscb_map;
-       saved_hscb_busaddr = q_hscb->hscb_busaddr;
-       memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
-       q_hscb->hscb_busaddr = saved_hscb_busaddr;
-       q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
-
-       /* Now swap HSCB pointers. */
-       ahd->next_queued_hscb = scb->hscb;
-       ahd->next_queued_hscb_map = scb->hscb_map;
-       scb->hscb = q_hscb;
-       scb->hscb_map = q_hscb_map;
-
-       /* Now define the mapping from tag to SCB in the scbindex */
-       ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
-}
-
-/*
- * Tell the sequencer about a new transaction to execute.
- */
-static __inline void
-ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb)
-{
-       ahd_swap_with_next_hscb(ahd, scb);
-
-       if (SCBID_IS_NULL(SCB_GET_TAG(scb)))
-               panic("Attempt to queue invalid SCB tag %x\n",
-                     SCB_GET_TAG(scb));
-
-       /*
-        * Keep a history of SCBs we've downloaded in the qinfifo.
-        */
-       ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb);
-       ahd->qinfifonext++;
-
-       if (scb->sg_count != 0)
-               ahd_setup_data_scb(ahd, scb);
-       else
-               ahd_setup_noxfer_scb(ahd, scb);
-       ahd_setup_scb_common(ahd, scb);
-
-       /*
-        * Make sure our data is consistent from the
-        * perspective of the adapter.
-        */
-       ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
-
-#ifdef AHD_DEBUG
-       if ((ahd_debug & AHD_SHOW_QUEUE) != 0) {
-               uint64_t host_dataptr;
-
-               host_dataptr = ahd_le64toh(scb->hscb->dataptr);
-               printf("%s: Queueing SCB %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
-                      ahd_name(ahd),
-                      SCB_GET_TAG(scb), scb->hscb->scsiid,
-                      ahd_le32toh(scb->hscb->hscb_busaddr),
-                      (u_int)((host_dataptr >> 32) & 0xFFFFFFFF),
-                      (u_int)(host_dataptr & 0xFFFFFFFF),
-                      ahd_le32toh(scb->hscb->datacnt));
-       }
 #endif
-       /* Tell the adapter about the newly queued SCB */
-       ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
-}
 
 static __inline uint8_t *
 ahd_get_sense_buf(struct ahd_softc *ahd, struct scb *scb)
@@ -801,151 +171,6 @@ ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb)
 }
 
 /************************** Interrupt Processing ******************************/
-static __inline void   ahd_sync_qoutfifo(struct ahd_softc *ahd, int op);
-static __inline void   ahd_sync_tqinfifo(struct ahd_softc *ahd, int op);
-static __inline u_int  ahd_check_cmdcmpltqueues(struct ahd_softc *ahd);
-static __inline int    ahd_intr(struct ahd_softc *ahd);
-
-static __inline void
-ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
-{
-       ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
-                       /*offset*/0,
-                       /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op);
-}
-
-static __inline void
-ahd_sync_tqinfifo(struct ahd_softc *ahd, int op)
-{
-#ifdef AHD_TARGET_MODE
-       if ((ahd->flags & AHD_TARGETROLE) != 0) {
-               ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
-                               ahd->shared_data_map.dmamap,
-                               ahd_targetcmd_offset(ahd, 0),
-                               sizeof(struct target_cmd) * AHD_TMODE_CMDS,
-                               op);
-       }
-#endif
-}
-
-/*
- * See if the firmware has posted any completed commands
- * into our in-core command complete fifos.
- */
-#define AHD_RUN_QOUTFIFO 0x1
-#define AHD_RUN_TQINFIFO 0x2
-static __inline u_int
-ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
-{
-       u_int retval;
-
-       retval = 0;
-       ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
-                       /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),
-                       /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD);
-       if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag
-         == ahd->qoutfifonext_valid_tag)
-               retval |= AHD_RUN_QOUTFIFO;
-#ifdef AHD_TARGET_MODE
-       if ((ahd->flags & AHD_TARGETROLE) != 0
-        && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {
-               ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
-                               ahd->shared_data_map.dmamap,
-                               ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),
-                               /*len*/sizeof(struct target_cmd),
-                               BUS_DMASYNC_POSTREAD);
-               if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0)
-                       retval |= AHD_RUN_TQINFIFO;
-       }
-#endif
-       return (retval);
-}
-
-/*
- * Catch an interrupt from the adapter
- */
-static __inline int
-ahd_intr(struct ahd_softc *ahd)
-{
-       u_int   intstat;
-
-       if ((ahd->pause & INTEN) == 0) {
-               /*
-                * Our interrupt is not enabled on the chip
-                * and may be disabled for re-entrancy reasons,
-                * so just return.  This is likely just a shared
-                * interrupt.
-                */
-               return (0);
-       }
-
-       /*
-        * Instead of directly reading the interrupt status register,
-        * infer the cause of the interrupt by checking our in-core
-        * completion queues.  This avoids a costly PCI bus read in
-        * most cases.
-        */
-       if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0
-        && (ahd_check_cmdcmpltqueues(ahd) != 0))
-               intstat = CMDCMPLT;
-       else
-               intstat = ahd_inb(ahd, INTSTAT);
-
-       if ((intstat & INT_PEND) == 0)
-               return (0);
-
-       if (intstat & CMDCMPLT) {
-               ahd_outb(ahd, CLRINT, CLRCMDINT);
-
-               /*
-                * Ensure that the chip sees that we've cleared
-                * this interrupt before we walk the output fifo.
-                * Otherwise, we may, due to posted bus writes,
-                * clear the interrupt after we finish the scan,
-                * and after the sequencer has added new entries
-                * and asserted the interrupt again.
-                */
-               if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
-                       if (ahd_is_paused(ahd)) {
-                               /*
-                                * Potentially lost SEQINT.
-                                * If SEQINTCODE is non-zero,
-                                * simulate the SEQINT.
-                                */
-                               if (ahd_inb(ahd, SEQINTCODE) != NO_SEQINT)
-                                       intstat |= SEQINT;
-                       }
-               } else {
-                       ahd_flush_device_writes(ahd);
-               }
-               ahd_run_qoutfifo(ahd);
-               ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]++;
-               ahd->cmdcmplt_total++;
-#ifdef AHD_TARGET_MODE
-               if ((ahd->flags & AHD_TARGETROLE) != 0)
-                       ahd_run_tqinfifo(ahd, /*paused*/FALSE);
-#endif
-       }
-
-       /*
-        * Handle statuses that may invalidate our cached
-        * copy of INTSTAT separately.
-        */
-       if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) {
-               /* Hot eject.  Do nothing */
-       } else if (intstat & HWERRINT) {
-               ahd_handle_hwerrint(ahd);
-       } else if ((intstat & (PCIINT|SPLTINT)) != 0) {
-               ahd->bus_intr(ahd);
-       } else {
-
-               if ((intstat & SEQINT) != 0)
-                       ahd_handle_seqint(ahd, intstat);
-
-               if ((intstat & SCSIINT) != 0)
-                       ahd_handle_scsiint(ahd, intstat);
-       }
-       return (1);
-}
+int    ahd_intr(struct ahd_softc *ahd);
 
 #endif  /* _AIC79XX_INLINE_H_ */
index 0081aa357c8b09c7f5f939d76c4bddfd2b8de65f..0f829b3b8ab75e0f990e420045bd7007b4f6855f 100644 (file)
@@ -193,7 +193,7 @@ struct ahd_linux_iocell_opts
 #define AIC79XX_PRECOMP_INDEX  0
 #define AIC79XX_SLEWRATE_INDEX 1
 #define AIC79XX_AMPLITUDE_INDEX        2
-static struct ahd_linux_iocell_opts aic79xx_iocell_info[] =
+static const struct ahd_linux_iocell_opts aic79xx_iocell_info[] =
 {
        AIC79XX_DEFAULT_IOOPTS,
        AIC79XX_DEFAULT_IOOPTS,
@@ -369,10 +369,167 @@ static void ahd_release_simq(struct ahd_softc *ahd);
 static int ahd_linux_unit;
 
 
+/************************** OS Utility Wrappers *******************************/
+void ahd_delay(long);
+void
+ahd_delay(long usec)
+{
+       /*
+        * udelay on Linux can have problems for
+        * multi-millisecond waits.  Wait at most
+        * 1024us per call.
+        */
+       while (usec > 0) {
+               udelay(usec % 1024);
+               usec -= 1024;
+       }
+}
+
+
+/***************************** Low Level I/O **********************************/
+uint8_t ahd_inb(struct ahd_softc * ahd, long port);
+void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val);
+void ahd_outw_atomic(struct ahd_softc * ahd,
+                                    long port, uint16_t val);
+void ahd_outsb(struct ahd_softc * ahd, long port,
+                              uint8_t *, int count);
+void ahd_insb(struct ahd_softc * ahd, long port,
+                              uint8_t *, int count);
+
+uint8_t
+ahd_inb(struct ahd_softc * ahd, long port)
+{
+       uint8_t x;
+
+       if (ahd->tags[0] == BUS_SPACE_MEMIO) {
+               x = readb(ahd->bshs[0].maddr + port);
+       } else {
+               x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
+       }
+       mb();
+       return (x);
+}
+
+#if 0 /* unused */
+static uint16_t
+ahd_inw_atomic(struct ahd_softc * ahd, long port)
+{
+       uint8_t x;
+
+       if (ahd->tags[0] == BUS_SPACE_MEMIO) {
+               x = readw(ahd->bshs[0].maddr + port);
+       } else {
+               x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
+       }
+       mb();
+       return (x);
+}
+#endif
+
+void
+ahd_outb(struct ahd_softc * ahd, long port, uint8_t val)
+{
+       if (ahd->tags[0] == BUS_SPACE_MEMIO) {
+               writeb(val, ahd->bshs[0].maddr + port);
+       } else {
+               outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
+       }
+       mb();
+}
+
+void
+ahd_outw_atomic(struct ahd_softc * ahd, long port, uint16_t val)
+{
+       if (ahd->tags[0] == BUS_SPACE_MEMIO) {
+               writew(val, ahd->bshs[0].maddr + port);
+       } else {
+               outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
+       }
+       mb();
+}
+
+void
+ahd_outsb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
+{
+       int i;
+
+       /*
+        * There is probably a more efficient way to do this on Linux
+        * but we don't use this for anything speed critical and this
+        * should work.
+        */
+       for (i = 0; i < count; i++)
+               ahd_outb(ahd, port, *array++);
+}
+
+void
+ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
+{
+       int i;
+
+       /*
+        * There is probably a more efficient way to do this on Linux
+        * but we don't use this for anything speed critical and this
+        * should work.
+        */
+       for (i = 0; i < count; i++)
+               *array++ = ahd_inb(ahd, port);
+}
+
+/******************************* PCI Routines *********************************/
+uint32_t
+ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width)
+{
+       switch (width) {
+       case 1:
+       {
+               uint8_t retval;
+
+               pci_read_config_byte(pci, reg, &retval);
+               return (retval);
+       }
+       case 2:
+       {
+               uint16_t retval;
+               pci_read_config_word(pci, reg, &retval);
+               return (retval);
+       }
+       case 4:
+       {
+               uint32_t retval;
+               pci_read_config_dword(pci, reg, &retval);
+               return (retval);
+       }
+       default:
+               panic("ahd_pci_read_config: Read size too big");
+               /* NOTREACHED */
+               return (0);
+       }
+}
+
+void
+ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width)
+{
+       switch (width) {
+       case 1:
+               pci_write_config_byte(pci, reg, value);
+               break;
+       case 2:
+               pci_write_config_word(pci, reg, value);
+               break;
+       case 4:
+               pci_write_config_dword(pci, reg, value);
+               break;
+       default:
+               panic("ahd_pci_write_config: Write size too big");
+               /* NOTREACHED */
+       }
+}
+
 /****************************** Inlines ***************************************/
-static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
+static void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
 
-static __inline void
+static void
 ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
 {
        struct scsi_cmnd *cmd;
@@ -400,13 +557,11 @@ ahd_linux_info(struct Scsi_Host *host)
        bp = &buffer[0];
        ahd = *(struct ahd_softc **)host->hostdata;
        memset(bp, 0, sizeof(buffer));
-       strcpy(bp, "Adaptec AIC79XX PCI-X SCSI HBA DRIVER, Rev ");
-       strcat(bp, AIC79XX_DRIVER_VERSION);
-       strcat(bp, "\n");
-       strcat(bp, "        <");
+       strcpy(bp, "Adaptec AIC79XX PCI-X SCSI HBA DRIVER, Rev " AIC79XX_DRIVER_VERSION "\n"
+                       "        <");
        strcat(bp, ahd->description);
-       strcat(bp, ">\n");
-       strcat(bp, "        ");
+       strcat(bp, ">\n"
+                       "        ");
        ahd_controller_info(ahd, ahd_info);
        strcat(bp, ahd_info);
 
@@ -432,7 +587,7 @@ ahd_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
        return rtn;
 }
 
-static inline struct scsi_target **
+static struct scsi_target **
 ahd_linux_target_in_softc(struct scsi_target *starget)
 {
        struct  ahd_softc *ahd =
@@ -991,7 +1146,7 @@ aic79xx_setup(char *s)
        char   *p;
        char   *end;
 
-       static struct {
+       static const struct {
                const char *name;
                uint32_t *flag;
        } options[] = {
@@ -1223,7 +1378,7 @@ ahd_platform_init(struct ahd_softc *ahd)
         * Lookup and commit any modified IO Cell options.
         */
        if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) {
-               struct ahd_linux_iocell_opts *iocell_opts;
+               const struct ahd_linux_iocell_opts *iocell_opts;
 
                iocell_opts = &aic79xx_iocell_info[ahd->unit];
                if (iocell_opts->precomp != AIC79XX_DEFAULT_PRECOMP)
@@ -2613,7 +2768,7 @@ static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp)
                uint8_t precomp;
 
                if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) {
-                       struct ahd_linux_iocell_opts *iocell_opts;
+                       const struct ahd_linux_iocell_opts *iocell_opts;
 
                        iocell_opts = &aic79xx_iocell_info[ahd->unit];
                        precomp = iocell_opts->precomp;
index 853998be1474f4059deb2251bef1ec7bb10a182c..8d6612c19922fe29cfd340992550627131b9897c 100644 (file)
@@ -222,22 +222,6 @@ typedef struct timer_list ahd_timer_t;
 /***************************** Timer Facilities *******************************/
 #define ahd_timer_init init_timer
 #define ahd_timer_stop del_timer_sync
-typedef void ahd_linux_callback_t (u_long);  
-static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec,
-                                    ahd_callback_t *func, void *arg);
-
-static __inline void
-ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
-{
-       struct ahd_softc *ahd;
-
-       ahd = (struct ahd_softc *)arg;
-       del_timer(timer);
-       timer->data = (u_long)arg;
-       timer->expires = jiffies + (usec * HZ)/1000000;
-       timer->function = (ahd_linux_callback_t*)func;
-       add_timer(timer);
-}
 
 /***************************** SMP support ************************************/
 #include <linux/spinlock.h>
@@ -376,7 +360,7 @@ struct ahd_platform_data {
 #define AHD_LINUX_NOIRQ        ((uint32_t)~0)
        uint32_t                 irq;           /* IRQ for this adapter */
        uint32_t                 bios_address;
-       uint32_t                 mem_busaddr;   /* Mem Base Addr */
+       resource_size_t          mem_busaddr;   /* Mem Base Addr */
 };
 
 /************************** OS Utility Wrappers *******************************/
@@ -386,111 +370,18 @@ struct ahd_platform_data {
 #define malloc(size, type, flags) kmalloc(size, flags)
 #define free(ptr, type) kfree(ptr)
 
-static __inline void ahd_delay(long);
-static __inline void
-ahd_delay(long usec)
-{
-       /*
-        * udelay on Linux can have problems for
-        * multi-millisecond waits.  Wait at most
-        * 1024us per call.
-        */
-       while (usec > 0) {
-               udelay(usec % 1024);
-               usec -= 1024;
-       }
-}
-
+void ahd_delay(long);
 
 /***************************** Low Level I/O **********************************/
-static __inline uint8_t ahd_inb(struct ahd_softc * ahd, long port);
-static __inline uint16_t ahd_inw_atomic(struct ahd_softc * ahd, long port);
-static __inline void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val);
-static __inline void ahd_outw_atomic(struct ahd_softc * ahd,
+uint8_t ahd_inb(struct ahd_softc * ahd, long port);
+void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val);
+void ahd_outw_atomic(struct ahd_softc * ahd,
                                     long port, uint16_t val);
-static __inline void ahd_outsb(struct ahd_softc * ahd, long port,
+void ahd_outsb(struct ahd_softc * ahd, long port,
                               uint8_t *, int count);
-static __inline void ahd_insb(struct ahd_softc * ahd, long port,
+void ahd_insb(struct ahd_softc * ahd, long port,
                               uint8_t *, int count);
 
-static __inline uint8_t
-ahd_inb(struct ahd_softc * ahd, long port)
-{
-       uint8_t x;
-
-       if (ahd->tags[0] == BUS_SPACE_MEMIO) {
-               x = readb(ahd->bshs[0].maddr + port);
-       } else {
-               x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
-       }
-       mb();
-       return (x);
-}
-
-static __inline uint16_t
-ahd_inw_atomic(struct ahd_softc * ahd, long port)
-{
-       uint8_t x;
-
-       if (ahd->tags[0] == BUS_SPACE_MEMIO) {
-               x = readw(ahd->bshs[0].maddr + port);
-       } else {
-               x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
-       }
-       mb();
-       return (x);
-}
-
-static __inline void
-ahd_outb(struct ahd_softc * ahd, long port, uint8_t val)
-{
-       if (ahd->tags[0] == BUS_SPACE_MEMIO) {
-               writeb(val, ahd->bshs[0].maddr + port);
-       } else {
-               outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
-       }
-       mb();
-}
-
-static __inline void
-ahd_outw_atomic(struct ahd_softc * ahd, long port, uint16_t val)
-{
-       if (ahd->tags[0] == BUS_SPACE_MEMIO) {
-               writew(val, ahd->bshs[0].maddr + port);
-       } else {
-               outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
-       }
-       mb();
-}
-
-static __inline void
-ahd_outsb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
-{
-       int i;
-
-       /*
-        * There is probably a more efficient way to do this on Linux
-        * but we don't use this for anything speed critical and this
-        * should work.
-        */
-       for (i = 0; i < count; i++)
-               ahd_outb(ahd, port, *array++);
-}
-
-static __inline void
-ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
-{
-       int i;
-
-       /*
-        * There is probably a more efficient way to do this on Linux
-        * but we don't use this for anything speed critical and this
-        * should work.
-        */
-       for (i = 0; i < count; i++)
-               *array++ = ahd_inb(ahd, port);
-}
-
 /**************************** Initialization **********************************/
 int            ahd_linux_register_host(struct ahd_softc *,
                                        struct scsi_host_template *);
@@ -593,62 +484,12 @@ void                       ahd_linux_pci_exit(void);
 int                     ahd_pci_map_registers(struct ahd_softc *ahd);
 int                     ahd_pci_map_int(struct ahd_softc *ahd);
 
-static __inline uint32_t ahd_pci_read_config(ahd_dev_softc_t pci,
+uint32_t                ahd_pci_read_config(ahd_dev_softc_t pci,
                                             int reg, int width);
-
-static __inline uint32_t
-ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width)
-{
-       switch (width) {
-       case 1:
-       {
-               uint8_t retval;
-
-               pci_read_config_byte(pci, reg, &retval);
-               return (retval);
-       }
-       case 2:
-       {
-               uint16_t retval;
-               pci_read_config_word(pci, reg, &retval);
-               return (retval);
-       }
-       case 4:
-       {
-               uint32_t retval;
-               pci_read_config_dword(pci, reg, &retval);
-               return (retval);
-       }
-       default:
-               panic("ahd_pci_read_config: Read size too big");
-               /* NOTREACHED */
-               return (0);
-       }
-}
-
-static __inline void ahd_pci_write_config(ahd_dev_softc_t pci,
+void                    ahd_pci_write_config(ahd_dev_softc_t pci,
                                          int reg, uint32_t value,
                                          int width);
 
-static __inline void
-ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width)
-{
-       switch (width) {
-       case 1:
-               pci_write_config_byte(pci, reg, value);
-               break;
-       case 2:
-               pci_write_config_word(pci, reg, value);
-               break;
-       case 4:
-               pci_write_config_dword(pci, reg, value);
-               break;
-       default:
-               panic("ahd_pci_write_config: Write size too big");
-               /* NOTREACHED */
-       }
-}
-
 static __inline int ahd_get_pci_function(ahd_dev_softc_t);
 static __inline int
 ahd_get_pci_function(ahd_dev_softc_t pci)
index dfaaae5e73aebdee4a8fa873117f1ce23db4c3f7..6593056867f6d33b9ac472b49f19ff56d9dcd96f 100644 (file)
@@ -49,7 +49,7 @@
        ID2C(x),         \
        ID2C(IDIROC(x))
 
-static struct pci_device_id ahd_linux_pci_id_table[] = {
+static const struct pci_device_id ahd_linux_pci_id_table[] = {
        /* aic7901 based controllers */
        ID(ID_AHA_29320A),
        ID(ID_AHA_29320ALP),
@@ -159,7 +159,7 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        char             buf[80];
        struct           ahd_softc *ahd;
        ahd_dev_softc_t  pci;
-       struct           ahd_pci_identity *entry;
+       const struct ahd_pci_identity *entry;
        char            *name;
        int              error;
        struct device   *dev = &pdev->dev;
@@ -249,8 +249,8 @@ ahd_linux_pci_exit(void)
 }
 
 static int
-ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base,
-                                u_long *base2)
+ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, resource_size_t *base,
+                                resource_size_t *base2)
 {
        *base = pci_resource_start(ahd->dev_softc, 0);
        /*
@@ -272,11 +272,11 @@ ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base,
 
 static int
 ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
-                                u_long *bus_addr,
+                                resource_size_t *bus_addr,
                                 uint8_t __iomem **maddr)
 {
-       u_long  start;
-       u_long  base_page;
+       resource_size_t start;
+       resource_size_t base_page;
        u_long  base_offset;
        int     error = 0;
 
@@ -310,7 +310,7 @@ int
 ahd_pci_map_registers(struct ahd_softc *ahd)
 {
        uint32_t command;
-       u_long   base;
+       resource_size_t base;
        uint8_t __iomem *maddr;
        int      error;
 
@@ -346,31 +346,32 @@ ahd_pci_map_registers(struct ahd_softc *ahd)
                } else
                        command |= PCIM_CMD_MEMEN;
        } else if (bootverbose) {
-               printf("aic79xx: PCI%d:%d:%d MEM region 0x%lx "
+               printf("aic79xx: PCI%d:%d:%d MEM region 0x%llx "
                       "unavailable. Cannot memory map device.\n",
                       ahd_get_pci_bus(ahd->dev_softc),
                       ahd_get_pci_slot(ahd->dev_softc),
                       ahd_get_pci_function(ahd->dev_softc),
-                      base);
+                      (unsigned long long)base);
        }
 
        if (maddr == NULL) {
-               u_long   base2;
+               resource_size_t base2;
 
                error = ahd_linux_pci_reserve_io_regions(ahd, &base, &base2);
                if (error == 0) {
                        ahd->tags[0] = BUS_SPACE_PIO;
                        ahd->tags[1] = BUS_SPACE_PIO;
-                       ahd->bshs[0].ioport = base;
-                       ahd->bshs[1].ioport = base2;
+                       ahd->bshs[0].ioport = (u_long)base;
+                       ahd->bshs[1].ioport = (u_long)base2;
                        command |= PCIM_CMD_PORTEN;
                } else {
-                       printf("aic79xx: PCI%d:%d:%d IO regions 0x%lx and 0x%lx"
-                              "unavailable. Cannot map device.\n",
+                       printf("aic79xx: PCI%d:%d:%d IO regions 0x%llx and "
+                              "0x%llx unavailable. Cannot map device.\n",
                               ahd_get_pci_bus(ahd->dev_softc),
                               ahd_get_pci_slot(ahd->dev_softc),
                               ahd_get_pci_function(ahd->dev_softc),
-                              base, base2);
+                              (unsigned long long)base,
+                              (unsigned long long)base2);
                }
        }
        ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, 4);
index c9f79fdf913105d77046db61619c6432a4123dd6..c25b6adffbf94f50fd5684063e7add6b04984895 100644 (file)
@@ -97,7 +97,7 @@ static ahd_device_setup_t ahd_aic7901A_setup;
 static ahd_device_setup_t ahd_aic7902_setup;
 static ahd_device_setup_t ahd_aic790X_setup;
 
-static struct ahd_pci_identity ahd_pci_ident_table [] =
+static const struct ahd_pci_identity ahd_pci_ident_table[] =
 {
        /* aic7901 based controllers */
        {
@@ -253,7 +253,7 @@ static void ahd_configure_termination(struct ahd_softc *ahd,
 static void    ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat);
 static void    ahd_pci_intr(struct ahd_softc *ahd);
 
-struct ahd_pci_identity *
+const struct ahd_pci_identity *
 ahd_find_pci_device(ahd_dev_softc_t pci)
 {
        uint64_t  full_id;
@@ -261,7 +261,7 @@ ahd_find_pci_device(ahd_dev_softc_t pci)
        uint16_t  vendor;
        uint16_t  subdevice;
        uint16_t  subvendor;
-       struct    ahd_pci_identity *entry;
+       const struct ahd_pci_identity *entry;
        u_int     i;
 
        vendor = ahd_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
@@ -292,7 +292,7 @@ ahd_find_pci_device(ahd_dev_softc_t pci)
 }
 
 int
-ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
+ahd_pci_config(struct ahd_softc *ahd, const struct ahd_pci_identity *entry)
 {
        struct scb_data *shared_scb_data;
        u_int            command;
index 6b28bebcbca0fffb4021fd517e5cf93254be6d07..014bed716e7c9e349e51af90a8ec739927d7cc6c 100644 (file)
@@ -57,7 +57,7 @@ static int    ahd_proc_write_seeprom(struct ahd_softc *ahd,
  * Table of syncrates that don't follow the "divisible by 4"
  * rule. This table will be expanded in future SCSI specs.
  */
-static struct {
+static const struct {
        u_int period_factor;
        u_int period;   /* in 100ths of ns */
 } scsi_syncrates[] = {
index 2068e00d2c750a09c8b733aff1fa01af385a395e..c21ceab8e9134f699af09203b6dada11acd1d132 100644 (file)
@@ -47,13 +47,6 @@ ahd_reg_print_t ahd_error_print;
     ahd_print_register(NULL, 0, "ERROR", 0x04, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_clrerr_print;
-#else
-#define ahd_clrerr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CLRERR", 0x04, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_hcntrl_print;
 #else
@@ -166,13 +159,6 @@ ahd_reg_print_t ahd_sg_cache_shadow_print;
     ahd_print_register(NULL, 0, "SG_CACHE_SHADOW", 0x1b, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_arbctl_print;
-#else
-#define ahd_arbctl_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "ARBCTL", 0x1b, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_sg_cache_pre_print;
 #else
@@ -187,20 +173,6 @@ ahd_reg_print_t ahd_lqin_print;
     ahd_print_register(NULL, 0, "LQIN", 0x20, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_typeptr_print;
-#else
-#define ahd_typeptr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "TYPEPTR", 0x20, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_tagptr_print;
-#else
-#define ahd_tagptr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "TAGPTR", 0x21, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_lunptr_print;
 #else
@@ -208,20 +180,6 @@ ahd_reg_print_t ahd_lunptr_print;
     ahd_print_register(NULL, 0, "LUNPTR", 0x22, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_datalenptr_print;
-#else
-#define ahd_datalenptr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DATALENPTR", 0x23, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_statlenptr_print;
-#else
-#define ahd_statlenptr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "STATLENPTR", 0x24, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_cmdlenptr_print;
 #else
@@ -257,13 +215,6 @@ ahd_reg_print_t ahd_qnextptr_print;
     ahd_print_register(NULL, 0, "QNEXTPTR", 0x29, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_idptr_print;
-#else
-#define ahd_idptr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "IDPTR", 0x2a, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_abrtbyteptr_print;
 #else
@@ -278,27 +229,6 @@ ahd_reg_print_t ahd_abrtbitptr_print;
     ahd_print_register(NULL, 0, "ABRTBITPTR", 0x2c, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_maxcmdbytes_print;
-#else
-#define ahd_maxcmdbytes_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "MAXCMDBYTES", 0x2d, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_maxcmd2rcv_print;
-#else
-#define ahd_maxcmd2rcv_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "MAXCMD2RCV", 0x2e, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_shortthresh_print;
-#else
-#define ahd_shortthresh_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SHORTTHRESH", 0x2f, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_lunlen_print;
 #else
@@ -327,41 +257,6 @@ ahd_reg_print_t ahd_maxcmdcnt_print;
     ahd_print_register(NULL, 0, "MAXCMDCNT", 0x33, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_lqrsvd01_print;
-#else
-#define ahd_lqrsvd01_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "LQRSVD01", 0x34, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_lqrsvd16_print;
-#else
-#define ahd_lqrsvd16_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "LQRSVD16", 0x35, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_lqrsvd17_print;
-#else
-#define ahd_lqrsvd17_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "LQRSVD17", 0x36, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_cmdrsvd0_print;
-#else
-#define ahd_cmdrsvd0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CMDRSVD0", 0x37, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_lqctl0_print;
-#else
-#define ahd_lqctl0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "LQCTL0", 0x38, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_lqctl1_print;
 #else
@@ -369,13 +264,6 @@ ahd_reg_print_t ahd_lqctl1_print;
     ahd_print_register(NULL, 0, "LQCTL1", 0x38, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scsbist0_print;
-#else
-#define ahd_scsbist0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCSBIST0", 0x39, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_lqctl2_print;
 #else
@@ -383,13 +271,6 @@ ahd_reg_print_t ahd_lqctl2_print;
     ahd_print_register(NULL, 0, "LQCTL2", 0x39, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scsbist1_print;
-#else
-#define ahd_scsbist1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCSBIST1", 0x3a, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_scsiseq0_print;
 #else
@@ -411,20 +292,6 @@ ahd_reg_print_t ahd_sxfrctl0_print;
     ahd_print_register(NULL, 0, "SXFRCTL0", 0x3c, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dlcount_print;
-#else
-#define ahd_dlcount_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_businitid_print;
-#else
-#define ahd_businitid_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_sxfrctl1_print;
 #else
@@ -432,20 +299,6 @@ ahd_reg_print_t ahd_sxfrctl1_print;
     ahd_print_register(NULL, 0, "SXFRCTL1", 0x3d, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_bustargid_print;
-#else
-#define ahd_bustargid_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "BUSTARGID", 0x3e, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sxfrctl2_print;
-#else
-#define ahd_sxfrctl2_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SXFRCTL2", 0x3e, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_dffstat_print;
 #else
@@ -454,17 +307,17 @@ ahd_reg_print_t ahd_dffstat_print;
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scsisigo_print;
+ahd_reg_print_t ahd_multargid_print;
 #else
-#define ahd_scsisigo_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCSISIGO", 0x40, regvalue, cur_col, wrap)
+#define ahd_multargid_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "MULTARGID", 0x40, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_multargid_print;
+ahd_reg_print_t ahd_scsisigo_print;
 #else
-#define ahd_multargid_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "MULTARGID", 0x40, regvalue, cur_col, wrap)
+#define ahd_scsisigo_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SCSISIGO", 0x40, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
@@ -481,13 +334,6 @@ ahd_reg_print_t ahd_scsiphase_print;
     ahd_print_register(NULL, 0, "SCSIPHASE", 0x42, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scsidat0_img_print;
-#else
-#define ahd_scsidat0_img_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCSIDAT0_IMG", 0x43, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_scsidat_print;
 #else
@@ -530,13 +376,6 @@ ahd_reg_print_t ahd_sblkctl_print;
     ahd_print_register(NULL, 0, "SBLKCTL", 0x4a, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_clrsint0_print;
-#else
-#define ahd_clrsint0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CLRSINT0", 0x4b, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_sstat0_print;
 #else
@@ -552,10 +391,10 @@ ahd_reg_print_t ahd_simode0_print;
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_clrsint1_print;
+ahd_reg_print_t ahd_clrsint0_print;
 #else
-#define ahd_clrsint1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CLRSINT1", 0x4c, regvalue, cur_col, wrap)
+#define ahd_clrsint0_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "CLRSINT0", 0x4b, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
@@ -566,17 +405,17 @@ ahd_reg_print_t ahd_sstat1_print;
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sstat2_print;
+ahd_reg_print_t ahd_clrsint1_print;
 #else
-#define ahd_sstat2_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SSTAT2", 0x4d, regvalue, cur_col, wrap)
+#define ahd_clrsint1_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "CLRSINT1", 0x4c, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_simode2_print;
+ahd_reg_print_t ahd_sstat2_print;
 #else
-#define ahd_simode2_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SIMODE2", 0x4d, regvalue, cur_col, wrap)
+#define ahd_sstat2_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SSTAT2", 0x4d, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
@@ -622,17 +461,17 @@ ahd_reg_print_t ahd_lqistat0_print;
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_clrlqiint0_print;
+ahd_reg_print_t ahd_lqimode0_print;
 #else
-#define ahd_clrlqiint0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CLRLQIINT0", 0x50, regvalue, cur_col, wrap)
+#define ahd_lqimode0_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "LQIMODE0", 0x50, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_lqimode0_print;
+ahd_reg_print_t ahd_clrlqiint0_print;
 #else
-#define ahd_lqimode0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "LQIMODE0", 0x50, regvalue, cur_col, wrap)
+#define ahd_clrlqiint0_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "CLRLQIINT0", 0x50, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
@@ -789,13 +628,6 @@ ahd_reg_print_t ahd_seqintsrc_print;
     ahd_print_register(NULL, 0, "SEQINTSRC", 0x5b, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_currscb_print;
-#else
-#define ahd_currscb_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CURRSCB", 0x5c, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_seqimode_print;
 #else
@@ -804,24 +636,17 @@ ahd_reg_print_t ahd_seqimode_print;
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_mdffstat_print;
-#else
-#define ahd_mdffstat_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "MDFFSTAT", 0x5d, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_crccontrol_print;
+ahd_reg_print_t ahd_currscb_print;
 #else
-#define ahd_crccontrol_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CRCCONTROL", 0x5d, regvalue, cur_col, wrap)
+#define ahd_currscb_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "CURRSCB", 0x5c, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dfftag_print;
+ahd_reg_print_t ahd_mdffstat_print;
 #else
-#define ahd_dfftag_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DFFTAG", 0x5e, regvalue, cur_col, wrap)
+#define ahd_mdffstat_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "MDFFSTAT", 0x5d, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
@@ -831,20 +656,6 @@ ahd_reg_print_t ahd_lastscb_print;
     ahd_print_register(NULL, 0, "LASTSCB", 0x5e, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scsitest_print;
-#else
-#define ahd_scsitest_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCSITEST", 0x5e, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_iopdnctl_print;
-#else
-#define ahd_iopdnctl_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "IOPDNCTL", 0x5f, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_shaddr_print;
 #else
@@ -859,13 +670,6 @@ ahd_reg_print_t ahd_negoaddr_print;
     ahd_print_register(NULL, 0, "NEGOADDR", 0x60, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dgrpcrci_print;
-#else
-#define ahd_dgrpcrci_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DGRPCRCI", 0x60, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_negperiod_print;
 #else
@@ -873,13 +677,6 @@ ahd_reg_print_t ahd_negperiod_print;
     ahd_print_register(NULL, 0, "NEGPERIOD", 0x61, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_packcrci_print;
-#else
-#define ahd_packcrci_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "PACKCRCI", 0x62, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_negoffset_print;
 #else
@@ -929,13 +726,6 @@ ahd_reg_print_t ahd_iownid_print;
     ahd_print_register(NULL, 0, "IOWNID", 0x67, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_pll960ctl0_print;
-#else
-#define ahd_pll960ctl0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "PLL960CTL0", 0x68, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_shcnt_print;
 #else
@@ -950,27 +740,6 @@ ahd_reg_print_t ahd_townid_print;
     ahd_print_register(NULL, 0, "TOWNID", 0x69, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_pll960ctl1_print;
-#else
-#define ahd_pll960ctl1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "PLL960CTL1", 0x69, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_pll960cnt0_print;
-#else
-#define ahd_pll960cnt0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "PLL960CNT0", 0x6a, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_xsig_print;
-#else
-#define ahd_xsig_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "XSIG", 0x6a, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_seloid_print;
 #else
@@ -978,41 +747,6 @@ ahd_reg_print_t ahd_seloid_print;
     ahd_print_register(NULL, 0, "SELOID", 0x6b, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_pll400ctl0_print;
-#else
-#define ahd_pll400ctl0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "PLL400CTL0", 0x6c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_fairness_print;
-#else
-#define ahd_fairness_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "FAIRNESS", 0x6c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_pll400ctl1_print;
-#else
-#define ahd_pll400ctl1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "PLL400CTL1", 0x6d, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_unfairness_print;
-#else
-#define ahd_unfairness_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_pll400cnt0_print;
-#else
-#define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_haddr_print;
 #else
@@ -1020,27 +754,6 @@ ahd_reg_print_t ahd_haddr_print;
     ahd_print_register(NULL, 0, "HADDR", 0x70, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_plldelay_print;
-#else
-#define ahd_plldelay_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "PLLDELAY", 0x70, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_hodmaadr_print;
-#else
-#define ahd_hodmaadr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "HODMAADR", 0x70, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_hodmacnt_print;
-#else
-#define ahd_hodmacnt_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "HODMACNT", 0x78, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_hcnt_print;
 #else
@@ -1049,10 +762,10 @@ ahd_reg_print_t ahd_hcnt_print;
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_hodmaen_print;
+ahd_reg_print_t ahd_sghaddr_print;
 #else
-#define ahd_hodmaen_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "HODMAEN", 0x7a, regvalue, cur_col, wrap)
+#define ahd_sghaddr_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
@@ -1063,10 +776,10 @@ ahd_reg_print_t ahd_scbhaddr_print;
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sghaddr_print;
+ahd_reg_print_t ahd_sghcnt_print;
 #else
-#define ahd_sghaddr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap)
+#define ahd_sghcnt_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
@@ -1076,13 +789,6 @@ ahd_reg_print_t ahd_scbhcnt_print;
     ahd_print_register(NULL, 0, "SCBHCNT", 0x84, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sghcnt_print;
-#else
-#define ahd_sghcnt_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_dff_thrsh_print;
 #else
@@ -1091,357 +797,56 @@ ahd_reg_print_t ahd_dff_thrsh_print;
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_romaddr_print;
+ahd_reg_print_t ahd_pcixctl_print;
 #else
-#define ahd_romaddr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "ROMADDR", 0x8a, regvalue, cur_col, wrap)
+#define ahd_pcixctl_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "PCIXCTL", 0x93, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_romcntrl_print;
+ahd_reg_print_t ahd_dchspltstat0_print;
 #else
-#define ahd_romcntrl_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "ROMCNTRL", 0x8d, regvalue, cur_col, wrap)
+#define ahd_dchspltstat0_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "DCHSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_romdata_print;
+ahd_reg_print_t ahd_dchspltstat1_print;
 #else
-#define ahd_romdata_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "ROMDATA", 0x8e, regvalue, cur_col, wrap)
+#define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_cmcrxmsg0_print;
+ahd_reg_print_t ahd_sgspltstat0_print;
 #else
-#define ahd_cmcrxmsg0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CMCRXMSG0", 0x90, regvalue, cur_col, wrap)
+#define ahd_sgspltstat0_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SGSPLTSTAT0", 0x9e, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_roenable_print;
+ahd_reg_print_t ahd_sgspltstat1_print;
 #else
-#define ahd_roenable_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "ROENABLE", 0x90, regvalue, cur_col, wrap)
+#define ahd_sgspltstat1_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlyrxmsg0_print;
+ahd_reg_print_t ahd_df0pcistat_print;
 #else
-#define ahd_ovlyrxmsg0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "OVLYRXMSG0", 0x90, regvalue, cur_col, wrap)
+#define ahd_df0pcistat_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "DF0PCISTAT", 0xa0, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dchrxmsg0_print;
+ahd_reg_print_t ahd_reg0_print;
 #else
-#define ahd_dchrxmsg0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DCHRXMSG0", 0x90, regvalue, cur_col, wrap)
+#define ahd_reg0_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "REG0", 0xa0, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlyrxmsg1_print;
-#else
-#define ahd_ovlyrxmsg1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "OVLYRXMSG1", 0x91, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_nsenable_print;
-#else
-#define ahd_nsenable_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "NSENABLE", 0x91, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_cmcrxmsg1_print;
-#else
-#define ahd_cmcrxmsg1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CMCRXMSG1", 0x91, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dchrxmsg1_print;
-#else
-#define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dchrxmsg2_print;
-#else
-#define ahd_dchrxmsg2_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DCHRXMSG2", 0x92, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_cmcrxmsg2_print;
-#else
-#define ahd_cmcrxmsg2_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CMCRXMSG2", 0x92, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ost_print;
-#else
-#define ahd_ost_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "OST", 0x92, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlyrxmsg2_print;
-#else
-#define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dchrxmsg3_print;
-#else
-#define ahd_dchrxmsg3_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DCHRXMSG3", 0x93, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlyrxmsg3_print;
-#else
-#define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_cmcrxmsg3_print;
-#else
-#define ahd_cmcrxmsg3_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CMCRXMSG3", 0x93, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_pcixctl_print;
-#else
-#define ahd_pcixctl_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "PCIXCTL", 0x93, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlyseqbcnt_print;
-#else
-#define ahd_ovlyseqbcnt_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "OVLYSEQBCNT", 0x94, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dchseqbcnt_print;
-#else
-#define ahd_dchseqbcnt_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DCHSEQBCNT", 0x94, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_cmcseqbcnt_print;
-#else
-#define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_cmcspltstat0_print;
-#else
-#define ahd_cmcspltstat0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CMCSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dchspltstat0_print;
-#else
-#define ahd_dchspltstat0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DCHSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlyspltstat0_print;
-#else
-#define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_cmcspltstat1_print;
-#else
-#define ahd_cmcspltstat1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CMCSPLTSTAT1", 0x97, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlyspltstat1_print;
-#else
-#define ahd_ovlyspltstat1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "OVLYSPLTSTAT1", 0x97, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dchspltstat1_print;
-#else
-#define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sgrxmsg0_print;
-#else
-#define ahd_sgrxmsg0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SGRXMSG0", 0x98, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_slvspltoutadr0_print;
-#else
-#define ahd_slvspltoutadr0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SLVSPLTOUTADR0", 0x98, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sgrxmsg1_print;
-#else
-#define ahd_sgrxmsg1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SGRXMSG1", 0x99, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_slvspltoutadr1_print;
-#else
-#define ahd_slvspltoutadr1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SLVSPLTOUTADR1", 0x99, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sgrxmsg2_print;
-#else
-#define ahd_sgrxmsg2_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SGRXMSG2", 0x9a, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_slvspltoutadr2_print;
-#else
-#define ahd_slvspltoutadr2_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SLVSPLTOUTADR2", 0x9a, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sgrxmsg3_print;
-#else
-#define ahd_sgrxmsg3_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SGRXMSG3", 0x9b, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_slvspltoutadr3_print;
-#else
-#define ahd_slvspltoutadr3_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SLVSPLTOUTADR3", 0x9b, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sgseqbcnt_print;
-#else
-#define ahd_sgseqbcnt_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SGSEQBCNT", 0x9c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_slvspltoutattr0_print;
-#else
-#define ahd_slvspltoutattr0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SLVSPLTOUTATTR0", 0x9c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_slvspltoutattr1_print;
-#else
-#define ahd_slvspltoutattr1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SLVSPLTOUTATTR1", 0x9d, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_slvspltoutattr2_print;
-#else
-#define ahd_slvspltoutattr2_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SLVSPLTOUTATTR2", 0x9e, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sgspltstat0_print;
-#else
-#define ahd_sgspltstat0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SGSPLTSTAT0", 0x9e, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sgspltstat1_print;
-#else
-#define ahd_sgspltstat1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sfunct_print;
-#else
-#define ahd_sfunct_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_df0pcistat_print;
-#else
-#define ahd_df0pcistat_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DF0PCISTAT", 0xa0, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_reg0_print;
-#else
-#define ahd_reg0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "REG0", 0xa0, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_df1pcistat_print;
-#else
-#define ahd_df1pcistat_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DF1PCISTAT", 0xa1, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sgpcistat_print;
-#else
-#define ahd_sgpcistat_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SGPCISTAT", 0xa2, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_reg1_print;
-#else
-#define ahd_reg1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "REG1", 0xa2, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_cmcpcistat_print;
-#else
-#define ahd_cmcpcistat_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CMCPCISTAT", 0xa3, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlypcistat_print;
-#else
-#define ahd_ovlypcistat_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "OVLYPCISTAT", 0xa4, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_reg_isr_print;
+ahd_reg_print_t ahd_reg_isr_print;
 #else
 #define ahd_reg_isr_print(regvalue, cur_col, wrap) \
     ahd_print_register(NULL, 0, "REG_ISR", 0xa4, regvalue, cur_col, wrap)
@@ -1454,13 +859,6 @@ ahd_reg_print_t ahd_sg_state_print;
     ahd_print_register(NULL, 0, "SG_STATE", 0xa6, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_msipcistat_print;
-#else
-#define ahd_msipcistat_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "MSIPCISTAT", 0xa6, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_targpcistat_print;
 #else
@@ -1468,13 +866,6 @@ ahd_reg_print_t ahd_targpcistat_print;
     ahd_print_register(NULL, 0, "TARGPCISTAT", 0xa7, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_data_count_odd_print;
-#else
-#define ahd_data_count_odd_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DATA_COUNT_ODD", 0xa7, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_scbptr_print;
 #else
@@ -1482,13 +873,6 @@ ahd_reg_print_t ahd_scbptr_print;
     ahd_print_register(NULL, 0, "SCBPTR", 0xa8, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ccscbacnt_print;
-#else
-#define ahd_ccscbacnt_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CCSCBACNT", 0xab, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_scbautoptr_print;
 #else
@@ -1503,13 +887,6 @@ ahd_reg_print_t ahd_ccsgaddr_print;
     ahd_print_register(NULL, 0, "CCSGADDR", 0xac, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ccscbadr_bk_print;
-#else
-#define ahd_ccscbadr_bk_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_ccscbaddr_print;
 #else
@@ -1517,13 +894,6 @@ ahd_reg_print_t ahd_ccscbaddr_print;
     ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_cmc_rambist_print;
-#else
-#define ahd_cmc_rambist_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CMC_RAMBIST", 0xad, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_ccscbctl_print;
 #else
@@ -1545,13 +915,6 @@ ahd_reg_print_t ahd_ccsgram_print;
     ahd_print_register(NULL, 0, "CCSGRAM", 0xb0, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_flexadr_print;
-#else
-#define ahd_flexadr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "FLEXADR", 0xb0, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_ccscbram_print;
 #else
@@ -1559,27 +922,6 @@ ahd_reg_print_t ahd_ccscbram_print;
     ahd_print_register(NULL, 0, "CCSCBRAM", 0xb0, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_flexcnt_print;
-#else
-#define ahd_flexcnt_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "FLEXCNT", 0xb3, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_flexdmastat_print;
-#else
-#define ahd_flexdmastat_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "FLEXDMASTAT", 0xb5, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_flexdata_print;
-#else
-#define ahd_flexdata_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "FLEXDATA", 0xb6, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_brddat_print;
 #else
@@ -1622,27 +964,6 @@ ahd_reg_print_t ahd_seestat_print;
     ahd_print_register(NULL, 0, "SEESTAT", 0xbe, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scbcnt_print;
-#else
-#define ahd_scbcnt_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCBCNT", 0xbf, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dfwaddr_print;
-#else
-#define ahd_dfwaddr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DFWADDR", 0xc0, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dspfltrctl_print;
-#else
-#define ahd_dspfltrctl_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DSPFLTRCTL", 0xc0, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_dspdatactl_print;
 #else
@@ -1650,27 +971,6 @@ ahd_reg_print_t ahd_dspdatactl_print;
     ahd_print_register(NULL, 0, "DSPDATACTL", 0xc1, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dfraddr_print;
-#else
-#define ahd_dfraddr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DFRADDR", 0xc2, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dspreqctl_print;
-#else
-#define ahd_dspreqctl_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DSPREQCTL", 0xc2, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dspackctl_print;
-#else
-#define ahd_dspackctl_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DSPACKCTL", 0xc3, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_dfdat_print;
 #else
@@ -1692,76 +992,6 @@ ahd_reg_print_t ahd_wrtbiasctl_print;
     ahd_print_register(NULL, 0, "WRTBIASCTL", 0xc5, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_rcvrbiosctl_print;
-#else
-#define ahd_rcvrbiosctl_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "RCVRBIOSCTL", 0xc6, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_wrtbiascalc_print;
-#else
-#define ahd_wrtbiascalc_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "WRTBIASCALC", 0xc7, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_rcvrbiascalc_print;
-#else
-#define ahd_rcvrbiascalc_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "RCVRBIASCALC", 0xc8, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dfptrs_print;
-#else
-#define ahd_dfptrs_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_skewcalc_print;
-#else
-#define ahd_skewcalc_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SKEWCALC", 0xc9, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dfbkptr_print;
-#else
-#define ahd_dfbkptr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dfdbctl_print;
-#else
-#define ahd_dfdbctl_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DFDBCTL", 0xcb, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dfscnt_print;
-#else
-#define ahd_dfscnt_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DFSCNT", 0xcc, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dfbcnt_print;
-#else
-#define ahd_dfbcnt_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DFBCNT", 0xce, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlyaddr_print;
-#else
-#define ahd_ovlyaddr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "OVLYADDR", 0xd4, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_seqctl0_print;
 #else
@@ -1769,13 +999,6 @@ ahd_reg_print_t ahd_seqctl0_print;
     ahd_print_register(NULL, 0, "SEQCTL0", 0xd6, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_seqctl1_print;
-#else
-#define ahd_seqctl1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SEQCTL1", 0xd7, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_flags_print;
 #else
@@ -1825,20 +1048,6 @@ ahd_reg_print_t ahd_dindex_print;
     ahd_print_register(NULL, 0, "DINDEX", 0xe4, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_brkaddr0_print;
-#else
-#define ahd_brkaddr0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "BRKADDR0", 0xe6, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_brkaddr1_print;
-#else
-#define ahd_brkaddr1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_allones_print;
 #else
@@ -1874,13 +1083,6 @@ ahd_reg_print_t ahd_dindir_print;
     ahd_print_register(NULL, 0, "DINDIR", 0xed, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_function1_print;
-#else
-#define ahd_function1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "FUNCTION1", 0xf0, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_stack_print;
 #else
@@ -1902,13 +1104,6 @@ ahd_reg_print_t ahd_curaddr_print;
     ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_lastaddr_print;
-#else
-#define ahd_lastaddr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "LASTADDR", 0xf6, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_intvec2_addr_print;
 #else
@@ -1931,24 +1126,17 @@ ahd_reg_print_t ahd_accum_save_print;
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_waiting_scb_tails_print;
-#else
-#define ahd_waiting_scb_tails_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "WAITING_SCB_TAILS", 0x100, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ahd_pci_config_base_print;
+ahd_reg_print_t ahd_sram_base_print;
 #else
-#define ahd_ahd_pci_config_base_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "AHD_PCI_CONFIG_BASE", 0x100, regvalue, cur_col, wrap)
+#define ahd_sram_base_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SRAM_BASE", 0x100, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sram_base_print;
+ahd_reg_print_t ahd_waiting_scb_tails_print;
 #else
-#define ahd_sram_base_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SRAM_BASE", 0x100, regvalue, cur_col, wrap)
+#define ahd_waiting_scb_tails_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "WAITING_SCB_TAILS", 0x100, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
@@ -2218,17 +1406,17 @@ ahd_reg_print_t ahd_mk_message_scsiid_print;
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_base_print;
+ahd_reg_print_t ahd_scb_residual_datacnt_print;
 #else
-#define ahd_scb_base_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_BASE", 0x180, regvalue, cur_col, wrap)
+#define ahd_scb_residual_datacnt_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SCB_RESIDUAL_DATACNT", 0x180, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_residual_datacnt_print;
+ahd_reg_print_t ahd_scb_base_print;
 #else
-#define ahd_scb_residual_datacnt_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_RESIDUAL_DATACNT", 0x180, regvalue, cur_col, wrap)
+#define ahd_scb_base_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SCB_BASE", 0x180, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
@@ -2245,27 +1433,6 @@ ahd_reg_print_t ahd_scb_scsi_status_print;
     ahd_print_register(NULL, 0, "SCB_SCSI_STATUS", 0x188, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_target_phases_print;
-#else
-#define ahd_scb_target_phases_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_TARGET_PHASES", 0x189, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_target_data_dir_print;
-#else
-#define ahd_scb_target_data_dir_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_TARGET_DATA_DIR", 0x18a, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_target_itag_print;
-#else
-#define ahd_scb_target_itag_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_TARGET_ITAG", 0x18b, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_scb_sense_busaddr_print;
 #else
@@ -2364,13 +1531,6 @@ ahd_reg_print_t ahd_scb_next2_print;
     ahd_print_register(NULL, 0, "SCB_NEXT2", 0x1ae, regvalue, cur_col, wrap)
 #endif
 
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_spare_print;
-#else
-#define ahd_scb_spare_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_SPARE", 0x1b0, regvalue, cur_col, wrap)
-#endif
-
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #else
@@ -2557,10 +1717,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 
 #define        SG_CACHE_PRE                    0x1b
 
-#define        LQIN                            0x20
-
 #define        TYPEPTR                         0x20
 
+#define        LQIN                            0x20
+
 #define        TAGPTR                          0x21
 
 #define        LUNPTR                          0x22
@@ -2620,14 +1780,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                SINGLECMD               0x02
 #define                ABORTPENDING            0x01
 
-#define        SCSBIST0                        0x39
-#define                GSBISTERR               0x40
-#define                GSBISTDONE              0x20
-#define                GSBISTRUN               0x10
-#define                OSBISTERR               0x04
-#define                OSBISTDONE              0x02
-#define                OSBISTRUN               0x01
-
 #define        LQCTL2                          0x39
 #define                LQIRETRY                0x80
 #define                LQICONTINUE             0x40
@@ -2638,10 +1790,13 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                LQOTOIDLE               0x02
 #define                LQOPAUSE                0x01
 
-#define        SCSBIST1                        0x3a
-#define                NTBISTERR               0x04
-#define                NTBISTDONE              0x02
-#define                NTBISTRUN               0x01
+#define        SCSBIST0                        0x39
+#define                GSBISTERR               0x40
+#define                GSBISTDONE              0x20
+#define                GSBISTRUN               0x10
+#define                OSBISTERR               0x04
+#define                OSBISTDONE              0x02
+#define                OSBISTRUN               0x01
 
 #define        SCSISEQ0                        0x3a
 #define                TEMODEO                 0x80
@@ -2650,8 +1805,15 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                FORCEBUSFREE            0x10
 #define                SCSIRSTO                0x01
 
+#define        SCSBIST1                        0x3a
+#define                NTBISTERR               0x04
+#define                NTBISTDONE              0x02
+#define                NTBISTRUN               0x01
+
 #define        SCSISEQ1                        0x3b
 
+#define        BUSINITID                       0x3c
+
 #define        SXFRCTL0                        0x3c
 #define                DFON                    0x80
 #define                DFPEXP                  0x40
@@ -2660,8 +1822,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 
 #define        DLCOUNT                         0x3c
 
-#define        BUSINITID                       0x3c
-
 #define        SXFRCTL1                        0x3d
 #define                BITBUCKET               0x80
 #define                ENSACHK                 0x40
@@ -2686,6 +1846,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                CURRFIFO_1              0x01
 #define                CURRFIFO_0              0x00
 
+#define        MULTARGID                       0x40
+
 #define        SCSISIGO                        0x40
 #define                CDO                     0x80
 #define                IOO                     0x40
@@ -2696,8 +1858,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                REQO                    0x02
 #define                ACKO                    0x01
 
-#define        MULTARGID                       0x40
-
 #define        SCSISIGI                        0x41
 #define                ATNI                    0x10
 #define                SELI                    0x08
@@ -2744,15 +1904,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                ENAB20                  0x04
 #define                SELWIDE                 0x02
 
-#define        CLRSINT0                        0x4b
-#define                CLRSELDO                0x40
-#define                CLRSELDI                0x20
-#define                CLRSELINGO              0x10
-#define                CLRIOERR                0x08
-#define                CLROVERRUN              0x04
-#define                CLRSPIORDY              0x02
-#define                CLRARBDO                0x01
-
 #define        SSTAT0                          0x4b
 #define                TARGET                  0x80
 #define                SELDO                   0x40
@@ -2772,14 +1923,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                ENSPIORDY               0x02
 #define                ENARBDO                 0x01
 
-#define        CLRSINT1                        0x4c
-#define                CLRSELTIMEO             0x80
-#define                CLRATNO                 0x40
-#define                CLRSCSIRSTI             0x20
-#define                CLRBUSFREE              0x08
-#define                CLRSCSIPERR             0x04
-#define                CLRSTRB2FAST            0x02
-#define                CLRREQINIT              0x01
+#define        CLRSINT0                        0x4b
+#define                CLRSELDO                0x40
+#define                CLRSELDI                0x20
+#define                CLRSELINGO              0x10
+#define                CLRIOERR                0x08
+#define                CLROVERRUN              0x04
+#define                CLRSPIORDY              0x02
+#define                CLRARBDO                0x01
 
 #define        SSTAT1                          0x4c
 #define                SELTO                   0x80
@@ -2791,6 +1942,15 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                STRB2FAST               0x02
 #define                REQINIT                 0x01
 
+#define        CLRSINT1                        0x4c
+#define                CLRSELTIMEO             0x80
+#define                CLRATNO                 0x40
+#define                CLRSCSIRSTI             0x20
+#define                CLRBUSFREE              0x08
+#define                CLRSCSIPERR             0x04
+#define                CLRSTRB2FAST            0x02
+#define                CLRREQINIT              0x01
+
 #define        SSTAT2                          0x4d
 #define                BUSFREETIME             0xc0
 #define                NONPACKREQ              0x20
@@ -2838,14 +1998,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                LQIATNLQ                0x02
 #define                LQIATNCMD               0x01
 
-#define        CLRLQIINT0                      0x50
-#define                CLRLQIATNQAS            0x20
-#define                CLRLQICRCT1             0x10
-#define                CLRLQICRCT2             0x08
-#define                CLRLQIBADLQT            0x04
-#define                CLRLQIATNLQ             0x02
-#define                CLRLQIATNCMD            0x01
-
 #define        LQIMODE0                        0x50
 #define                ENLQIATNQASK            0x20
 #define                ENLQICRCT1              0x10
@@ -2854,6 +2006,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                ENLQIATNLQ              0x02
 #define                ENLQIATNCMD             0x01
 
+#define        CLRLQIINT0                      0x50
+#define                CLRLQIATNQAS            0x20
+#define                CLRLQICRCT1             0x10
+#define                CLRLQICRCT2             0x08
+#define                CLRLQIBADLQT            0x04
+#define                CLRLQIATNLQ             0x02
+#define                CLRLQIATNCMD            0x01
+
 #define        LQIMODE1                        0x51
 #define                ENLQIPHASE_LQ           0x80
 #define                ENLQIPHASE_NLQ          0x40
@@ -2976,6 +2136,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 
 #define        LQOSCSCTL                       0x5a
 #define                LQOH2A_VERSION          0x80
+#define                LQOBUSETDLY             0x40
+#define                LQONOHOLDLACK           0x02
 #define                LQONOCHKOVER            0x01
 
 #define        NEXTSCB                         0x5a
@@ -2998,8 +2160,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                CFG4ICMD                0x02
 #define                CFG4TCMD                0x01
 
-#define        CURRSCB                         0x5c
-
 #define        SEQIMODE                        0x5c
 #define                ENCTXTDONE              0x40
 #define                ENSAVEPTRS              0x20
@@ -3009,6 +2169,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                ENCFG4ICMD              0x02
 #define                ENCFG4TCMD              0x01
 
+#define        CURRSCB                         0x5c
+
 #define        MDFFSTAT                        0x5d
 #define                SHCNTNEGATIVE           0x40
 #define                SHCNTMINUS1             0x20
@@ -3023,29 +2185,29 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 
 #define        DFFTAG                          0x5e
 
-#define        LASTSCB                         0x5e
-
 #define        SCSITEST                        0x5e
 #define                CNTRTEST                0x08
 #define                SEL_TXPLL_DEBUG         0x04
 
+#define        LASTSCB                         0x5e
+
 #define        IOPDNCTL                        0x5f
 #define                DISABLE_OE              0x80
 #define                PDN_IDIST               0x04
 #define                PDN_DIFFSENSE           0x01
 
+#define        DGRPCRCI                        0x60
+
 #define        SHADDR                          0x60
 
 #define        NEGOADDR                        0x60
 
-#define        DGRPCRCI                        0x60
-
 #define        NEGPERIOD                       0x61
 
-#define        PACKCRCI                        0x62
-
 #define        NEGOFFSET                       0x62
 
+#define        PACKCRCI                        0x62
+
 #define        NEGPPROPTS                      0x63
 #define                PPROPT_PACE             0x08
 #define                PPROPT_QAS              0x04
@@ -3066,6 +2228,7 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define        ANNEXDAT                        0x66
 
 #define        SCSCHKN                         0x66
+#define                BIDICHKDIS              0x80
 #define                STSELSKIDDIS            0x40
 #define                CURRFIFODEF             0x20
 #define                WIDERESEN               0x10
@@ -3090,6 +2253,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 
 #define        SELOID                          0x6b
 
+#define        FAIRNESS                        0x6c
+
 #define        PLL400CTL0                      0x6c
 #define                PLL_VCOSEL              0x80
 #define                PLL_PWDN                0x40
@@ -3099,8 +2264,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                PLL_DLPF                0x02
 #define                PLL_ENFBM               0x01
 
-#define        FAIRNESS                        0x6c
-
 #define        PLL400CTL1                      0x6d
 #define                PLL_CNTEN               0x80
 #define                PLL_CNTCLR              0x40
@@ -3112,25 +2275,25 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 
 #define        HADDR                           0x70
 
+#define        HODMAADR                        0x70
+
 #define        PLLDELAY                        0x70
 #define                SPLIT_DROP_REQ          0x80
 
-#define        HODMAADR                        0x70
+#define        HCNT                            0x78
 
 #define        HODMACNT                        0x78
 
-#define        HCNT                            0x78
-
 #define        HODMAEN                         0x7a
 
-#define        SCBHADDR                        0x7c
-
 #define        SGHADDR                         0x7c
 
-#define        SCBHCNT                         0x84
+#define        SCBHADDR                        0x7c
 
 #define        SGHCNT                          0x84
 
+#define        SCBHCNT                         0x84
+
 #define        DFF_THRSH                       0x88
 #define                WR_DFTHRSH              0x70
 #define                RD_DFTHRSH              0x07
@@ -3163,6 +2326,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 
 #define        CMCRXMSG0                       0x90
 
+#define        OVLYRXMSG0                      0x90
+
+#define        DCHRXMSG0                       0x90
+
 #define        ROENABLE                        0x90
 #define                MSIROEN                 0x20
 #define                OVLYROEN                0x10
@@ -3171,11 +2338,11 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                DCH1ROEN                0x02
 #define                DCH0ROEN                0x01
 
-#define        OVLYRXMSG0                      0x90
+#define        OVLYRXMSG1                      0x91
 
-#define        DCHRXMSG0                       0x90
+#define        CMCRXMSG1                       0x91
 
-#define        OVLYRXMSG1                      0x91
+#define        DCHRXMSG1                       0x91
 
 #define        NSENABLE                        0x91
 #define                MSINSEN                 0x20
@@ -3185,10 +2352,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                DCH1NSEN                0x02
 #define                DCH0NSEN                0x01
 
-#define        CMCRXMSG1                       0x91
-
-#define        DCHRXMSG1                       0x91
-
 #define        DCHRXMSG2                       0x92
 
 #define        CMCRXMSG2                       0x92
@@ -3212,24 +2375,24 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                TSCSERREN               0x02
 #define                CMPABCDIS               0x01
 
+#define        CMCSEQBCNT                      0x94
+
 #define        OVLYSEQBCNT                     0x94
 
 #define        DCHSEQBCNT                      0x94
 
-#define        CMCSEQBCNT                      0x94
-
-#define        CMCSPLTSTAT0                    0x96
-
 #define        DCHSPLTSTAT0                    0x96
 
 #define        OVLYSPLTSTAT0                   0x96
 
-#define        CMCSPLTSTAT1                    0x97
+#define        CMCSPLTSTAT0                    0x96
 
 #define        OVLYSPLTSTAT1                   0x97
 
 #define        DCHSPLTSTAT1                    0x97
 
+#define        CMCSPLTSTAT1                    0x97
+
 #define        SGRXMSG0                        0x98
 #define                CDNUM                   0xf8
 #define                CFNUM                   0x07
@@ -3257,18 +2420,15 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                TAG_NUM                 0x1f
 #define                RLXORD                  0x10
 
-#define        SGSEQBCNT                       0x9c
-
 #define        SLVSPLTOUTATTR0                 0x9c
 #define                LOWER_BCNT              0xff
 
+#define        SGSEQBCNT                       0x9c
+
 #define        SLVSPLTOUTATTR1                 0x9d
 #define                CMPLT_DNUM              0xf8
 #define                CMPLT_FNUM              0x07
 
-#define        SLVSPLTOUTATTR2                 0x9e
-#define                CMPLT_BNUM              0xff
-
 #define        SGSPLTSTAT0                     0x9e
 #define                STAETERM                0x80
 #define                SCBCERR                 0x40
@@ -3279,6 +2439,9 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                RXSCEMSG                0x02
 #define                RXSPLTRSP               0x01
 
+#define        SLVSPLTOUTATTR2                 0x9e
+#define                CMPLT_BNUM              0xff
+
 #define        SGSPLTSTAT1                     0x9f
 #define                RXDATABUCKET            0x01
 
@@ -3334,10 +2497,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 
 #define        CCSGADDR                        0xac
 
-#define        CCSCBADR_BK                     0xac
-
 #define        CCSCBADDR                       0xac
 
+#define        CCSCBADR_BK                     0xac
+
 #define        CMC_RAMBIST                     0xad
 #define                SG_ELEMENT_SIZE         0x80
 #define                SCBRAMBIST_FAIL         0x40
@@ -3391,9 +2554,9 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define        SEEDAT                          0xbc
 
 #define        SEECTL                          0xbe
+#define                SEEOP_EWDS              0x40
 #define                SEEOP_WALL              0x40
 #define                SEEOP_EWEN              0x40
-#define                SEEOP_EWDS              0x40
 #define                SEEOPCODE               0x70
 #define                SEERST                  0x02
 #define                SEESTART                0x01
@@ -3410,25 +2573,25 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 
 #define        SCBCNT                          0xbf
 
-#define        DFWADDR                         0xc0
-
 #define        DSPFLTRCTL                      0xc0
 #define                FLTRDISABLE             0x20
 #define                EDGESENSE               0x10
 #define                DSPFCNTSEL              0x0f
 
+#define        DFWADDR                         0xc0
+
 #define        DSPDATACTL                      0xc1
 #define                BYPASSENAB              0x80
 #define                DESQDIS                 0x10
 #define                RCVROFFSTDIS            0x04
 #define                XMITOFFSTDIS            0x02
 
-#define        DFRADDR                         0xc2
-
 #define        DSPREQCTL                       0xc2
 #define                MANREQCTL               0xc0
 #define                MANREQDLY               0x3f
 
+#define        DFRADDR                         0xc2
+
 #define        DSPACKCTL                       0xc3
 #define                MANACKCTL               0xc0
 #define                MANACKDLY               0x3f
@@ -3449,14 +2612,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 
 #define        WRTBIASCALC                     0xc7
 
-#define        RCVRBIASCALC                    0xc8
-
 #define        DFPTRS                          0xc8
 
-#define        SKEWCALC                        0xc9
+#define        RCVRBIASCALC                    0xc8
 
 #define        DFBKPTR                         0xc9
 
+#define        SKEWCALC                        0xc9
+
 #define        DFDBCTL                         0xcb
 #define                DFF_CIO_WR_RDY          0x20
 #define                DFF_CIO_RD_RDY          0x10
@@ -3541,12 +2704,12 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 
 #define        ACCUM_SAVE                      0xfa
 
-#define        WAITING_SCB_TAILS               0x100
-
 #define        AHD_PCI_CONFIG_BASE             0x100
 
 #define        SRAM_BASE                       0x100
 
+#define        WAITING_SCB_TAILS               0x100
+
 #define        WAITING_TID_HEAD                0x120
 
 #define        WAITING_TID_TAIL                0x122
@@ -3575,8 +2738,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define                PRELOADEN               0x80
 #define                WIDEODD                 0x40
 #define                SCSIEN                  0x20
-#define                SDMAEN                  0x10
 #define                SDMAENACK               0x10
+#define                SDMAEN                  0x10
 #define                HDMAEN                  0x08
 #define                HDMAENACK               0x08
 #define                DIRECTION               0x04
@@ -3674,12 +2837,12 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 
 #define        MK_MESSAGE_SCSIID               0x162
 
-#define        SCB_BASE                        0x180
-
 #define        SCB_RESIDUAL_DATACNT            0x180
 #define        SCB_CDB_STORE                   0x180
 #define        SCB_HOST_CDB_PTR                0x180
 
+#define        SCB_BASE                        0x180
+
 #define        SCB_RESIDUAL_SGPTR              0x184
 #define                SG_ADDR_MASK            0xf8
 #define                SG_OVERRUN_RESID        0x02
@@ -3747,6 +2910,17 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define        SCB_DISCONNECTED_LISTS          0x1b8
 
 
+#define        CMD_GROUP_CODE_SHIFT    0x05
+#define        STIMESEL_MIN    0x18
+#define        STIMESEL_SHIFT  0x03
+#define        INVALID_ADDR    0x80
+#define        AHD_PRECOMP_MASK        0x07
+#define        TARGET_DATA_IN  0x01
+#define        CCSCBADDR_MAX   0x80
+#define        NUMDSPS         0x14
+#define        SEEOP_EWEN_ADDR 0xc0
+#define        AHD_ANNEXCOL_PER_DEV0   0x04
+#define        DST_MODE_SHIFT  0x04
 #define        AHD_TIMER_MAX_US        0x18ffe7
 #define        AHD_TIMER_MAX_TICKS     0xffff
 #define        AHD_SENSE_BUFSIZE       0x100
@@ -3781,43 +2955,32 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
 #define        LUNLEN_SINGLE_LEVEL_LUN 0x0f
 #define        NVRAM_SCB_OFFSET        0x2c
 #define        STATUS_PKT_SENSE        0xff
-#define        CMD_GROUP_CODE_SHIFT    0x05
 #define        MAX_OFFSET_PACED_BUG    0x7f
 #define        STIMESEL_BUG_ADJ        0x08
-#define        STIMESEL_MIN    0x18
-#define        STIMESEL_SHIFT  0x03
 #define        CCSGRAM_MAXSEGS 0x10
-#define        INVALID_ADDR    0x80
 #define        SEEOP_ERAL_ADDR 0x80
 #define        AHD_SLEWRATE_DEF_REVB   0x08
 #define        AHD_PRECOMP_CUTBACK_17  0x04
-#define        AHD_PRECOMP_MASK        0x07
 #define        SRC_MODE_SHIFT  0x00
 #define        PKT_OVERRUN_BUFSIZE     0x200
 #define        SCB_TRANSFER_SIZE_1BYTE_LUN     0x30
-#define        TARGET_DATA_IN  0x01
 #define        HOST_MSG        0xff
 #define        MAX_OFFSET      0xfe
 #define        BUS_16_BIT      0x01
-#define        CCSCBADDR_MAX   0x80
-#define        NUMDSPS         0x14
-#define        SEEOP_EWEN_ADDR 0xc0
-#define        AHD_ANNEXCOL_PER_DEV0   0x04
-#define        DST_MODE_SHIFT  0x04
 
 
 /* Downloaded Constant Definitions */
+#define        SG_SIZEOF       0x04
+#define        SG_PREFETCH_ALIGN_MASK  0x02
+#define        SG_PREFETCH_CNT_LIMIT   0x01
 #define        CACHELINE_MASK  0x07
 #define        SCB_TRANSFER_SIZE       0x06
 #define        PKT_OVERRUN_BUFOFFSET   0x05
-#define        SG_SIZEOF       0x04
 #define        SG_PREFETCH_ADDR_MASK   0x03
-#define        SG_PREFETCH_ALIGN_MASK  0x02
-#define        SG_PREFETCH_CNT_LIMIT   0x01
 #define        SG_PREFETCH_CNT 0x00
 #define        DOWNLOAD_CONST_COUNT    0x08
 
 
 /* Exported Labels */
-#define        LABEL_seq_isr   0x28f
 #define        LABEL_timer_isr 0x28b
+#define        LABEL_seq_isr   0x28f
index db38a61a8cb4f2cf15160f4406a4749fcb716ad9..c4c8a96bf5a36b53003f8ce15549760f94dfd134 100644 (file)
@@ -8,7 +8,7 @@
 
 #include "aic79xx_osm.h"
 
-static ahd_reg_parse_entry_t MODE_PTR_parse_table[] = {
+static const ahd_reg_parse_entry_t MODE_PTR_parse_table[] = {
        { "SRC_MODE",           0x07, 0x07 },
        { "DST_MODE",           0x70, 0x70 }
 };
@@ -20,7 +20,7 @@ ahd_mode_ptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x00, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t INTSTAT_parse_table[] = {
+static const ahd_reg_parse_entry_t INTSTAT_parse_table[] = {
        { "SPLTINT",            0x01, 0x01 },
        { "CMDCMPLT",           0x02, 0x02 },
        { "SEQINT",             0x04, 0x04 },
@@ -39,7 +39,7 @@ ahd_intstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x01, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SEQINTCODE_parse_table[] = {
+static const ahd_reg_parse_entry_t SEQINTCODE_parse_table[] = {
        { "NO_SEQINT",          0x00, 0xff },
        { "BAD_PHASE",          0x01, 0xff },
        { "SEND_REJECT",        0x02, 0xff },
@@ -76,7 +76,7 @@ ahd_seqintcode_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x02, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t CLRINT_parse_table[] = {
+static const ahd_reg_parse_entry_t CLRINT_parse_table[] = {
        { "CLRSPLTINT",         0x01, 0x01 },
        { "CLRCMDINT",          0x02, 0x02 },
        { "CLRSEQINT",          0x04, 0x04 },
@@ -94,7 +94,7 @@ ahd_clrint_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x03, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t ERROR_parse_table[] = {
+static const ahd_reg_parse_entry_t ERROR_parse_table[] = {
        { "DSCTMOUT",           0x02, 0x02 },
        { "ILLOPCODE",          0x04, 0x04 },
        { "SQPARERR",           0x08, 0x08 },
@@ -111,24 +111,7 @@ ahd_error_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x04, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t CLRERR_parse_table[] = {
-       { "CLRDSCTMOUT",        0x02, 0x02 },
-       { "CLRILLOPCODE",       0x04, 0x04 },
-       { "CLRSQPARERR",        0x08, 0x08 },
-       { "CLRDPARERR",         0x10, 0x10 },
-       { "CLRMPARERR",         0x20, 0x20 },
-       { "CLRCIOACCESFAIL",    0x40, 0x40 },
-       { "CLRCIOPARERR",       0x80, 0x80 }
-};
-
-int
-ahd_clrerr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(CLRERR_parse_table, 7, "CLRERR",
-           0x04, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t HCNTRL_parse_table[] = {
+static const ahd_reg_parse_entry_t HCNTRL_parse_table[] = {
        { "CHIPRST",            0x01, 0x01 },
        { "CHIPRSTACK",         0x01, 0x01 },
        { "INTEN",              0x02, 0x02 },
@@ -160,7 +143,7 @@ ahd_hescb_qoff_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x08, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t HS_MAILBOX_parse_table[] = {
+static const ahd_reg_parse_entry_t HS_MAILBOX_parse_table[] = {
        { "ENINT_COALESCE",     0x40, 0x40 },
        { "HOST_TQINPOS",       0x80, 0x80 }
 };
@@ -172,7 +155,7 @@ ahd_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x0b, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SEQINTSTAT_parse_table[] = {
+static const ahd_reg_parse_entry_t SEQINTSTAT_parse_table[] = {
        { "SEQ_SPLTINT",        0x01, 0x01 },
        { "SEQ_PCIINT",         0x02, 0x02 },
        { "SEQ_SCSIINT",        0x04, 0x04 },
@@ -187,7 +170,7 @@ ahd_seqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x0c, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = {
+static const ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = {
        { "CLRSEQ_SPLTINT",     0x01, 0x01 },
        { "CLRSEQ_PCIINT",      0x02, 0x02 },
        { "CLRSEQ_SCSIINT",     0x04, 0x04 },
@@ -230,7 +213,7 @@ ahd_sdscb_qoff_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x14, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t QOFF_CTLSTA_parse_table[] = {
+static const ahd_reg_parse_entry_t QOFF_CTLSTA_parse_table[] = {
        { "SCB_QSIZE_4",        0x00, 0x0f },
        { "SCB_QSIZE_8",        0x01, 0x0f },
        { "SCB_QSIZE_16",       0x02, 0x0f },
@@ -258,7 +241,7 @@ ahd_qoff_ctlsta_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x16, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t INTCTL_parse_table[] = {
+static const ahd_reg_parse_entry_t INTCTL_parse_table[] = {
        { "SPLTINTEN",          0x01, 0x01 },
        { "SEQINTEN",           0x02, 0x02 },
        { "SCSIINTEN",          0x04, 0x04 },
@@ -276,7 +259,7 @@ ahd_intctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x18, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t DFCNTRL_parse_table[] = {
+static const ahd_reg_parse_entry_t DFCNTRL_parse_table[] = {
        { "DIRECTIONEN",        0x01, 0x01 },
        { "FIFOFLUSH",          0x02, 0x02 },
        { "FIFOFLUSHACK",       0x02, 0x02 },
@@ -297,7 +280,7 @@ ahd_dfcntrl_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x19, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t DSCOMMAND0_parse_table[] = {
+static const ahd_reg_parse_entry_t DSCOMMAND0_parse_table[] = {
        { "CIOPARCKEN",         0x01, 0x01 },
        { "DISABLE_TWATE",      0x02, 0x02 },
        { "EXTREQLCK",          0x10, 0x10 },
@@ -313,7 +296,7 @@ ahd_dscommand0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x19, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t DFSTATUS_parse_table[] = {
+static const ahd_reg_parse_entry_t DFSTATUS_parse_table[] = {
        { "FIFOEMP",            0x01, 0x01 },
        { "FIFOFULL",           0x02, 0x02 },
        { "DFTHRESH",           0x04, 0x04 },
@@ -330,7 +313,7 @@ ahd_dfstatus_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x1a, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SG_CACHE_SHADOW_parse_table[] = {
+static const ahd_reg_parse_entry_t SG_CACHE_SHADOW_parse_table[] = {
        { "LAST_SEG_DONE",      0x01, 0x01 },
        { "LAST_SEG",           0x02, 0x02 },
        { "ODD_SEG",            0x04, 0x04 },
@@ -344,20 +327,7 @@ ahd_sg_cache_shadow_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x1b, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t ARBCTL_parse_table[] = {
-       { "USE_TIME",           0x07, 0x07 },
-       { "RETRY_SWEN",         0x08, 0x08 },
-       { "RESET_HARB",         0x80, 0x80 }
-};
-
-int
-ahd_arbctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(ARBCTL_parse_table, 3, "ARBCTL",
-           0x1b, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SG_CACHE_PRE_parse_table[] = {
+static const ahd_reg_parse_entry_t SG_CACHE_PRE_parse_table[] = {
        { "LAST_SEG",           0x02, 0x02 },
        { "ODD_SEG",            0x04, 0x04 },
        { "SG_ADDR_MASK",       0xf8, 0xf8 }
@@ -377,20 +347,6 @@ ahd_lqin_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x20, regvalue, cur_col, wrap));
 }
 
-int
-ahd_typeptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "TYPEPTR",
-           0x20, regvalue, cur_col, wrap));
-}
-
-int
-ahd_tagptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "TAGPTR",
-           0x21, regvalue, cur_col, wrap));
-}
-
 int
 ahd_lunptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -398,20 +354,6 @@ ahd_lunptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x22, regvalue, cur_col, wrap));
 }
 
-int
-ahd_datalenptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "DATALENPTR",
-           0x23, regvalue, cur_col, wrap));
-}
-
-int
-ahd_statlenptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "STATLENPTR",
-           0x24, regvalue, cur_col, wrap));
-}
-
 int
 ahd_cmdlenptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -447,13 +389,6 @@ ahd_qnextptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x29, regvalue, cur_col, wrap));
 }
 
-int
-ahd_idptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "IDPTR",
-           0x2a, regvalue, cur_col, wrap));
-}
-
 int
 ahd_abrtbyteptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -468,28 +403,7 @@ ahd_abrtbitptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x2c, regvalue, cur_col, wrap));
 }
 
-int
-ahd_maxcmdbytes_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "MAXCMDBYTES",
-           0x2d, regvalue, cur_col, wrap));
-}
-
-int
-ahd_maxcmd2rcv_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "MAXCMD2RCV",
-           0x2e, regvalue, cur_col, wrap));
-}
-
-int
-ahd_shortthresh_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "SHORTTHRESH",
-           0x2f, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t LUNLEN_parse_table[] = {
+static const ahd_reg_parse_entry_t LUNLEN_parse_table[] = {
        { "ILUNLEN",            0x0f, 0x0f },
        { "TLUNLEN",            0xf0, 0xf0 }
 };
@@ -522,49 +436,7 @@ ahd_maxcmdcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x33, regvalue, cur_col, wrap));
 }
 
-int
-ahd_lqrsvd01_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "LQRSVD01",
-           0x34, regvalue, cur_col, wrap));
-}
-
-int
-ahd_lqrsvd16_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "LQRSVD16",
-           0x35, regvalue, cur_col, wrap));
-}
-
-int
-ahd_lqrsvd17_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "LQRSVD17",
-           0x36, regvalue, cur_col, wrap));
-}
-
-int
-ahd_cmdrsvd0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "CMDRSVD0",
-           0x37, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t LQCTL0_parse_table[] = {
-       { "LQ0INITGCLT",        0x03, 0x03 },
-       { "LQ0TARGCLT",         0x0c, 0x0c },
-       { "LQIINITGCLT",        0x30, 0x30 },
-       { "LQITARGCLT",         0xc0, 0xc0 }
-};
-
-int
-ahd_lqctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(LQCTL0_parse_table, 4, "LQCTL0",
-           0x38, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t LQCTL1_parse_table[] = {
+static const ahd_reg_parse_entry_t LQCTL1_parse_table[] = {
        { "ABORTPENDING",       0x01, 0x01 },
        { "SINGLECMD",          0x02, 0x02 },
        { "PCI2PCI",            0x04, 0x04 }
@@ -577,23 +449,7 @@ ahd_lqctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x38, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SCSBIST0_parse_table[] = {
-       { "OSBISTRUN",          0x01, 0x01 },
-       { "OSBISTDONE",         0x02, 0x02 },
-       { "OSBISTERR",          0x04, 0x04 },
-       { "GSBISTRUN",          0x10, 0x10 },
-       { "GSBISTDONE",         0x20, 0x20 },
-       { "GSBISTERR",          0x40, 0x40 }
-};
-
-int
-ahd_scsbist0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SCSBIST0_parse_table, 6, "SCSBIST0",
-           0x39, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t LQCTL2_parse_table[] = {
+static const ahd_reg_parse_entry_t LQCTL2_parse_table[] = {
        { "LQOPAUSE",           0x01, 0x01 },
        { "LQOTOIDLE",          0x02, 0x02 },
        { "LQOCONTINUE",        0x04, 0x04 },
@@ -611,20 +467,7 @@ ahd_lqctl2_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x39, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SCSBIST1_parse_table[] = {
-       { "NTBISTRUN",          0x01, 0x01 },
-       { "NTBISTDONE",         0x02, 0x02 },
-       { "NTBISTERR",          0x04, 0x04 }
-};
-
-int
-ahd_scsbist1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SCSBIST1_parse_table, 3, "SCSBIST1",
-           0x3a, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SCSISEQ0_parse_table[] = {
+static const ahd_reg_parse_entry_t SCSISEQ0_parse_table[] = {
        { "SCSIRSTO",           0x01, 0x01 },
        { "FORCEBUSFREE",       0x10, 0x10 },
        { "ENARBO",             0x20, 0x20 },
@@ -639,7 +482,7 @@ ahd_scsiseq0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x3a, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SCSISEQ1_parse_table[] = {
+static const ahd_reg_parse_entry_t SCSISEQ1_parse_table[] = {
        { "ALTSTIM",            0x01, 0x01 },
        { "ENAUTOATNP",         0x02, 0x02 },
        { "MANUALP",            0x0c, 0x0c },
@@ -655,7 +498,7 @@ ahd_scsiseq1_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x3b, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SXFRCTL0_parse_table[] = {
+static const ahd_reg_parse_entry_t SXFRCTL0_parse_table[] = {
        { "SPIOEN",             0x08, 0x08 },
        { "BIOSCANCELEN",       0x10, 0x10 },
        { "DFPEXP",             0x40, 0x40 },
@@ -669,21 +512,7 @@ ahd_sxfrctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x3c, regvalue, cur_col, wrap));
 }
 
-int
-ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "DLCOUNT",
-           0x3c, regvalue, cur_col, wrap));
-}
-
-int
-ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "BUSINITID",
-           0x3c, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SXFRCTL1_parse_table[] = {
+static const ahd_reg_parse_entry_t SXFRCTL1_parse_table[] = {
        { "STPWEN",             0x01, 0x01 },
        { "ACTNEGEN",           0x02, 0x02 },
        { "ENSTIMER",           0x04, 0x04 },
@@ -700,27 +529,7 @@ ahd_sxfrctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x3d, regvalue, cur_col, wrap));
 }
 
-int
-ahd_bustargid_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "BUSTARGID",
-           0x3e, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SXFRCTL2_parse_table[] = {
-       { "ASU",                0x07, 0x07 },
-       { "CMDDMAEN",           0x08, 0x08 },
-       { "AUTORSTDIS",         0x10, 0x10 }
-};
-
-int
-ahd_sxfrctl2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SXFRCTL2_parse_table, 3, "SXFRCTL2",
-           0x3e, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t DFFSTAT_parse_table[] = {
+static const ahd_reg_parse_entry_t DFFSTAT_parse_table[] = {
        { "CURRFIFO_0",         0x00, 0x03 },
        { "CURRFIFO_1",         0x01, 0x03 },
        { "CURRFIFO_NONE",      0x03, 0x03 },
@@ -736,7 +545,14 @@ ahd_dffstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x3f, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SCSISIGO_parse_table[] = {
+int
+ahd_multargid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+       return (ahd_print_register(NULL, 0, "MULTARGID",
+           0x40, regvalue, cur_col, wrap));
+}
+
+static const ahd_reg_parse_entry_t SCSISIGO_parse_table[] = {
        { "P_DATAOUT",          0x00, 0xe0 },
        { "P_DATAOUT_DT",       0x20, 0xe0 },
        { "P_DATAIN",           0x40, 0xe0 },
@@ -763,14 +579,7 @@ ahd_scsisigo_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x40, regvalue, cur_col, wrap));
 }
 
-int
-ahd_multargid_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "MULTARGID",
-           0x40, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SCSISIGI_parse_table[] = {
+static const ahd_reg_parse_entry_t SCSISIGI_parse_table[] = {
        { "P_DATAOUT",          0x00, 0xe0 },
        { "P_DATAOUT_DT",       0x20, 0xe0 },
        { "P_DATAIN",           0x40, 0xe0 },
@@ -797,7 +606,7 @@ ahd_scsisigi_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x41, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SCSIPHASE_parse_table[] = {
+static const ahd_reg_parse_entry_t SCSIPHASE_parse_table[] = {
        { "DATA_OUT_PHASE",     0x01, 0x03 },
        { "DATA_IN_PHASE",      0x02, 0x03 },
        { "DATA_PHASE_MASK",    0x03, 0x03 },
@@ -814,13 +623,6 @@ ahd_scsiphase_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x42, regvalue, cur_col, wrap));
 }
 
-int
-ahd_scsidat0_img_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "SCSIDAT0_IMG",
-           0x43, regvalue, cur_col, wrap));
-}
-
 int
 ahd_scsidat_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -835,7 +637,7 @@ ahd_scsibus_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x46, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t TARGIDIN_parse_table[] = {
+static const ahd_reg_parse_entry_t TARGIDIN_parse_table[] = {
        { "TARGID",             0x0f, 0x0f },
        { "CLKOUT",             0x80, 0x80 }
 };
@@ -847,7 +649,7 @@ ahd_targidin_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x48, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SELID_parse_table[] = {
+static const ahd_reg_parse_entry_t SELID_parse_table[] = {
        { "ONEBIT",             0x08, 0x08 },
        { "SELID_MASK",         0xf0, 0xf0 }
 };
@@ -859,7 +661,7 @@ ahd_selid_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x49, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t OPTIONMODE_parse_table[] = {
+static const ahd_reg_parse_entry_t OPTIONMODE_parse_table[] = {
        { "AUTO_MSGOUT_DE",     0x02, 0x02 },
        { "ENDGFORMCHK",        0x04, 0x04 },
        { "BUSFREEREV",         0x10, 0x10 },
@@ -876,7 +678,7 @@ ahd_optionmode_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x4a, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = {
+static const ahd_reg_parse_entry_t SBLKCTL_parse_table[] = {
        { "SELWIDE",            0x02, 0x02 },
        { "ENAB20",             0x04, 0x04 },
        { "ENAB40",             0x08, 0x08 },
@@ -891,24 +693,7 @@ ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x4a, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t CLRSINT0_parse_table[] = {
-       { "CLRARBDO",           0x01, 0x01 },
-       { "CLRSPIORDY",         0x02, 0x02 },
-       { "CLROVERRUN",         0x04, 0x04 },
-       { "CLRIOERR",           0x08, 0x08 },
-       { "CLRSELINGO",         0x10, 0x10 },
-       { "CLRSELDI",           0x20, 0x20 },
-       { "CLRSELDO",           0x40, 0x40 }
-};
-
-int
-ahd_clrsint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(CLRSINT0_parse_table, 7, "CLRSINT0",
-           0x4b, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SSTAT0_parse_table[] = {
+static const ahd_reg_parse_entry_t SSTAT0_parse_table[] = {
        { "ARBDO",              0x01, 0x01 },
        { "SPIORDY",            0x02, 0x02 },
        { "OVERRUN",            0x04, 0x04 },
@@ -926,7 +711,7 @@ ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x4b, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SIMODE0_parse_table[] = {
+static const ahd_reg_parse_entry_t SIMODE0_parse_table[] = {
        { "ENARBDO",            0x01, 0x01 },
        { "ENSPIORDY",          0x02, 0x02 },
        { "ENOVERRUN",          0x04, 0x04 },
@@ -943,24 +728,24 @@ ahd_simode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x4b, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t CLRSINT1_parse_table[] = {
-       { "CLRREQINIT",         0x01, 0x01 },
-       { "CLRSTRB2FAST",       0x02, 0x02 },
-       { "CLRSCSIPERR",        0x04, 0x04 },
-       { "CLRBUSFREE",         0x08, 0x08 },
-       { "CLRSCSIRSTI",        0x20, 0x20 },
-       { "CLRATNO",            0x40, 0x40 },
-       { "CLRSELTIMEO",        0x80, 0x80 }
+static const ahd_reg_parse_entry_t CLRSINT0_parse_table[] = {
+       { "CLRARBDO",           0x01, 0x01 },
+       { "CLRSPIORDY",         0x02, 0x02 },
+       { "CLROVERRUN",         0x04, 0x04 },
+       { "CLRIOERR",           0x08, 0x08 },
+       { "CLRSELINGO",         0x10, 0x10 },
+       { "CLRSELDI",           0x20, 0x20 },
+       { "CLRSELDO",           0x40, 0x40 }
 };
 
 int
-ahd_clrsint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_clrsint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-       return (ahd_print_register(CLRSINT1_parse_table, 7, "CLRSINT1",
-           0x4c, regvalue, cur_col, wrap));
+       return (ahd_print_register(CLRSINT0_parse_table, 7, "CLRSINT0",
+           0x4b, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SSTAT1_parse_table[] = {
+static const ahd_reg_parse_entry_t SSTAT1_parse_table[] = {
        { "REQINIT",            0x01, 0x01 },
        { "STRB2FAST",          0x02, 0x02 },
        { "SCSIPERR",           0x04, 0x04 },
@@ -978,7 +763,24 @@ ahd_sstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x4c, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SSTAT2_parse_table[] = {
+static const ahd_reg_parse_entry_t CLRSINT1_parse_table[] = {
+       { "CLRREQINIT",         0x01, 0x01 },
+       { "CLRSTRB2FAST",       0x02, 0x02 },
+       { "CLRSCSIPERR",        0x04, 0x04 },
+       { "CLRBUSFREE",         0x08, 0x08 },
+       { "CLRSCSIRSTI",        0x20, 0x20 },
+       { "CLRATNO",            0x40, 0x40 },
+       { "CLRSELTIMEO",        0x80, 0x80 }
+};
+
+int
+ahd_clrsint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+       return (ahd_print_register(CLRSINT1_parse_table, 7, "CLRSINT1",
+           0x4c, regvalue, cur_col, wrap));
+}
+
+static const ahd_reg_parse_entry_t SSTAT2_parse_table[] = {
        { "BUSFREE_LQO",        0x40, 0xc0 },
        { "BUSFREE_DFF0",       0x80, 0xc0 },
        { "BUSFREE_DFF1",       0xc0, 0xc0 },
@@ -998,20 +800,7 @@ ahd_sstat2_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x4d, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SIMODE2_parse_table[] = {
-       { "ENDMADONE",          0x01, 0x01 },
-       { "ENSDONE",            0x02, 0x02 },
-       { "ENWIDE_RES",         0x04, 0x04 }
-};
-
-int
-ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2",
-           0x4d, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t CLRSINT2_parse_table[] = {
+static const ahd_reg_parse_entry_t CLRSINT2_parse_table[] = {
        { "CLRDMADONE",         0x01, 0x01 },
        { "CLRSDONE",           0x02, 0x02 },
        { "CLRWIDE_RES",        0x04, 0x04 },
@@ -1025,7 +814,7 @@ ahd_clrsint2_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x4d, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t PERRDIAG_parse_table[] = {
+static const ahd_reg_parse_entry_t PERRDIAG_parse_table[] = {
        { "DTERR",              0x01, 0x01 },
        { "DGFORMERR",          0x02, 0x02 },
        { "CRCERR",             0x04, 0x04 },
@@ -1064,7 +853,7 @@ ahd_lqostate_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x4f, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t LQISTAT0_parse_table[] = {
+static const ahd_reg_parse_entry_t LQISTAT0_parse_table[] = {
        { "LQIATNCMD",          0x01, 0x01 },
        { "LQIATNLQ",           0x02, 0x02 },
        { "LQIBADLQT",          0x04, 0x04 },
@@ -1080,23 +869,7 @@ ahd_lqistat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x50, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t CLRLQIINT0_parse_table[] = {
-       { "CLRLQIATNCMD",       0x01, 0x01 },
-       { "CLRLQIATNLQ",        0x02, 0x02 },
-       { "CLRLQIBADLQT",       0x04, 0x04 },
-       { "CLRLQICRCT2",        0x08, 0x08 },
-       { "CLRLQICRCT1",        0x10, 0x10 },
-       { "CLRLQIATNQAS",       0x20, 0x20 }
-};
-
-int
-ahd_clrlqiint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(CLRLQIINT0_parse_table, 6, "CLRLQIINT0",
-           0x50, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t LQIMODE0_parse_table[] = {
+static const ahd_reg_parse_entry_t LQIMODE0_parse_table[] = {
        { "ENLQIATNCMD",        0x01, 0x01 },
        { "ENLQIATNLQ",         0x02, 0x02 },
        { "ENLQIBADLQT",        0x04, 0x04 },
@@ -1112,7 +885,23 @@ ahd_lqimode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x50, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t LQIMODE1_parse_table[] = {
+static const ahd_reg_parse_entry_t CLRLQIINT0_parse_table[] = {
+       { "CLRLQIATNCMD",       0x01, 0x01 },
+       { "CLRLQIATNLQ",        0x02, 0x02 },
+       { "CLRLQIBADLQT",       0x04, 0x04 },
+       { "CLRLQICRCT2",        0x08, 0x08 },
+       { "CLRLQICRCT1",        0x10, 0x10 },
+       { "CLRLQIATNQAS",       0x20, 0x20 }
+};
+
+int
+ahd_clrlqiint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+       return (ahd_print_register(CLRLQIINT0_parse_table, 6, "CLRLQIINT0",
+           0x50, regvalue, cur_col, wrap));
+}
+
+static const ahd_reg_parse_entry_t LQIMODE1_parse_table[] = {
        { "ENLQIOVERI_NLQ",     0x01, 0x01 },
        { "ENLQIOVERI_LQ",      0x02, 0x02 },
        { "ENLQIBADLQI",        0x04, 0x04 },
@@ -1130,7 +919,7 @@ ahd_lqimode1_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x51, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t LQISTAT1_parse_table[] = {
+static const ahd_reg_parse_entry_t LQISTAT1_parse_table[] = {
        { "LQIOVERI_NLQ",       0x01, 0x01 },
        { "LQIOVERI_LQ",        0x02, 0x02 },
        { "LQIBADLQI",          0x04, 0x04 },
@@ -1148,7 +937,7 @@ ahd_lqistat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x51, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t CLRLQIINT1_parse_table[] = {
+static const ahd_reg_parse_entry_t CLRLQIINT1_parse_table[] = {
        { "CLRLQIOVERI_NLQ",    0x01, 0x01 },
        { "CLRLQIOVERI_LQ",     0x02, 0x02 },
        { "CLRLQIBADLQI",       0x04, 0x04 },
@@ -1166,7 +955,7 @@ ahd_clrlqiint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x51, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t LQISTAT2_parse_table[] = {
+static const ahd_reg_parse_entry_t LQISTAT2_parse_table[] = {
        { "LQIGSAVAIL",         0x01, 0x01 },
        { "LQISTOPCMD",         0x02, 0x02 },
        { "LQISTOPLQ",          0x04, 0x04 },
@@ -1184,7 +973,7 @@ ahd_lqistat2_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x52, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SSTAT3_parse_table[] = {
+static const ahd_reg_parse_entry_t SSTAT3_parse_table[] = {
        { "OSRAMPERR",          0x01, 0x01 },
        { "NTRAMPERR",          0x02, 0x02 }
 };
@@ -1196,7 +985,7 @@ ahd_sstat3_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x53, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SIMODE3_parse_table[] = {
+static const ahd_reg_parse_entry_t SIMODE3_parse_table[] = {
        { "ENOSRAMPERR",        0x01, 0x01 },
        { "ENNTRAMPERR",        0x02, 0x02 }
 };
@@ -1208,7 +997,7 @@ ahd_simode3_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x53, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t CLRSINT3_parse_table[] = {
+static const ahd_reg_parse_entry_t CLRSINT3_parse_table[] = {
        { "CLROSRAMPERR",       0x01, 0x01 },
        { "CLRNTRAMPERR",       0x02, 0x02 }
 };
@@ -1220,7 +1009,7 @@ ahd_clrsint3_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x53, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t LQOSTAT0_parse_table[] = {
+static const ahd_reg_parse_entry_t LQOSTAT0_parse_table[] = {
        { "LQOTCRC",            0x01, 0x01 },
        { "LQOATNPKT",          0x02, 0x02 },
        { "LQOATNLQ",           0x04, 0x04 },
@@ -1235,7 +1024,7 @@ ahd_lqostat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x54, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t CLRLQOINT0_parse_table[] = {
+static const ahd_reg_parse_entry_t CLRLQOINT0_parse_table[] = {
        { "CLRLQOTCRC",         0x01, 0x01 },
        { "CLRLQOATNPKT",       0x02, 0x02 },
        { "CLRLQOATNLQ",        0x04, 0x04 },
@@ -1250,7 +1039,7 @@ ahd_clrlqoint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x54, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = {
+static const ahd_reg_parse_entry_t LQOMODE0_parse_table[] = {
        { "ENLQOTCRC",          0x01, 0x01 },
        { "ENLQOATNPKT",        0x02, 0x02 },
        { "ENLQOATNLQ",         0x04, 0x04 },
@@ -1265,7 +1054,7 @@ ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x54, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = {
+static const ahd_reg_parse_entry_t LQOMODE1_parse_table[] = {
        { "ENLQOPHACHGINPKT",   0x01, 0x01 },
        { "ENLQOBUSFREE",       0x02, 0x02 },
        { "ENLQOBADQAS",        0x04, 0x04 },
@@ -1280,7 +1069,7 @@ ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x55, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t LQOSTAT1_parse_table[] = {
+static const ahd_reg_parse_entry_t LQOSTAT1_parse_table[] = {
        { "LQOPHACHGINPKT",     0x01, 0x01 },
        { "LQOBUSFREE",         0x02, 0x02 },
        { "LQOBADQAS",          0x04, 0x04 },
@@ -1295,7 +1084,7 @@ ahd_lqostat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x55, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t CLRLQOINT1_parse_table[] = {
+static const ahd_reg_parse_entry_t CLRLQOINT1_parse_table[] = {
        { "CLRLQOPHACHGINPKT",  0x01, 0x01 },
        { "CLRLQOBUSFREE",      0x02, 0x02 },
        { "CLRLQOBADQAS",       0x04, 0x04 },
@@ -1310,7 +1099,7 @@ ahd_clrlqoint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x55, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t LQOSTAT2_parse_table[] = {
+static const ahd_reg_parse_entry_t LQOSTAT2_parse_table[] = {
        { "LQOSTOP0",           0x01, 0x01 },
        { "LQOPHACHGOUTPKT",    0x02, 0x02 },
        { "LQOWAITFIFO",        0x10, 0x10 },
@@ -1331,7 +1120,7 @@ ahd_os_space_cnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x56, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SIMODE1_parse_table[] = {
+static const ahd_reg_parse_entry_t SIMODE1_parse_table[] = {
        { "ENREQINIT",          0x01, 0x01 },
        { "ENSTRB2FAST",        0x02, 0x02 },
        { "ENSCSIPERR",         0x04, 0x04 },
@@ -1356,7 +1145,7 @@ ahd_gsfifo_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x58, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t DFFSXFRCTL_parse_table[] = {
+static const ahd_reg_parse_entry_t DFFSXFRCTL_parse_table[] = {
        { "RSTCHN",             0x01, 0x01 },
        { "CLRCHN",             0x02, 0x02 },
        { "CLRSHCNT",           0x04, 0x04 },
@@ -1370,15 +1159,17 @@ ahd_dffsxfrctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x5a, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t LQOSCSCTL_parse_table[] = {
+static const ahd_reg_parse_entry_t LQOSCSCTL_parse_table[] = {
        { "LQONOCHKOVER",       0x01, 0x01 },
+       { "LQONOHOLDLACK",      0x02, 0x02 },
+       { "LQOBUSETDLY",        0x40, 0x40 },
        { "LQOH2A_VERSION",     0x80, 0x80 }
 };
 
 int
 ahd_lqoscsctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-       return (ahd_print_register(LQOSCSCTL_parse_table, 2, "LQOSCSCTL",
+       return (ahd_print_register(LQOSCSCTL_parse_table, 4, "LQOSCSCTL",
            0x5a, regvalue, cur_col, wrap));
 }
 
@@ -1389,7 +1180,7 @@ ahd_nextscb_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x5a, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t CLRSEQINTSRC_parse_table[] = {
+static const ahd_reg_parse_entry_t CLRSEQINTSRC_parse_table[] = {
        { "CLRCFG4TCMD",        0x01, 0x01 },
        { "CLRCFG4ICMD",        0x02, 0x02 },
        { "CLRCFG4TSTAT",       0x04, 0x04 },
@@ -1406,7 +1197,7 @@ ahd_clrseqintsrc_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x5b, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SEQINTSRC_parse_table[] = {
+static const ahd_reg_parse_entry_t SEQINTSRC_parse_table[] = {
        { "CFG4TCMD",           0x01, 0x01 },
        { "CFG4ICMD",           0x02, 0x02 },
        { "CFG4TSTAT",          0x04, 0x04 },
@@ -1423,14 +1214,7 @@ ahd_seqintsrc_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x5b, regvalue, cur_col, wrap));
 }
 
-int
-ahd_currscb_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "CURRSCB",
-           0x5c, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SEQIMODE_parse_table[] = {
+static const ahd_reg_parse_entry_t SEQIMODE_parse_table[] = {
        { "ENCFG4TCMD",         0x01, 0x01 },
        { "ENCFG4ICMD",         0x02, 0x02 },
        { "ENCFG4TSTAT",        0x04, 0x04 },
@@ -1447,7 +1231,14 @@ ahd_seqimode_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x5c, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t MDFFSTAT_parse_table[] = {
+int
+ahd_currscb_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+       return (ahd_print_register(NULL, 0, "CURRSCB",
+           0x5c, regvalue, cur_col, wrap));
+}
+
+static const ahd_reg_parse_entry_t MDFFSTAT_parse_table[] = {
        { "FIFOFREE",           0x01, 0x01 },
        { "DATAINFIFO",         0x02, 0x02 },
        { "DLZERO",             0x04, 0x04 },
@@ -1464,24 +1255,6 @@ ahd_mdffstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x5d, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t CRCCONTROL_parse_table[] = {
-       { "CRCVALCHKEN",        0x40, 0x40 }
-};
-
-int
-ahd_crccontrol_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(CRCCONTROL_parse_table, 1, "CRCCONTROL",
-           0x5d, regvalue, cur_col, wrap));
-}
-
-int
-ahd_dfftag_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "DFFTAG",
-           0x5e, regvalue, cur_col, wrap));
-}
-
 int
 ahd_lastscb_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -1489,31 +1262,6 @@ ahd_lastscb_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x5e, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SCSITEST_parse_table[] = {
-       { "SEL_TXPLL_DEBUG",    0x04, 0x04 },
-       { "CNTRTEST",           0x08, 0x08 }
-};
-
-int
-ahd_scsitest_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SCSITEST_parse_table, 2, "SCSITEST",
-           0x5e, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t IOPDNCTL_parse_table[] = {
-       { "PDN_DIFFSENSE",      0x01, 0x01 },
-       { "PDN_IDIST",          0x04, 0x04 },
-       { "DISABLE_OE",         0x80, 0x80 }
-};
-
-int
-ahd_iopdnctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(IOPDNCTL_parse_table, 3, "IOPDNCTL",
-           0x5f, regvalue, cur_col, wrap));
-}
-
 int
 ahd_shaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -1528,13 +1276,6 @@ ahd_negoaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x60, regvalue, cur_col, wrap));
 }
 
-int
-ahd_dgrpcrci_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "DGRPCRCI",
-           0x60, regvalue, cur_col, wrap));
-}
-
 int
 ahd_negperiod_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -1543,20 +1284,13 @@ ahd_negperiod_print(u_int regvalue, u_int *cur_col, u_int wrap)
 }
 
 int
-ahd_packcrci_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "PACKCRCI",
-           0x62, regvalue, cur_col, wrap));
-}
-
-int
-ahd_negoffset_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_negoffset_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
        return (ahd_print_register(NULL, 0, "NEGOFFSET",
            0x62, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t NEGPPROPTS_parse_table[] = {
+static const ahd_reg_parse_entry_t NEGPPROPTS_parse_table[] = {
        { "PPROPT_IUT",         0x01, 0x01 },
        { "PPROPT_DT",          0x02, 0x02 },
        { "PPROPT_QAS",         0x04, 0x04 },
@@ -1570,7 +1304,7 @@ ahd_negppropts_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x63, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t NEGCONOPTS_parse_table[] = {
+static const ahd_reg_parse_entry_t NEGCONOPTS_parse_table[] = {
        { "WIDEXFER",           0x01, 0x01 },
        { "ENAUTOATNO",         0x02, 0x02 },
        { "ENAUTOATNI",         0x04, 0x04 },
@@ -1601,20 +1335,21 @@ ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x66, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SCSCHKN_parse_table[] = {
+static const ahd_reg_parse_entry_t SCSCHKN_parse_table[] = {
        { "LSTSGCLRDIS",        0x01, 0x01 },
        { "SHVALIDSTDIS",       0x02, 0x02 },
        { "DFFACTCLR",          0x04, 0x04 },
        { "SDONEMSKDIS",        0x08, 0x08 },
        { "WIDERESEN",          0x10, 0x10 },
        { "CURRFIFODEF",        0x20, 0x20 },
-       { "STSELSKIDDIS",       0x40, 0x40 }
+       { "STSELSKIDDIS",       0x40, 0x40 },
+       { "BIDICHKDIS",         0x80, 0x80 }
 };
 
 int
 ahd_scschkn_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-       return (ahd_print_register(SCSCHKN_parse_table, 7, "SCSCHKN",
+       return (ahd_print_register(SCSCHKN_parse_table, 8, "SCSCHKN",
            0x66, regvalue, cur_col, wrap));
 }
 
@@ -1625,23 +1360,6 @@ ahd_iownid_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x67, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t PLL960CTL0_parse_table[] = {
-       { "PLL_ENFBM",          0x01, 0x01 },
-       { "PLL_DLPF",           0x02, 0x02 },
-       { "PLL_ENLPF",          0x04, 0x04 },
-       { "PLL_ENLUD",          0x08, 0x08 },
-       { "PLL_NS",             0x30, 0x30 },
-       { "PLL_PWDN",           0x40, 0x40 },
-       { "PLL_VCOSEL",         0x80, 0x80 }
-};
-
-int
-ahd_pll960ctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(PLL960CTL0_parse_table, 7, "PLL960CTL0",
-           0x68, regvalue, cur_col, wrap));
-}
-
 int
 ahd_shcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -1656,33 +1374,6 @@ ahd_townid_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x69, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t PLL960CTL1_parse_table[] = {
-       { "PLL_RST",            0x01, 0x01 },
-       { "PLL_CNTCLR",         0x40, 0x40 },
-       { "PLL_CNTEN",          0x80, 0x80 }
-};
-
-int
-ahd_pll960ctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(PLL960CTL1_parse_table, 3, "PLL960CTL1",
-           0x69, regvalue, cur_col, wrap));
-}
-
-int
-ahd_pll960cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "PLL960CNT0",
-           0x6a, regvalue, cur_col, wrap));
-}
-
-int
-ahd_xsig_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "XSIG",
-           0x6a, regvalue, cur_col, wrap));
-}
-
 int
 ahd_seloid_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -1690,57 +1381,6 @@ ahd_seloid_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x6b, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t PLL400CTL0_parse_table[] = {
-       { "PLL_ENFBM",          0x01, 0x01 },
-       { "PLL_DLPF",           0x02, 0x02 },
-       { "PLL_ENLPF",          0x04, 0x04 },
-       { "PLL_ENLUD",          0x08, 0x08 },
-       { "PLL_NS",             0x30, 0x30 },
-       { "PLL_PWDN",           0x40, 0x40 },
-       { "PLL_VCOSEL",         0x80, 0x80 }
-};
-
-int
-ahd_pll400ctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(PLL400CTL0_parse_table, 7, "PLL400CTL0",
-           0x6c, regvalue, cur_col, wrap));
-}
-
-int
-ahd_fairness_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "FAIRNESS",
-           0x6c, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t PLL400CTL1_parse_table[] = {
-       { "PLL_RST",            0x01, 0x01 },
-       { "PLL_CNTCLR",         0x40, 0x40 },
-       { "PLL_CNTEN",          0x80, 0x80 }
-};
-
-int
-ahd_pll400ctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(PLL400CTL1_parse_table, 3, "PLL400CTL1",
-           0x6d, regvalue, cur_col, wrap));
-}
-
-int
-ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "UNFAIRNESS",
-           0x6e, regvalue, cur_col, wrap));
-}
-
-int
-ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "PLL400CNT0",
-           0x6e, regvalue, cur_col, wrap));
-}
-
 int
 ahd_haddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -1748,31 +1388,6 @@ ahd_haddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x70, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t PLLDELAY_parse_table[] = {
-       { "SPLIT_DROP_REQ",     0x80, 0x80 }
-};
-
-int
-ahd_plldelay_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(PLLDELAY_parse_table, 1, "PLLDELAY",
-           0x70, regvalue, cur_col, wrap));
-}
-
-int
-ahd_hodmaadr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "HODMAADR",
-           0x70, regvalue, cur_col, wrap));
-}
-
-int
-ahd_hodmacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "HODMACNT",
-           0x78, regvalue, cur_col, wrap));
-}
-
 int
 ahd_hcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -1781,10 +1396,10 @@ ahd_hcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
 }
 
 int
-ahd_hodmaen_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-       return (ahd_print_register(NULL, 0, "HODMAEN",
-           0x7a, regvalue, cur_col, wrap));
+       return (ahd_print_register(NULL, 0, "SGHADDR",
+           0x7c, regvalue, cur_col, wrap));
 }
 
 int
@@ -1795,10 +1410,10 @@ ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 }
 
 int
-ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-       return (ahd_print_register(NULL, 0, "SGHADDR",
-           0x7c, regvalue, cur_col, wrap));
+       return (ahd_print_register(NULL, 0, "SGHCNT",
+           0x84, regvalue, cur_col, wrap));
 }
 
 int
@@ -1808,14 +1423,7 @@ ahd_scbhcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x84, regvalue, cur_col, wrap));
 }
 
-int
-ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "SGHCNT",
-           0x84, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t DFF_THRSH_parse_table[] = {
+static const ahd_reg_parse_entry_t DFF_THRSH_parse_table[] = {
        { "WR_DFTHRSH_MIN",     0x00, 0x70 },
        { "RD_DFTHRSH_MIN",     0x00, 0x07 },
        { "RD_DFTHRSH_25",      0x01, 0x07 },
@@ -1843,209 +1451,7 @@ ahd_dff_thrsh_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x88, regvalue, cur_col, wrap));
 }
 
-int
-ahd_romaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "ROMADDR",
-           0x8a, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t ROMCNTRL_parse_table[] = {
-       { "RDY",                0x01, 0x01 },
-       { "REPEAT",             0x02, 0x02 },
-       { "ROMSPD",             0x18, 0x18 },
-       { "ROMOP",              0xe0, 0xe0 }
-};
-
-int
-ahd_romcntrl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(ROMCNTRL_parse_table, 4, "ROMCNTRL",
-           0x8d, regvalue, cur_col, wrap));
-}
-
-int
-ahd_romdata_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "ROMDATA",
-           0x8e, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t CMCRXMSG0_parse_table[] = {
-       { "CFNUM",              0x07, 0x07 },
-       { "CDNUM",              0xf8, 0xf8 }
-};
-
-int
-ahd_cmcrxmsg0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(CMCRXMSG0_parse_table, 2, "CMCRXMSG0",
-           0x90, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t ROENABLE_parse_table[] = {
-       { "DCH0ROEN",           0x01, 0x01 },
-       { "DCH1ROEN",           0x02, 0x02 },
-       { "SGROEN",             0x04, 0x04 },
-       { "CMCROEN",            0x08, 0x08 },
-       { "OVLYROEN",           0x10, 0x10 },
-       { "MSIROEN",            0x20, 0x20 }
-};
-
-int
-ahd_roenable_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(ROENABLE_parse_table, 6, "ROENABLE",
-           0x90, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t OVLYRXMSG0_parse_table[] = {
-       { "CFNUM",              0x07, 0x07 },
-       { "CDNUM",              0xf8, 0xf8 }
-};
-
-int
-ahd_ovlyrxmsg0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(OVLYRXMSG0_parse_table, 2, "OVLYRXMSG0",
-           0x90, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t DCHRXMSG0_parse_table[] = {
-       { "CFNUM",              0x07, 0x07 },
-       { "CDNUM",              0xf8, 0xf8 }
-};
-
-int
-ahd_dchrxmsg0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(DCHRXMSG0_parse_table, 2, "DCHRXMSG0",
-           0x90, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t OVLYRXMSG1_parse_table[] = {
-       { "CBNUM",              0xff, 0xff }
-};
-
-int
-ahd_ovlyrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(OVLYRXMSG1_parse_table, 1, "OVLYRXMSG1",
-           0x91, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t NSENABLE_parse_table[] = {
-       { "DCH0NSEN",           0x01, 0x01 },
-       { "DCH1NSEN",           0x02, 0x02 },
-       { "SGNSEN",             0x04, 0x04 },
-       { "CMCNSEN",            0x08, 0x08 },
-       { "OVLYNSEN",           0x10, 0x10 },
-       { "MSINSEN",            0x20, 0x20 }
-};
-
-int
-ahd_nsenable_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NSENABLE_parse_table, 6, "NSENABLE",
-           0x91, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t CMCRXMSG1_parse_table[] = {
-       { "CBNUM",              0xff, 0xff }
-};
-
-int
-ahd_cmcrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(CMCRXMSG1_parse_table, 1, "CMCRXMSG1",
-           0x91, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = {
-       { "CBNUM",              0xff, 0xff }
-};
-
-int
-ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1",
-           0x91, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t DCHRXMSG2_parse_table[] = {
-       { "MINDEX",             0xff, 0xff }
-};
-
-int
-ahd_dchrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(DCHRXMSG2_parse_table, 1, "DCHRXMSG2",
-           0x92, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t CMCRXMSG2_parse_table[] = {
-       { "MINDEX",             0xff, 0xff }
-};
-
-int
-ahd_cmcrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(CMCRXMSG2_parse_table, 1, "CMCRXMSG2",
-           0x92, regvalue, cur_col, wrap));
-}
-
-int
-ahd_ost_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "OST",
-           0x92, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = {
-       { "MINDEX",             0xff, 0xff }
-};
-
-int
-ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2",
-           0x92, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t DCHRXMSG3_parse_table[] = {
-       { "MCLASS",             0x0f, 0x0f }
-};
-
-int
-ahd_dchrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(DCHRXMSG3_parse_table, 1, "DCHRXMSG3",
-           0x93, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = {
-       { "MCLASS",             0x0f, 0x0f }
-};
-
-int
-ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3",
-           0x93, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t CMCRXMSG3_parse_table[] = {
-       { "MCLASS",             0x0f, 0x0f }
-};
-
-int
-ahd_cmcrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(CMCRXMSG3_parse_table, 1, "CMCRXMSG3",
-           0x93, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t PCIXCTL_parse_table[] = {
+static const ahd_reg_parse_entry_t PCIXCTL_parse_table[] = {
        { "CMPABCDIS",          0x01, 0x01 },
        { "TSCSERREN",          0x02, 0x02 },
        { "SRSPDPEEN",          0x04, 0x04 },
@@ -2062,46 +1468,7 @@ ahd_pcixctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x93, regvalue, cur_col, wrap));
 }
 
-int
-ahd_ovlyseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "OVLYSEQBCNT",
-           0x94, regvalue, cur_col, wrap));
-}
-
-int
-ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "DCHSEQBCNT",
-           0x94, regvalue, cur_col, wrap));
-}
-
-int
-ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "CMCSEQBCNT",
-           0x94, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t CMCSPLTSTAT0_parse_table[] = {
-       { "RXSPLTRSP",          0x01, 0x01 },
-       { "RXSCEMSG",           0x02, 0x02 },
-       { "RXOVRUN",            0x04, 0x04 },
-       { "CNTNOTCMPLT",        0x08, 0x08 },
-       { "SCDATBUCKET",        0x10, 0x10 },
-       { "SCADERR",            0x20, 0x20 },
-       { "SCBCERR",            0x40, 0x40 },
-       { "STAETERM",           0x80, 0x80 }
-};
-
-int
-ahd_cmcspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(CMCSPLTSTAT0_parse_table, 8, "CMCSPLTSTAT0",
-           0x96, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = {
+static const ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = {
        { "RXSPLTRSP",          0x01, 0x01 },
        { "RXSCEMSG",           0x02, 0x02 },
        { "RXOVRUN",            0x04, 0x04 },
@@ -2119,190 +1486,18 @@ ahd_dchspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x96, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = {
-       { "RXSPLTRSP",          0x01, 0x01 },
-       { "RXSCEMSG",           0x02, 0x02 },
-       { "RXOVRUN",            0x04, 0x04 },
-       { "CNTNOTCMPLT",        0x08, 0x08 },
-       { "SCDATBUCKET",        0x10, 0x10 },
-       { "SCADERR",            0x20, 0x20 },
-       { "SCBCERR",            0x40, 0x40 },
-       { "STAETERM",           0x80, 0x80 }
-};
-
-int
-ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0",
-           0x96, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t CMCSPLTSTAT1_parse_table[] = {
-       { "RXDATABUCKET",       0x01, 0x01 }
-};
-
-int
-ahd_cmcspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(CMCSPLTSTAT1_parse_table, 1, "CMCSPLTSTAT1",
-           0x97, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t OVLYSPLTSTAT1_parse_table[] = {
-       { "RXDATABUCKET",       0x01, 0x01 }
-};
-
-int
-ahd_ovlyspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(OVLYSPLTSTAT1_parse_table, 1, "OVLYSPLTSTAT1",
-           0x97, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = {
+static const ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = {
        { "RXDATABUCKET",       0x01, 0x01 }
 };
 
 int
 ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-       return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1",
-           0x97, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SGRXMSG0_parse_table[] = {
-       { "CFNUM",              0x07, 0x07 },
-       { "CDNUM",              0xf8, 0xf8 }
-};
-
-int
-ahd_sgrxmsg0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SGRXMSG0_parse_table, 2, "SGRXMSG0",
-           0x98, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SLVSPLTOUTADR0_parse_table[] = {
-       { "LOWER_ADDR",         0x7f, 0x7f }
-};
-
-int
-ahd_slvspltoutadr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SLVSPLTOUTADR0_parse_table, 1, "SLVSPLTOUTADR0",
-           0x98, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SGRXMSG1_parse_table[] = {
-       { "CBNUM",              0xff, 0xff }
-};
-
-int
-ahd_sgrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SGRXMSG1_parse_table, 1, "SGRXMSG1",
-           0x99, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SLVSPLTOUTADR1_parse_table[] = {
-       { "REQ_FNUM",           0x07, 0x07 },
-       { "REQ_DNUM",           0xf8, 0xf8 }
-};
-
-int
-ahd_slvspltoutadr1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SLVSPLTOUTADR1_parse_table, 2, "SLVSPLTOUTADR1",
-           0x99, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SGRXMSG2_parse_table[] = {
-       { "MINDEX",             0xff, 0xff }
-};
-
-int
-ahd_sgrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SGRXMSG2_parse_table, 1, "SGRXMSG2",
-           0x9a, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SLVSPLTOUTADR2_parse_table[] = {
-       { "REQ_BNUM",           0xff, 0xff }
-};
-
-int
-ahd_slvspltoutadr2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SLVSPLTOUTADR2_parse_table, 1, "SLVSPLTOUTADR2",
-           0x9a, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SGRXMSG3_parse_table[] = {
-       { "MCLASS",             0x0f, 0x0f }
-};
-
-int
-ahd_sgrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SGRXMSG3_parse_table, 1, "SGRXMSG3",
-           0x9b, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SLVSPLTOUTADR3_parse_table[] = {
-       { "RLXORD",             0x10, 0x10 },
-       { "TAG_NUM",            0x1f, 0x1f }
-};
-
-int
-ahd_slvspltoutadr3_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SLVSPLTOUTADR3_parse_table, 2, "SLVSPLTOUTADR3",
-           0x9b, regvalue, cur_col, wrap));
-}
-
-int
-ahd_sgseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "SGSEQBCNT",
-           0x9c, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SLVSPLTOUTATTR0_parse_table[] = {
-       { "LOWER_BCNT",         0xff, 0xff }
-};
-
-int
-ahd_slvspltoutattr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SLVSPLTOUTATTR0_parse_table, 1, "SLVSPLTOUTATTR0",
-           0x9c, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SLVSPLTOUTATTR1_parse_table[] = {
-       { "CMPLT_FNUM",         0x07, 0x07 },
-       { "CMPLT_DNUM",         0xf8, 0xf8 }
-};
-
-int
-ahd_slvspltoutattr1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SLVSPLTOUTATTR1_parse_table, 2, "SLVSPLTOUTATTR1",
-           0x9d, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SLVSPLTOUTATTR2_parse_table[] = {
-       { "CMPLT_BNUM",         0xff, 0xff }
-};
-
-int
-ahd_slvspltoutattr2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SLVSPLTOUTATTR2_parse_table, 1, "SLVSPLTOUTATTR2",
-           0x9e, regvalue, cur_col, wrap));
+       return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1",
+           0x97, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SGSPLTSTAT0_parse_table[] = {
+static const ahd_reg_parse_entry_t SGSPLTSTAT0_parse_table[] = {
        { "RXSPLTRSP",          0x01, 0x01 },
        { "RXSCEMSG",           0x02, 0x02 },
        { "RXOVRUN",            0x04, 0x04 },
@@ -2320,7 +1515,7 @@ ahd_sgspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x9e, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = {
+static const ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = {
        { "RXDATABUCKET",       0x01, 0x01 }
 };
 
@@ -2331,19 +1526,7 @@ ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x9f, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SFUNCT_parse_table[] = {
-       { "TEST_NUM",           0x0f, 0x0f },
-       { "TEST_GROUP",         0xf0, 0xf0 }
-};
-
-int
-ahd_sfunct_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SFUNCT_parse_table, 2, "SFUNCT",
-           0x9f, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t DF0PCISTAT_parse_table[] = {
+static const ahd_reg_parse_entry_t DF0PCISTAT_parse_table[] = {
        { "DPR",                0x01, 0x01 },
        { "TWATERR",            0x02, 0x02 },
        { "RDPERR",             0x04, 0x04 },
@@ -2368,83 +1551,6 @@ ahd_reg0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xa0, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t DF1PCISTAT_parse_table[] = {
-       { "DPR",                0x01, 0x01 },
-       { "TWATERR",            0x02, 0x02 },
-       { "RDPERR",             0x04, 0x04 },
-       { "SCAAPERR",           0x08, 0x08 },
-       { "RTA",                0x10, 0x10 },
-       { "RMA",                0x20, 0x20 },
-       { "SSE",                0x40, 0x40 },
-       { "DPE",                0x80, 0x80 }
-};
-
-int
-ahd_df1pcistat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(DF1PCISTAT_parse_table, 8, "DF1PCISTAT",
-           0xa1, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SGPCISTAT_parse_table[] = {
-       { "DPR",                0x01, 0x01 },
-       { "RDPERR",             0x04, 0x04 },
-       { "SCAAPERR",           0x08, 0x08 },
-       { "RTA",                0x10, 0x10 },
-       { "RMA",                0x20, 0x20 },
-       { "SSE",                0x40, 0x40 },
-       { "DPE",                0x80, 0x80 }
-};
-
-int
-ahd_sgpcistat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SGPCISTAT_parse_table, 7, "SGPCISTAT",
-           0xa2, regvalue, cur_col, wrap));
-}
-
-int
-ahd_reg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "REG1",
-           0xa2, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t CMCPCISTAT_parse_table[] = {
-       { "DPR",                0x01, 0x01 },
-       { "TWATERR",            0x02, 0x02 },
-       { "RDPERR",             0x04, 0x04 },
-       { "SCAAPERR",           0x08, 0x08 },
-       { "RTA",                0x10, 0x10 },
-       { "RMA",                0x20, 0x20 },
-       { "SSE",                0x40, 0x40 },
-       { "DPE",                0x80, 0x80 }
-};
-
-int
-ahd_cmcpcistat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(CMCPCISTAT_parse_table, 8, "CMCPCISTAT",
-           0xa3, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t OVLYPCISTAT_parse_table[] = {
-       { "DPR",                0x01, 0x01 },
-       { "RDPERR",             0x04, 0x04 },
-       { "SCAAPERR",           0x08, 0x08 },
-       { "RTA",                0x10, 0x10 },
-       { "RMA",                0x20, 0x20 },
-       { "SSE",                0x40, 0x40 },
-       { "DPE",                0x80, 0x80 }
-};
-
-int
-ahd_ovlypcistat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(OVLYPCISTAT_parse_table, 7, "OVLYPCISTAT",
-           0xa4, regvalue, cur_col, wrap));
-}
-
 int
 ahd_reg_isr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -2452,7 +1558,7 @@ ahd_reg_isr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xa4, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SG_STATE_parse_table[] = {
+static const ahd_reg_parse_entry_t SG_STATE_parse_table[] = {
        { "SEGS_AVAIL",         0x01, 0x01 },
        { "LOADING_NEEDED",     0x02, 0x02 },
        { "FETCH_INPROG",       0x04, 0x04 }
@@ -2465,23 +1571,7 @@ ahd_sg_state_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xa6, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t MSIPCISTAT_parse_table[] = {
-       { "DPR",                0x01, 0x01 },
-       { "TWATERR",            0x02, 0x02 },
-       { "CLRPENDMSI",         0x08, 0x08 },
-       { "RTA",                0x10, 0x10 },
-       { "RMA",                0x20, 0x20 },
-       { "SSE",                0x40, 0x40 }
-};
-
-int
-ahd_msipcistat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(MSIPCISTAT_parse_table, 6, "MSIPCISTAT",
-           0xa6, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t TARGPCISTAT_parse_table[] = {
+static const ahd_reg_parse_entry_t TARGPCISTAT_parse_table[] = {
        { "TWATERR",            0x02, 0x02 },
        { "STA",                0x08, 0x08 },
        { "SSE",                0x40, 0x40 },
@@ -2495,13 +1585,6 @@ ahd_targpcistat_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xa7, regvalue, cur_col, wrap));
 }
 
-int
-ahd_data_count_odd_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "DATA_COUNT_ODD",
-           0xa7, regvalue, cur_col, wrap));
-}
-
 int
 ahd_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -2509,14 +1592,7 @@ ahd_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xa8, regvalue, cur_col, wrap));
 }
 
-int
-ahd_ccscbacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "CCSCBACNT",
-           0xab, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SCBAUTOPTR_parse_table[] = {
+static const ahd_reg_parse_entry_t SCBAUTOPTR_parse_table[] = {
        { "SCBPTR_OFF",         0x07, 0x07 },
        { "SCBPTR_ADDR",        0x38, 0x38 },
        { "AUSCBPTR_EN",        0x80, 0x80 }
@@ -2536,13 +1612,6 @@ ahd_ccsgaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xac, regvalue, cur_col, wrap));
 }
 
-int
-ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "CCSCBADR_BK",
-           0xac, regvalue, cur_col, wrap));
-}
-
 int
 ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -2550,23 +1619,7 @@ ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xac, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t CMC_RAMBIST_parse_table[] = {
-       { "CMC_BUFFER_BIST_EN", 0x01, 0x01 },
-       { "CMC_BUFFER_BIST_FAIL",0x02, 0x02 },
-       { "SG_BIST_EN",         0x10, 0x10 },
-       { "SG_BIST_FAIL",       0x20, 0x20 },
-       { "SCBRAMBIST_FAIL",    0x40, 0x40 },
-       { "SG_ELEMENT_SIZE",    0x80, 0x80 }
-};
-
-int
-ahd_cmc_rambist_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(CMC_RAMBIST_parse_table, 6, "CMC_RAMBIST",
-           0xad, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t CCSCBCTL_parse_table[] = {
+static const ahd_reg_parse_entry_t CCSCBCTL_parse_table[] = {
        { "CCSCBRESET",         0x01, 0x01 },
        { "CCSCBDIR",           0x04, 0x04 },
        { "CCSCBEN",            0x08, 0x08 },
@@ -2582,7 +1635,7 @@ ahd_ccscbctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xad, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = {
+static const ahd_reg_parse_entry_t CCSGCTL_parse_table[] = {
        { "CCSGRESET",          0x01, 0x01 },
        { "SG_FETCH_REQ",       0x02, 0x02 },
        { "CCSGENACK",          0x08, 0x08 },
@@ -2605,13 +1658,6 @@ ahd_ccsgram_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xb0, regvalue, cur_col, wrap));
 }
 
-int
-ahd_flexadr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "FLEXADR",
-           0xb0, regvalue, cur_col, wrap));
-}
-
 int
 ahd_ccscbram_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -2619,32 +1665,6 @@ ahd_ccscbram_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xb0, regvalue, cur_col, wrap));
 }
 
-int
-ahd_flexcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "FLEXCNT",
-           0xb3, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t FLEXDMASTAT_parse_table[] = {
-       { "FLEXDMADONE",        0x01, 0x01 },
-       { "FLEXDMAERR",         0x02, 0x02 }
-};
-
-int
-ahd_flexdmastat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(FLEXDMASTAT_parse_table, 2, "FLEXDMASTAT",
-           0xb5, regvalue, cur_col, wrap));
-}
-
-int
-ahd_flexdata_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "FLEXDATA",
-           0xb6, regvalue, cur_col, wrap));
-}
-
 int
 ahd_brddat_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -2652,7 +1672,7 @@ ahd_brddat_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xb8, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t BRDCTL_parse_table[] = {
+static const ahd_reg_parse_entry_t BRDCTL_parse_table[] = {
        { "BRDSTB",             0x01, 0x01 },
        { "BRDRW",              0x02, 0x02 },
        { "BRDEN",              0x04, 0x04 },
@@ -2682,7 +1702,7 @@ ahd_seedat_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xbc, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SEECTL_parse_table[] = {
+static const ahd_reg_parse_entry_t SEECTL_parse_table[] = {
        { "SEEOP_ERAL",         0x40, 0x70 },
        { "SEEOP_WRITE",        0x50, 0x70 },
        { "SEEOP_READ",         0x60, 0x70 },
@@ -2702,7 +1722,7 @@ ahd_seectl_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xbe, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SEESTAT_parse_table[] = {
+static const ahd_reg_parse_entry_t SEESTAT_parse_table[] = {
        { "SEESTART",           0x01, 0x01 },
        { "SEEBUSY",            0x02, 0x02 },
        { "SEEARBACK",          0x04, 0x04 },
@@ -2718,34 +1738,7 @@ ahd_seestat_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xbe, regvalue, cur_col, wrap));
 }
 
-int
-ahd_scbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "SCBCNT",
-           0xbf, regvalue, cur_col, wrap));
-}
-
-int
-ahd_dfwaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "DFWADDR",
-           0xc0, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t DSPFLTRCTL_parse_table[] = {
-       { "DSPFCNTSEL",         0x0f, 0x0f },
-       { "EDGESENSE",          0x10, 0x10 },
-       { "FLTRDISABLE",        0x20, 0x20 }
-};
-
-int
-ahd_dspfltrctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(DSPFLTRCTL_parse_table, 3, "DSPFLTRCTL",
-           0xc0, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t DSPDATACTL_parse_table[] = {
+static const ahd_reg_parse_entry_t DSPDATACTL_parse_table[] = {
        { "XMITOFFSTDIS",       0x02, 0x02 },
        { "RCVROFFSTDIS",       0x04, 0x04 },
        { "DESQDIS",            0x10, 0x10 },
@@ -2759,37 +1752,6 @@ ahd_dspdatactl_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xc1, regvalue, cur_col, wrap));
 }
 
-int
-ahd_dfraddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "DFRADDR",
-           0xc2, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t DSPREQCTL_parse_table[] = {
-       { "MANREQDLY",          0x3f, 0x3f },
-       { "MANREQCTL",          0xc0, 0xc0 }
-};
-
-int
-ahd_dspreqctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(DSPREQCTL_parse_table, 2, "DSPREQCTL",
-           0xc2, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t DSPACKCTL_parse_table[] = {
-       { "MANACKDLY",          0x3f, 0x3f },
-       { "MANACKCTL",          0xc0, 0xc0 }
-};
-
-int
-ahd_dspackctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(DSPACKCTL_parse_table, 2, "DSPACKCTL",
-           0xc3, regvalue, cur_col, wrap));
-}
-
 int
 ahd_dfdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -2797,7 +1759,7 @@ ahd_dfdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xc4, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t DSPSELECT_parse_table[] = {
+static const ahd_reg_parse_entry_t DSPSELECT_parse_table[] = {
        { "DSPSEL",             0x1f, 0x1f },
        { "AUTOINCEN",          0x80, 0x80 }
 };
@@ -2809,7 +1771,7 @@ ahd_dspselect_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xc4, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t WRTBIASCTL_parse_table[] = {
+static const ahd_reg_parse_entry_t WRTBIASCTL_parse_table[] = {
        { "XMITMANVAL",         0x3f, 0x3f },
        { "AUTOXBCDIS",         0x80, 0x80 }
 };
@@ -2821,91 +1783,7 @@ ahd_wrtbiasctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xc5, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t RCVRBIOSCTL_parse_table[] = {
-       { "RCVRMANVAL",         0x3f, 0x3f },
-       { "AUTORBCDIS",         0x80, 0x80 }
-};
-
-int
-ahd_rcvrbiosctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(RCVRBIOSCTL_parse_table, 2, "RCVRBIOSCTL",
-           0xc6, regvalue, cur_col, wrap));
-}
-
-int
-ahd_wrtbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "WRTBIASCALC",
-           0xc7, regvalue, cur_col, wrap));
-}
-
-int
-ahd_rcvrbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "RCVRBIASCALC",
-           0xc8, regvalue, cur_col, wrap));
-}
-
-int
-ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "DFPTRS",
-           0xc8, regvalue, cur_col, wrap));
-}
-
-int
-ahd_skewcalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "SKEWCALC",
-           0xc9, regvalue, cur_col, wrap));
-}
-
-int
-ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "DFBKPTR",
-           0xc9, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t DFDBCTL_parse_table[] = {
-       { "DFF_RAMBIST_EN",     0x01, 0x01 },
-       { "DFF_RAMBIST_DONE",   0x02, 0x02 },
-       { "DFF_RAMBIST_FAIL",   0x04, 0x04 },
-       { "DFF_DIR_ERR",        0x08, 0x08 },
-       { "DFF_CIO_RD_RDY",     0x10, 0x10 },
-       { "DFF_CIO_WR_RDY",     0x20, 0x20 }
-};
-
-int
-ahd_dfdbctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(DFDBCTL_parse_table, 6, "DFDBCTL",
-           0xcb, regvalue, cur_col, wrap));
-}
-
-int
-ahd_dfscnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "DFSCNT",
-           0xcc, regvalue, cur_col, wrap));
-}
-
-int
-ahd_dfbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "DFBCNT",
-           0xce, regvalue, cur_col, wrap));
-}
-
-int
-ahd_ovlyaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "OVLYADDR",
-           0xd4, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SEQCTL0_parse_table[] = {
+static const ahd_reg_parse_entry_t SEQCTL0_parse_table[] = {
        { "LOADRAM",            0x01, 0x01 },
        { "SEQRESET",           0x02, 0x02 },
        { "STEP",               0x04, 0x04 },
@@ -2923,21 +1801,7 @@ ahd_seqctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xd6, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SEQCTL1_parse_table[] = {
-       { "RAMBIST_EN",         0x01, 0x01 },
-       { "RAMBIST_FAIL",       0x02, 0x02 },
-       { "RAMBIST_DONE",       0x04, 0x04 },
-       { "OVRLAY_DATA_CHK",    0x08, 0x08 }
-};
-
-int
-ahd_seqctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(SEQCTL1_parse_table, 4, "SEQCTL1",
-           0xd7, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t FLAGS_parse_table[] = {
+static const ahd_reg_parse_entry_t FLAGS_parse_table[] = {
        { "CARRY",              0x01, 0x01 },
        { "ZERO",               0x02, 0x02 }
 };
@@ -2949,7 +1813,7 @@ ahd_flags_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xd8, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SEQINTCTL_parse_table[] = {
+static const ahd_reg_parse_entry_t SEQINTCTL_parse_table[] = {
        { "IRET",               0x01, 0x01 },
        { "INTMASK1",           0x02, 0x02 },
        { "INTMASK2",           0x04, 0x04 },
@@ -3001,24 +1865,6 @@ ahd_dindex_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xe4, regvalue, cur_col, wrap));
 }
 
-int
-ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "BRKADDR0",
-           0xe6, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t BRKADDR1_parse_table[] = {
-       { "BRKDIS",             0x80, 0x80 }
-};
-
-int
-ahd_brkaddr1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(BRKADDR1_parse_table, 1, "BRKADDR1",
-           0xe6, regvalue, cur_col, wrap));
-}
-
 int
 ahd_allones_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -3054,13 +1900,6 @@ ahd_dindir_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xed, regvalue, cur_col, wrap));
 }
 
-int
-ahd_function1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "FUNCTION1",
-           0xf0, regvalue, cur_col, wrap));
-}
-
 int
 ahd_stack_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -3082,13 +1921,6 @@ ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xf4, regvalue, cur_col, wrap));
 }
 
-int
-ahd_lastaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "LASTADDR",
-           0xf6, regvalue, cur_col, wrap));
-}
-
 int
 ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -3111,23 +1943,16 @@ ahd_accum_save_print(u_int regvalue, u_int *cur_col, u_int wrap)
 }
 
 int
-ahd_waiting_scb_tails_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "WAITING_SCB_TAILS",
-           0x100, regvalue, cur_col, wrap));
-}
-
-int
-ahd_ahd_pci_config_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_sram_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-       return (ahd_print_register(NULL, 0, "AHD_PCI_CONFIG_BASE",
+       return (ahd_print_register(NULL, 0, "SRAM_BASE",
            0x100, regvalue, cur_col, wrap));
 }
 
 int
-ahd_sram_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_waiting_scb_tails_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-       return (ahd_print_register(NULL, 0, "SRAM_BASE",
+       return (ahd_print_register(NULL, 0, "WAITING_SCB_TAILS",
            0x100, regvalue, cur_col, wrap));
 }
 
@@ -3215,7 +2040,7 @@ ahd_msg_out_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x137, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t DMAPARAMS_parse_table[] = {
+static const ahd_reg_parse_entry_t DMAPARAMS_parse_table[] = {
        { "FIFORESET",          0x01, 0x01 },
        { "FIFOFLUSH",          0x02, 0x02 },
        { "DIRECTION",          0x04, 0x04 },
@@ -3235,7 +2060,7 @@ ahd_dmaparams_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x138, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
+static const ahd_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
        { "NO_DISCONNECT",      0x01, 0x01 },
        { "SPHASE_PENDING",     0x02, 0x02 },
        { "DPHASE_PENDING",     0x04, 0x04 },
@@ -3268,7 +2093,7 @@ ahd_saved_lun_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x13b, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t LASTPHASE_parse_table[] = {
+static const ahd_reg_parse_entry_t LASTPHASE_parse_table[] = {
        { "P_DATAOUT",          0x00, 0xe0 },
        { "P_DATAOUT_DT",       0x20, 0xe0 },
        { "P_DATAIN",           0x40, 0xe0 },
@@ -3326,7 +2151,7 @@ ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x144, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t ARG_1_parse_table[] = {
+static const ahd_reg_parse_entry_t ARG_1_parse_table[] = {
        { "CONT_MSG_LOOP_TARG", 0x02, 0x02 },
        { "CONT_MSG_LOOP_READ", 0x03, 0x03 },
        { "CONT_MSG_LOOP_WRITE",0x04, 0x04 },
@@ -3358,7 +2183,7 @@ ahd_last_msg_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x14a, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = {
+static const ahd_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = {
        { "ALTSTIM",            0x01, 0x01 },
        { "ENAUTOATNP",         0x02, 0x02 },
        { "MANUALP",            0x0c, 0x0c },
@@ -3381,7 +2206,7 @@ ahd_initiator_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x14c, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
+static const ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
        { "PENDING_MK_MESSAGE", 0x01, 0x01 },
        { "TARGET_MSG_PENDING", 0x02, 0x02 },
        { "SELECTOUT_QFROZEN",  0x04, 0x04 }
@@ -3465,20 +2290,20 @@ ahd_mk_message_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
 }
 
 int
-ahd_scb_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_scb_residual_datacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-       return (ahd_print_register(NULL, 0, "SCB_BASE",
+       return (ahd_print_register(NULL, 0, "SCB_RESIDUAL_DATACNT",
            0x180, regvalue, cur_col, wrap));
 }
 
 int
-ahd_scb_residual_datacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_scb_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-       return (ahd_print_register(NULL, 0, "SCB_RESIDUAL_DATACNT",
+       return (ahd_print_register(NULL, 0, "SCB_BASE",
            0x180, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SCB_RESIDUAL_SGPTR_parse_table[] = {
+static const ahd_reg_parse_entry_t SCB_RESIDUAL_SGPTR_parse_table[] = {
        { "SG_LIST_NULL",       0x01, 0x01 },
        { "SG_OVERRUN_RESID",   0x02, 0x02 },
        { "SG_ADDR_MASK",       0xf8, 0xf8 }
@@ -3498,27 +2323,6 @@ ahd_scb_scsi_status_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x188, regvalue, cur_col, wrap));
 }
 
-int
-ahd_scb_target_phases_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "SCB_TARGET_PHASES",
-           0x189, regvalue, cur_col, wrap));
-}
-
-int
-ahd_scb_target_data_dir_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "SCB_TARGET_DATA_DIR",
-           0x18a, regvalue, cur_col, wrap));
-}
-
-int
-ahd_scb_target_itag_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "SCB_TARGET_ITAG",
-           0x18b, regvalue, cur_col, wrap));
-}
-
 int
 ahd_scb_sense_busaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -3533,7 +2337,7 @@ ahd_scb_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x190, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SCB_CONTROL_parse_table[] = {
+static const ahd_reg_parse_entry_t SCB_CONTROL_parse_table[] = {
        { "SCB_TAG_TYPE",       0x03, 0x03 },
        { "DISCONNECTED",       0x04, 0x04 },
        { "STATUS_RCVD",        0x08, 0x08 },
@@ -3550,7 +2354,7 @@ ahd_scb_control_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x192, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SCB_SCSIID_parse_table[] = {
+static const ahd_reg_parse_entry_t SCB_SCSIID_parse_table[] = {
        { "OID",                0x0f, 0x0f },
        { "TID",                0xf0, 0xf0 }
 };
@@ -3562,7 +2366,7 @@ ahd_scb_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x193, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SCB_LUN_parse_table[] = {
+static const ahd_reg_parse_entry_t SCB_LUN_parse_table[] = {
        { "LID",                0xff, 0xff }
 };
 
@@ -3573,7 +2377,7 @@ ahd_scb_lun_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x194, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SCB_TASK_ATTRIBUTE_parse_table[] = {
+static const ahd_reg_parse_entry_t SCB_TASK_ATTRIBUTE_parse_table[] = {
        { "SCB_XFERLEN_ODD",    0x01, 0x01 }
 };
 
@@ -3584,7 +2388,7 @@ ahd_scb_task_attribute_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x195, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SCB_CDB_LEN_parse_table[] = {
+static const ahd_reg_parse_entry_t SCB_CDB_LEN_parse_table[] = {
        { "SCB_CDB_LEN_PTR",    0x80, 0x80 }
 };
 
@@ -3609,7 +2413,7 @@ ahd_scb_dataptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x198, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SCB_DATACNT_parse_table[] = {
+static const ahd_reg_parse_entry_t SCB_DATACNT_parse_table[] = {
        { "SG_HIGH_ADDR_BITS",  0x7f, 0x7f },
        { "SG_LAST_SEG",        0x80, 0x80 }
 };
@@ -3621,7 +2425,7 @@ ahd_scb_datacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x1a0, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SCB_SGPTR_parse_table[] = {
+static const ahd_reg_parse_entry_t SCB_SGPTR_parse_table[] = {
        { "SG_LIST_NULL",       0x01, 0x01 },
        { "SG_FULL_RESID",      0x02, 0x02 },
        { "SG_STATUS_VALID",    0x04, 0x04 }
@@ -3655,13 +2459,6 @@ ahd_scb_next2_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x1ae, regvalue, cur_col, wrap));
 }
 
-int
-ahd_scb_spare_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahd_print_register(NULL, 0, "SCB_SPARE",
-           0x1b0, regvalue, cur_col, wrap));
-}
-
 int
 ahd_scb_disconnected_lists_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
index 11bed07e90b7ef8573ae0d5fc5afcb7f3211ab07..4b51e232392ff8b3278a34c7c7e810e3ebf84d57 100644 (file)
@@ -5,7 +5,7 @@
  * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $
  * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $
  */
-static uint8_t seqprog[] = {
+static const uint8_t seqprog[] = {
        0xff, 0x02, 0x06, 0x78,
        0x00, 0xea, 0x6e, 0x59,
        0x01, 0xea, 0x04, 0x30,
@@ -1027,7 +1027,7 @@ ahd_patch0_func(struct ahd_softc *ahd)
        return (0);
 }
 
-static struct patch {
+static const struct patch {
        ahd_patch_func_t                *patch_func;
        uint32_t                 begin          :10,
                                 skip_instr     :10,
@@ -1166,7 +1166,7 @@ static struct patch {
        { ahd_patch23_func, 815, 11, 1 }
 };
 
-static struct cs {
+static const struct cs {
        uint16_t        begin;
        uint16_t        end;
 } critical_sections[] = {
index c0344e61765112195bb711ad25137e34da58fc61..e4e651cca3e448185cefb4a9474f9cf7baad12f0 100644 (file)
@@ -736,7 +736,7 @@ struct ahc_syncrate {
 #define                ST_SXFR    0x010        /* Rate Single Transition Only */
 #define                DT_SXFR    0x040        /* Rate Double Transition Only */
        uint8_t period; /* Period to send to SCSI target */
-       char *rate;
+       const char *rate;
 };
 
 /* Safe and valid period for async negotiations. */
@@ -1114,7 +1114,7 @@ typedef int (ahc_device_setup_t)(struct ahc_softc *);
 struct ahc_pci_identity {
        uint64_t                 full_id;
        uint64_t                 id_mask;
-       char                    *name;
+       const char              *name;
        ahc_device_setup_t      *setup;
 };
 
@@ -1133,15 +1133,11 @@ extern const int ahc_num_aic7770_devs;
 
 /*************************** Function Declarations ****************************/
 /******************************************************************************/
-u_int                  ahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl);
-void                   ahc_unbusy_tcl(struct ahc_softc *ahc, u_int tcl);
-void                   ahc_busy_tcl(struct ahc_softc *ahc,
-                                    u_int tcl, u_int busyid);
 
 /***************************** PCI Front End *********************************/
-struct ahc_pci_identity        *ahc_find_pci_device(ahc_dev_softc_t);
+const struct ahc_pci_identity  *ahc_find_pci_device(ahc_dev_softc_t);
 int                     ahc_pci_config(struct ahc_softc *,
-                                       struct ahc_pci_identity *);
+                                       const struct ahc_pci_identity *);
 int                     ahc_pci_test_register_access(struct ahc_softc *);
 #ifdef CONFIG_PM
 void                    ahc_pci_resume(struct ahc_softc *ahc);
@@ -1155,9 +1151,6 @@ int                        aic7770_config(struct ahc_softc *ahc,
 
 /************************** SCB and SCB queue management **********************/
 int            ahc_probe_scbs(struct ahc_softc *);
-void           ahc_run_untagged_queues(struct ahc_softc *ahc);
-void           ahc_run_untagged_queue(struct ahc_softc *ahc,
-                                      struct scb_tailq *queue);
 void           ahc_qinfifo_requeue_tail(struct ahc_softc *ahc,
                                         struct scb *scb);
 int            ahc_match_scb(struct ahc_softc *ahc, struct scb *scb,
@@ -1178,22 +1171,8 @@ int                       ahc_resume(struct ahc_softc *ahc);
 #endif
 void                    ahc_set_unit(struct ahc_softc *, int);
 void                    ahc_set_name(struct ahc_softc *, char *);
-void                    ahc_alloc_scbs(struct ahc_softc *ahc);
 void                    ahc_free(struct ahc_softc *ahc);
 int                     ahc_reset(struct ahc_softc *ahc, int reinit);
-void                    ahc_shutdown(void *arg);
-
-/*************************** Interrupt Services *******************************/
-void                   ahc_clear_intstat(struct ahc_softc *ahc);
-void                   ahc_run_qoutfifo(struct ahc_softc *ahc);
-#ifdef AHC_TARGET_MODE
-void                   ahc_run_tqinfifo(struct ahc_softc *ahc, int paused);
-#endif
-void                   ahc_handle_brkadrint(struct ahc_softc *ahc);
-void                   ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat);
-void                   ahc_handle_scsiint(struct ahc_softc *ahc,
-                                          u_int intstat);
-void                   ahc_clear_critical_section(struct ahc_softc *ahc);
 
 /***************************** Error Recovery *********************************/
 typedef enum {
@@ -1214,36 +1193,19 @@ int                     ahc_search_disc_list(struct ahc_softc *ahc, int target,
                                             char channel, int lun, u_int tag,
                                             int stop_on_first, int remove,
                                             int save_state);
-void                   ahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb);
 int                    ahc_reset_channel(struct ahc_softc *ahc, char channel,
                                          int initiate_reset);
-int                    ahc_abort_scbs(struct ahc_softc *ahc, int target,
-                                      char channel, int lun, u_int tag,
-                                      role_t role, uint32_t status);
-void                   ahc_restart(struct ahc_softc *ahc);
-void                   ahc_calc_residual(struct ahc_softc *ahc,
-                                         struct scb *scb);
+
 /*************************** Utility Functions ********************************/
-struct ahc_phase_table_entry*
-                       ahc_lookup_phase_entry(int phase);
 void                   ahc_compile_devinfo(struct ahc_devinfo *devinfo,
                                            u_int our_id, u_int target,
                                            u_int lun, char channel,
                                            role_t role);
 /************************** Transfer Negotiation ******************************/
-struct ahc_syncrate*   ahc_find_syncrate(struct ahc_softc *ahc, u_int *period,
+const struct ahc_syncrate*     ahc_find_syncrate(struct ahc_softc *ahc, u_int *period,
                                          u_int *ppr_options, u_int maxsync);
 u_int                  ahc_find_period(struct ahc_softc *ahc,
                                        u_int scsirate, u_int maxsync);
-void                   ahc_validate_offset(struct ahc_softc *ahc,
-                                           struct ahc_initiator_tinfo *tinfo,
-                                           struct ahc_syncrate *syncrate,
-                                           u_int *offset, int wide,
-                                           role_t role);
-void                   ahc_validate_width(struct ahc_softc *ahc,
-                                          struct ahc_initiator_tinfo *tinfo,
-                                          u_int *bus_width,
-                                          role_t role);
 /*
  * Negotiation types.  These are used to qualify if we should renegotiate
  * even if our goal and current transport parameters are identical.
@@ -1263,7 +1225,7 @@ void                      ahc_set_width(struct ahc_softc *ahc,
                                      u_int width, u_int type, int paused);
 void                   ahc_set_syncrate(struct ahc_softc *ahc,
                                         struct ahc_devinfo *devinfo,
-                                        struct ahc_syncrate *syncrate,
+                                        const struct ahc_syncrate *syncrate,
                                         u_int period, u_int offset,
                                         u_int ppr_options,
                                         u_int type, int paused);
@@ -1305,11 +1267,10 @@ extern uint32_t ahc_debug;
 #define AHC_SHOW_MASKED_ERRORS 0x1000
 #define AHC_DEBUG_SEQUENCER    0x2000
 #endif
-void                   ahc_print_scb(struct scb *scb);
 void                   ahc_print_devinfo(struct ahc_softc *ahc,
                                          struct ahc_devinfo *dev);
 void                   ahc_dump_card_state(struct ahc_softc *ahc);
-int                    ahc_print_register(ahc_reg_parse_entry_t *table,
+int                    ahc_print_register(const ahc_reg_parse_entry_t *table,
                                           u_int num_entries,
                                           const char *name,
                                           u_int address,
index e196d83b93c7a49fc8fcf1828afbc1da2c16a7b0..0d2f763c3427c820300303fb8bec461a4a66548b 100644 (file)
@@ -238,6 +238,7 @@ register SXFRCTL2 {
 register OPTIONMODE {
        address                 0x008
        access_mode RW
+       count           2
        field   AUTORATEEN              0x80
        field   AUTOACKEN               0x40
        field   ATNMGMNTEN              0x20
@@ -254,6 +255,7 @@ register TARGCRCCNT {
        address                 0x00a
        size    2
        access_mode RW
+       count           2
 }
 
 /*
@@ -344,6 +346,7 @@ register SSTAT2 {
 register SSTAT3 {
        address                 0x00e
        access_mode RO
+       count           2
        mask    SCSICNT         0xf0
        mask    OFFCNT          0x0f
        mask    U2OFFCNT        0x7f
@@ -367,6 +370,7 @@ register SCSIID_ULTRA2 {
 register SIMODE0 {
        address                 0x010
        access_mode RW
+       count           2
        field   ENSELDO         0x40
        field   ENSELDI         0x20
        field   ENSELINGO       0x10
@@ -429,6 +433,7 @@ register SHADDR {
 register SELTIMER {
        address                 0x018
        access_mode RW
+       count           1
        field   STAGE6          0x20
        field   STAGE5          0x10
        field   STAGE4          0x08
@@ -467,6 +472,7 @@ register TARGID {
        address                 0x01b
        size                    2
        access_mode RW
+       count           14
 }
 
 /*
@@ -480,6 +486,7 @@ register TARGID {
 register SPIOCAP {
        address                 0x01b
        access_mode RW
+       count           10
        field   SOFT1           0x80
        field   SOFT0           0x40
        field   SOFTCMDEN       0x20    
@@ -492,6 +499,7 @@ register SPIOCAP {
 
 register BRDCTL        {
        address                 0x01d
+       count           11
        field   BRDDAT7         0x80
        field   BRDDAT6         0x40
        field   BRDDAT5         0x20
@@ -534,6 +542,7 @@ register BRDCTL     {
  */
 register SEECTL {
        address                 0x01e
+       count           11
        field   EXTARBACK       0x80
        field   EXTARBREQ       0x40
        field   SEEMS           0x20
@@ -570,6 +579,7 @@ register SBLKCTL {
 register SEQCTL {
        address                 0x060
        access_mode RW
+       count           15
        field   PERRORDIS       0x80
        field   PAUSEDIS        0x40
        field   FAILDIS         0x20
@@ -590,6 +600,7 @@ register SEQCTL {
 register SEQRAM {
        address                 0x061
        access_mode RW
+       count           2
 }
 
 /*
@@ -604,6 +615,7 @@ register SEQADDR0 {
 register SEQADDR1 {
        address                 0x063
        access_mode RW
+       count           8
        mask    SEQADDR1_MASK   0x01
 }
 
@@ -649,6 +661,7 @@ register NONE {
 register FLAGS {
        address                 0x06b
        access_mode RO
+       count           18
        field   ZERO            0x02
        field   CARRY           0x01
 }
@@ -671,6 +684,7 @@ register FUNCTION1 {
 register STACK {
        address                 0x06f
        access_mode RO
+       count           5
 }
 
 const  STACK_SIZE      4
@@ -692,6 +706,7 @@ register BCTL {
 register DSCOMMAND0 {
        address                 0x084
        access_mode RW
+       count           7
        field   CACHETHEN       0x80    /* Cache Threshold enable */
        field   DPARCKEN        0x40    /* Data Parity Check Enable */
        field   MPARCKEN        0x20    /* Memory Parity Check Enable */
@@ -717,6 +732,7 @@ register DSCOMMAND1 {
 register BUSTIME {
        address                 0x085
        access_mode RW
+       count           2
        mask    BOFF            0xf0
        mask    BON             0x0f
 }
@@ -727,6 +743,7 @@ register BUSTIME {
 register BUSSPD {
        address                 0x086
        access_mode RW
+       count           2
        mask    DFTHRSH         0xc0
        mask    STBOFF          0x38
        mask    STBON           0x07
@@ -737,6 +754,7 @@ register BUSSPD {
 /* aic7850/55/60/70/80/95 only */
 register DSPCISTATUS {
        address                 0x086
+       count           4
        mask    DFTHRSH_100     0xc0
 }
 
@@ -758,6 +776,7 @@ const       SEQ_MAILBOX_SHIFT       0
 register HCNTRL {
        address                 0x087
        access_mode RW
+       count           14
        field   POWRDN          0x40
        field   SWINT           0x10
        field   IRQMS           0x08
@@ -869,6 +888,7 @@ register INTSTAT {
 register ERROR {
        address                 0x092
        access_mode RO
+       count           26
        field   CIOPARERR       0x80    /* Ultra2 only */
        field   PCIERRSTAT      0x40    /* PCI only */
        field   MPARERR         0x20    /* PCI only */
@@ -885,6 +905,7 @@ register ERROR {
 register CLRINT {
        address                 0x092
        access_mode WO
+       count           24
        field   CLRPARERR       0x10    /* PCI only */
        field   CLRBRKADRINT    0x08
        field   CLRSCSIINT      0x04
@@ -943,6 +964,7 @@ register DFDAT {
 register SCBCNT {
        address                 0x09a
        access_mode RW
+       count           1
        field   SCBAUTO         0x80
        mask    SCBCNT_MASK     0x1f
 }
@@ -954,6 +976,7 @@ register SCBCNT {
 register QINFIFO {
        address                 0x09b
        access_mode RW
+       count           12
 }
 
 /*
@@ -972,11 +995,13 @@ register QINCNT   {
 register QOUTFIFO {
        address                 0x09d
        access_mode WO
+       count           7
 }
 
 register CRCCONTROL1 {
        address                 0x09d
        access_mode RW
+       count           3
        field   CRCONSEEN               0x80
        field   CRCVALCHKEN             0x40
        field   CRCENDCHKEN             0x20
@@ -1013,6 +1038,7 @@ register SCSIPHASE {
 register SFUNCT {
        address                 0x09f
        access_mode RW
+       count       4
        field   ALT_MODE        0x80
 }
 
@@ -1095,6 +1121,7 @@ scb {
        }
        SCB_SCSIOFFSET {
                size    1
+               count   1
        }
        SCB_NEXT {
                size    1
@@ -1118,6 +1145,7 @@ const     SG_SIZEOF       0x08            /* sizeof(struct ahc_dma) */
 register SEECTL_2840 {
        address                 0x0c0
        access_mode RW
+       count           2
        field   CS_2840         0x04
        field   CK_2840         0x02
        field   DO_2840         0x01
@@ -1126,6 +1154,7 @@ register SEECTL_2840 {
 register STATUS_2840 {
        address                 0x0c1
        access_mode RW
+       count           4
        field   EEPROM_TF       0x80
        mask    BIOS_SEL        0x60
        mask    ADSEL           0x1e
@@ -1161,6 +1190,7 @@ register CCSGCTL {
 
 register CCSCBCNT {
        address                 0xEF
+       count           1
 }
 
 register CCSCBCTL {
@@ -1187,6 +1217,7 @@ register CCSCBRAM {
 register SCBBADDR {
        address                 0x0F0
        access_mode RW
+       count           3
 }
 
 register CCSCBPTR {
@@ -1195,6 +1226,7 @@ register CCSCBPTR {
 
 register HNSCB_QOFF {
        address                 0x0F4
+       count           4
 }
 
 register SNSCB_QOFF {
@@ -1234,6 +1266,7 @@ register DFF_THRSH {
        mask    WR_DFTHRSH_85   0x50
        mask    WR_DFTHRSH_90   0x60
        mask    WR_DFTHRSH_MAX  0x70
+       count   4
 }
 
 register SG_CACHE_PRE {
@@ -1287,6 +1320,7 @@ scratch_ram {
        ULTRA_ENB {
                alias           CMDSIZE_TABLE
                size            2
+               count           2
        }
        /*
         * Bit vector of targets that have disconnection disabled as set by
@@ -1296,6 +1330,7 @@ scratch_ram {
         */
        DISC_DSB {
                size            2
+               count           6
        }
        CMDSIZE_TABLE_TAIL {
                size            4
@@ -1323,6 +1358,7 @@ scratch_ram {
        /* Parameters for DMA Logic */
        DMAPARAMS {
                size            1
+               count           12
                field   PRELOADEN       0x80
                field   WIDEODD         0x40
                field   SCSIEN          0x20
@@ -1436,11 +1472,12 @@ scratch_ram {
        KERNEL_TQINPOS {
                size            1
        }
-       TQINPOS {                
+       TQINPOS {
                size            1
        }
        ARG_1 {
                size            1
+               count           1
                mask    SEND_MSG                0x80
                mask    SEND_SENSE              0x40
                mask    SEND_REJ                0x20
@@ -1495,6 +1532,7 @@ scratch_ram {
                size    1
                field   HA_274_EXTENDED_TRANS   0x01
                alias   INITIATOR_TAG
+               count           1
        }
 
        SEQ_FLAGS2 {
@@ -1518,6 +1556,7 @@ scratch_ram {
         */
        SCSICONF {
                size            1
+               count           12
                field   TERM_ENB        0x80
                field   RESET_SCSI      0x40
                field   ENSPCHK         0x20
@@ -1527,16 +1566,19 @@ scratch_ram {
        INTDEF {
                address         0x05c
                size            1
+               count           1
                field   EDGE_TRIG       0x80
                mask    VECTOR          0x0f
        }
        HOSTCONF {
                address         0x05d
                size            1
+               count           1
        }
        HA_274_BIOSCTRL {
                address         0x05f
                size            1
+               count           1
                mask    BIOSMODE                0x30
                mask    BIOSDISABLED            0x30    
                field   CHANNEL_B_PRIMARY       0x08
@@ -1552,6 +1594,7 @@ scratch_ram {
         */
        TARG_OFFSET {
                size            16
+               count           1
        }
 }
 
index 3cb07e114e89cd6e83e9753594dc741dd63fe03c..dd11999b77b6dd590992671c062ad508b3bcf546 100644 (file)
@@ -84,16 +84,16 @@ struct seeprom_cmd {
 };
 
 /* Short opcodes for the c46 */
-static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
-static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
+static const struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
+static const struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
 
 /* Long opcodes for the C56/C66 */
-static struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
-static struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
+static const struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
+static const struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
 
 /* Common opcodes */
-static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}};
-static struct seeprom_cmd seeprom_read  = {3, {1, 1, 0}};
+static const struct seeprom_cmd seeprom_write = {3, {1, 0, 1}};
+static const struct seeprom_cmd seeprom_read  = {3, {1, 1, 0}};
 
 /*
  * Wait for the SEERDY to go high; about 800 ns.
@@ -108,7 +108,7 @@ static struct seeprom_cmd seeprom_read  = {3, {1, 1, 0}};
  * Send a START condition and the given command
  */
 static void
-send_seeprom_cmd(struct seeprom_descriptor *sd, struct seeprom_cmd *cmd)
+send_seeprom_cmd(struct seeprom_descriptor *sd, const struct seeprom_cmd *cmd)
 {
        uint8_t temp;
        int i = 0;
@@ -227,7 +227,7 @@ int
 ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
                  u_int start_addr, u_int count)
 {
-       struct seeprom_cmd *ewen, *ewds;
+       const struct seeprom_cmd *ewen, *ewds;
        uint16_t v;
        uint8_t temp;
        int i, k;
index 64e62ce59c152fbedf5495021d0b7d3a6f9e536e..0ae2b4605d09aa9068765486903aa19929ed7e9d 100644 (file)
@@ -51,8 +51,7 @@
 #endif
 
 /***************************** Lookup Tables **********************************/
-char *ahc_chip_names[] =
-{
+static const char *const ahc_chip_names[] = {
        "NONE",
        "aic7770",
        "aic7850",
@@ -75,10 +74,10 @@ static const u_int num_chip_names = ARRAY_SIZE(ahc_chip_names);
  */
 struct ahc_hard_error_entry {
         uint8_t errno;
-       char *errmesg;
+       const char *errmesg;
 };
 
-static struct ahc_hard_error_entry ahc_hard_errors[] = {
+static const struct ahc_hard_error_entry ahc_hard_errors[] = {
        { ILLHADDR,     "Illegal Host Access" },
        { ILLSADDR,     "Illegal Sequencer Address referrenced" },
        { ILLOPCODE,    "Illegal Opcode in sequencer program" },
@@ -90,7 +89,7 @@ static struct ahc_hard_error_entry ahc_hard_errors[] = {
 };
 static const u_int num_errors = ARRAY_SIZE(ahc_hard_errors);
 
-static struct ahc_phase_table_entry ahc_phase_table[] =
+static const struct ahc_phase_table_entry ahc_phase_table[] =
 {
        { P_DATAOUT,    MSG_NOOP,               "in Data-out phase"     },
        { P_DATAIN,     MSG_INITIATOR_DET_ERR,  "in Data-in phase"      },
@@ -115,7 +114,7 @@ static const u_int num_phases = ARRAY_SIZE(ahc_phase_table) - 1;
  * Provides a mapping of tranfer periods in ns to the proper value to
  * stick in the scsixfer reg.
  */
-static struct ahc_syncrate ahc_syncrates[] =
+static const struct ahc_syncrate ahc_syncrates[] =
 {
       /* ultra2    fast/ultra  period     rate */
        { 0x42,      0x000,      9,      "80.0" },
@@ -148,7 +147,7 @@ static struct ahc_tmode_tstate*
 static void            ahc_free_tstate(struct ahc_softc *ahc,
                                        u_int scsi_id, char channel, int force);
 #endif
-static struct ahc_syncrate*
+static const struct ahc_syncrate*
                        ahc_devlimited_syncrate(struct ahc_softc *ahc,
                                                struct ahc_initiator_tinfo *,
                                                u_int *period,
@@ -204,9 +203,9 @@ static void         ahc_setup_target_msgin(struct ahc_softc *ahc,
 #endif
 
 static bus_dmamap_callback_t   ahc_dmamap_cb; 
-static void                    ahc_build_free_scb_list(struct ahc_softc *ahc);
-static int                     ahc_init_scbdata(struct ahc_softc *ahc);
-static void                    ahc_fini_scbdata(struct ahc_softc *ahc);
+static void            ahc_build_free_scb_list(struct ahc_softc *ahc);
+static int             ahc_init_scbdata(struct ahc_softc *ahc);
+static void            ahc_fini_scbdata(struct ahc_softc *ahc);
 static void            ahc_qinfifo_requeue(struct ahc_softc *ahc,
                                            struct scb *prev_scb,
                                            struct scb *scb);
@@ -222,7 +221,7 @@ static void         ahc_dumpseq(struct ahc_softc *ahc);
 #endif
 static int             ahc_loadseq(struct ahc_softc *ahc);
 static int             ahc_check_patch(struct ahc_softc *ahc,
-                                       struct patch **start_patch,
+                                       const struct patch **start_patch,
                                        u_int start_instr, u_int *skip_addr);
 static void            ahc_download_instr(struct ahc_softc *ahc,
                                           u_int instrptr, uint8_t *dconsts);
@@ -237,11 +236,582 @@ static void              ahc_update_scsiid(struct ahc_softc *ahc,
 static int             ahc_handle_target_cmd(struct ahc_softc *ahc,
                                              struct target_cmd *cmd);
 #endif
+
+static u_int           ahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl);
+static void            ahc_unbusy_tcl(struct ahc_softc *ahc, u_int tcl);
+static void            ahc_busy_tcl(struct ahc_softc *ahc,
+                                    u_int tcl, u_int busyid);
+
+/************************** SCB and SCB queue management **********************/
+static void            ahc_run_untagged_queues(struct ahc_softc *ahc);
+static void            ahc_run_untagged_queue(struct ahc_softc *ahc,
+                                              struct scb_tailq *queue);
+
+/****************************** Initialization ********************************/
+static void             ahc_alloc_scbs(struct ahc_softc *ahc);
+static void             ahc_shutdown(void *arg);
+
+/*************************** Interrupt Services *******************************/
+static void            ahc_clear_intstat(struct ahc_softc *ahc);
+static void            ahc_run_qoutfifo(struct ahc_softc *ahc);
+#ifdef AHC_TARGET_MODE
+static void            ahc_run_tqinfifo(struct ahc_softc *ahc, int paused);
+#endif
+static void            ahc_handle_brkadrint(struct ahc_softc *ahc);
+static void            ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat);
+static void            ahc_handle_scsiint(struct ahc_softc *ahc,
+                                          u_int intstat);
+static void            ahc_clear_critical_section(struct ahc_softc *ahc);
+
+/***************************** Error Recovery *********************************/
+static void            ahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb);
+static int             ahc_abort_scbs(struct ahc_softc *ahc, int target,
+                                      char channel, int lun, u_int tag,
+                                      role_t role, uint32_t status);
+static void            ahc_calc_residual(struct ahc_softc *ahc,
+                                         struct scb *scb);
+
+/*********************** Untagged Transaction Routines ************************/
+static inline void     ahc_freeze_untagged_queues(struct ahc_softc *ahc);
+static inline void     ahc_release_untagged_queues(struct ahc_softc *ahc);
+
+/*
+ * Block our completion routine from starting the next untagged
+ * transaction for this target or target lun.
+ */
+static inline void
+ahc_freeze_untagged_queues(struct ahc_softc *ahc)
+{
+       if ((ahc->flags & AHC_SCB_BTT) == 0)
+               ahc->untagged_queue_lock++;
+}
+
+/*
+ * Allow the next untagged transaction for this target or target lun
+ * to be executed.  We use a counting semaphore to allow the lock
+ * to be acquired recursively.  Once the count drops to zero, the
+ * transaction queues will be run.
+ */
+static inline void
+ahc_release_untagged_queues(struct ahc_softc *ahc)
+{
+       if ((ahc->flags & AHC_SCB_BTT) == 0) {
+               ahc->untagged_queue_lock--;
+               if (ahc->untagged_queue_lock == 0)
+                       ahc_run_untagged_queues(ahc);
+       }
+}
+
 /************************* Sequencer Execution Control ************************/
 /*
- * Restart the sequencer program from address zero
+ * Work around any chip bugs related to halting sequencer execution.
+ * On Ultra2 controllers, we must clear the CIOBUS stretch signal by
+ * reading a register that will set this signal and deassert it.
+ * Without this workaround, if the chip is paused, by an interrupt or
+ * manual pause while accessing scb ram, accesses to certain registers
+ * will hang the system (infinite pci retries).
+ */
+static void
+ahc_pause_bug_fix(struct ahc_softc *ahc)
+{
+       if ((ahc->features & AHC_ULTRA2) != 0)
+               (void)ahc_inb(ahc, CCSCBCTL);
+}
+
+/*
+ * Determine whether the sequencer has halted code execution.
+ * Returns non-zero status if the sequencer is stopped.
+ */
+int
+ahc_is_paused(struct ahc_softc *ahc)
+{
+       return ((ahc_inb(ahc, HCNTRL) & PAUSE) != 0);
+}
+
+/*
+ * Request that the sequencer stop and wait, indefinitely, for it
+ * to stop.  The sequencer will only acknowledge that it is paused
+ * once it has reached an instruction boundary and PAUSEDIS is
+ * cleared in the SEQCTL register.  The sequencer may use PAUSEDIS
+ * for critical sections.
+ */
+void
+ahc_pause(struct ahc_softc *ahc)
+{
+       ahc_outb(ahc, HCNTRL, ahc->pause);
+
+       /*
+        * Since the sequencer can disable pausing in a critical section, we
+        * must loop until it actually stops.
+        */
+       while (ahc_is_paused(ahc) == 0)
+               ;
+
+       ahc_pause_bug_fix(ahc);
+}
+
+/*
+ * Allow the sequencer to continue program execution.
+ * We check here to ensure that no additional interrupt
+ * sources that would cause the sequencer to halt have been
+ * asserted.  If, for example, a SCSI bus reset is detected
+ * while we are fielding a different, pausing, interrupt type,
+ * we don't want to release the sequencer before going back
+ * into our interrupt handler and dealing with this new
+ * condition.
+ */
+void
+ahc_unpause(struct ahc_softc *ahc)
+{
+       if ((ahc_inb(ahc, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) == 0)
+               ahc_outb(ahc, HCNTRL, ahc->unpause);
+}
+
+/************************** Memory mapping routines ***************************/
+static struct ahc_dma_seg *
+ahc_sg_bus_to_virt(struct scb *scb, uint32_t sg_busaddr)
+{
+       int sg_index;
+
+       sg_index = (sg_busaddr - scb->sg_list_phys)/sizeof(struct ahc_dma_seg);
+       /* sg_list_phys points to entry 1, not 0 */
+       sg_index++;
+
+       return (&scb->sg_list[sg_index]);
+}
+
+static uint32_t
+ahc_sg_virt_to_bus(struct scb *scb, struct ahc_dma_seg *sg)
+{
+       int sg_index;
+
+       /* sg_list_phys points to entry 1, not 0 */
+       sg_index = sg - &scb->sg_list[1];
+
+       return (scb->sg_list_phys + (sg_index * sizeof(*scb->sg_list)));
+}
+
+static uint32_t
+ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index)
+{
+       return (ahc->scb_data->hscb_busaddr
+               + (sizeof(struct hardware_scb) * index));
+}
+
+static void
+ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op)
+{
+       ahc_dmamap_sync(ahc, ahc->scb_data->hscb_dmat,
+                       ahc->scb_data->hscb_dmamap,
+                       /*offset*/(scb->hscb - ahc->hscbs) * sizeof(*scb->hscb),
+                       /*len*/sizeof(*scb->hscb), op);
+}
+
+void
+ahc_sync_sglist(struct ahc_softc *ahc, struct scb *scb, int op)
+{
+       if (scb->sg_count == 0)
+               return;
+
+       ahc_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap,
+                       /*offset*/(scb->sg_list - scb->sg_map->sg_vaddr)
+                               * sizeof(struct ahc_dma_seg),
+                       /*len*/sizeof(struct ahc_dma_seg) * scb->sg_count, op);
+}
+
+#ifdef AHC_TARGET_MODE
+static uint32_t
+ahc_targetcmd_offset(struct ahc_softc *ahc, u_int index)
+{
+       return (((uint8_t *)&ahc->targetcmds[index]) - ahc->qoutfifo);
+}
+#endif
+
+/*********************** Miscelaneous Support Functions ***********************/
+/*
+ * Determine whether the sequencer reported a residual
+ * for this SCB/transaction.
+ */
+static void
+ahc_update_residual(struct ahc_softc *ahc, struct scb *scb)
+{
+       uint32_t sgptr;
+
+       sgptr = ahc_le32toh(scb->hscb->sgptr);
+       if ((sgptr & SG_RESID_VALID) != 0)
+               ahc_calc_residual(ahc, scb);
+}
+
+/*
+ * Return pointers to the transfer negotiation information
+ * for the specified our_id/remote_id pair.
+ */
+struct ahc_initiator_tinfo *
+ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id,
+                   u_int remote_id, struct ahc_tmode_tstate **tstate)
+{
+       /*
+        * Transfer data structures are stored from the perspective
+        * of the target role.  Since the parameters for a connection
+        * in the initiator role to a given target are the same as
+        * when the roles are reversed, we pretend we are the target.
+        */
+       if (channel == 'B')
+               our_id += 8;
+       *tstate = ahc->enabled_targets[our_id];
+       return (&(*tstate)->transinfo[remote_id]);
+}
+
+uint16_t
+ahc_inw(struct ahc_softc *ahc, u_int port)
+{
+       uint16_t r = ahc_inb(ahc, port+1) << 8;
+       return r | ahc_inb(ahc, port);
+}
+
+void
+ahc_outw(struct ahc_softc *ahc, u_int port, u_int value)
+{
+       ahc_outb(ahc, port, value & 0xFF);
+       ahc_outb(ahc, port+1, (value >> 8) & 0xFF);
+}
+
+uint32_t
+ahc_inl(struct ahc_softc *ahc, u_int port)
+{
+       return ((ahc_inb(ahc, port))
+             | (ahc_inb(ahc, port+1) << 8)
+             | (ahc_inb(ahc, port+2) << 16)
+             | (ahc_inb(ahc, port+3) << 24));
+}
+
+void
+ahc_outl(struct ahc_softc *ahc, u_int port, uint32_t value)
+{
+       ahc_outb(ahc, port, (value) & 0xFF);
+       ahc_outb(ahc, port+1, ((value) >> 8) & 0xFF);
+       ahc_outb(ahc, port+2, ((value) >> 16) & 0xFF);
+       ahc_outb(ahc, port+3, ((value) >> 24) & 0xFF);
+}
+
+uint64_t
+ahc_inq(struct ahc_softc *ahc, u_int port)
+{
+       return ((ahc_inb(ahc, port))
+             | (ahc_inb(ahc, port+1) << 8)
+             | (ahc_inb(ahc, port+2) << 16)
+             | (ahc_inb(ahc, port+3) << 24)
+             | (((uint64_t)ahc_inb(ahc, port+4)) << 32)
+             | (((uint64_t)ahc_inb(ahc, port+5)) << 40)
+             | (((uint64_t)ahc_inb(ahc, port+6)) << 48)
+             | (((uint64_t)ahc_inb(ahc, port+7)) << 56));
+}
+
+void
+ahc_outq(struct ahc_softc *ahc, u_int port, uint64_t value)
+{
+       ahc_outb(ahc, port, value & 0xFF);
+       ahc_outb(ahc, port+1, (value >> 8) & 0xFF);
+       ahc_outb(ahc, port+2, (value >> 16) & 0xFF);
+       ahc_outb(ahc, port+3, (value >> 24) & 0xFF);
+       ahc_outb(ahc, port+4, (value >> 32) & 0xFF);
+       ahc_outb(ahc, port+5, (value >> 40) & 0xFF);
+       ahc_outb(ahc, port+6, (value >> 48) & 0xFF);
+       ahc_outb(ahc, port+7, (value >> 56) & 0xFF);
+}
+
+/*
+ * Get a free scb. If there are none, see if we can allocate a new SCB.
+ */
+struct scb *
+ahc_get_scb(struct ahc_softc *ahc)
+{
+       struct scb *scb;
+
+       if ((scb = SLIST_FIRST(&ahc->scb_data->free_scbs)) == NULL) {
+               ahc_alloc_scbs(ahc);
+               scb = SLIST_FIRST(&ahc->scb_data->free_scbs);
+               if (scb == NULL)
+                       return (NULL);
+       }
+       SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links.sle);
+       return (scb);
+}
+
+/*
+ * Return an SCB resource to the free list.
+ */
+void
+ahc_free_scb(struct ahc_softc *ahc, struct scb *scb)
+{
+       struct hardware_scb *hscb;
+
+       hscb = scb->hscb;
+       /* Clean up for the next user */
+       ahc->scb_data->scbindex[hscb->tag] = NULL;
+       scb->flags = SCB_FREE;
+       hscb->control = 0;
+
+       SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle);
+
+       /* Notify the OSM that a resource is now available. */
+       ahc_platform_scb_free(ahc, scb);
+}
+
+struct scb *
+ahc_lookup_scb(struct ahc_softc *ahc, u_int tag)
+{
+       struct scb* scb;
+
+       scb = ahc->scb_data->scbindex[tag];
+       if (scb != NULL)
+               ahc_sync_scb(ahc, scb,
+                            BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+       return (scb);
+}
+
+static void
+ahc_swap_with_next_hscb(struct ahc_softc *ahc, struct scb *scb)
+{
+       struct hardware_scb *q_hscb;
+       u_int  saved_tag;
+
+       /*
+        * Our queuing method is a bit tricky.  The card
+        * knows in advance which HSCB to download, and we
+        * can't disappoint it.  To achieve this, the next
+        * SCB to download is saved off in ahc->next_queued_scb.
+        * When we are called to queue "an arbitrary scb",
+        * we copy the contents of the incoming HSCB to the one
+        * the sequencer knows about, swap HSCB pointers and
+        * finally assign the SCB to the tag indexed location
+        * in the scb_array.  This makes sure that we can still
+        * locate the correct SCB by SCB_TAG.
+        */
+       q_hscb = ahc->next_queued_scb->hscb;
+       saved_tag = q_hscb->tag;
+       memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
+       if ((scb->flags & SCB_CDB32_PTR) != 0) {
+               q_hscb->shared_data.cdb_ptr =
+                   ahc_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag)
+                             + offsetof(struct hardware_scb, cdb32));
+       }
+       q_hscb->tag = saved_tag;
+       q_hscb->next = scb->hscb->tag;
+
+       /* Now swap HSCB pointers. */
+       ahc->next_queued_scb->hscb = scb->hscb;
+       scb->hscb = q_hscb;
+
+       /* Now define the mapping from tag to SCB in the scbindex */
+       ahc->scb_data->scbindex[scb->hscb->tag] = scb;
+}
+
+/*
+ * Tell the sequencer about a new transaction to execute.
  */
 void
+ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb)
+{
+       ahc_swap_with_next_hscb(ahc, scb);
+
+       if (scb->hscb->tag == SCB_LIST_NULL
+        || scb->hscb->next == SCB_LIST_NULL)
+               panic("Attempt to queue invalid SCB tag %x:%x\n",
+                     scb->hscb->tag, scb->hscb->next);
+
+       /*
+        * Setup data "oddness".
+        */
+       scb->hscb->lun &= LID;
+       if (ahc_get_transfer_length(scb) & 0x1)
+               scb->hscb->lun |= SCB_XFERLEN_ODD;
+
+       /*
+        * Keep a history of SCBs we've downloaded in the qinfifo.
+        */
+       ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag;
+
+       /*
+        * Make sure our data is consistent from the
+        * perspective of the adapter.
+        */
+       ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+
+       /* Tell the adapter about the newly queued SCB */
+       if ((ahc->features & AHC_QUEUE_REGS) != 0) {
+               ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
+       } else {
+               if ((ahc->features & AHC_AUTOPAUSE) == 0)
+                       ahc_pause(ahc);
+               ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext);
+               if ((ahc->features & AHC_AUTOPAUSE) == 0)
+                       ahc_unpause(ahc);
+       }
+}
+
+struct scsi_sense_data *
+ahc_get_sense_buf(struct ahc_softc *ahc, struct scb *scb)
+{
+       int offset;
+
+       offset = scb - ahc->scb_data->scbarray;
+       return (&ahc->scb_data->sense[offset]);
+}
+
+static uint32_t
+ahc_get_sense_bufaddr(struct ahc_softc *ahc, struct scb *scb)
+{
+       int offset;
+
+       offset = scb - ahc->scb_data->scbarray;
+       return (ahc->scb_data->sense_busaddr
+             + (offset * sizeof(struct scsi_sense_data)));
+}
+
+/************************** Interrupt Processing ******************************/
+static void
+ahc_sync_qoutfifo(struct ahc_softc *ahc, int op)
+{
+       ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
+                       /*offset*/0, /*len*/256, op);
+}
+
+static void
+ahc_sync_tqinfifo(struct ahc_softc *ahc, int op)
+{
+#ifdef AHC_TARGET_MODE
+       if ((ahc->flags & AHC_TARGETROLE) != 0) {
+               ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
+                               ahc->shared_data_dmamap,
+                               ahc_targetcmd_offset(ahc, 0),
+                               sizeof(struct target_cmd) * AHC_TMODE_CMDS,
+                               op);
+       }
+#endif
+}
+
+/*
+ * See if the firmware has posted any completed commands
+ * into our in-core command complete fifos.
+ */
+#define AHC_RUN_QOUTFIFO 0x1
+#define AHC_RUN_TQINFIFO 0x2
+static u_int
+ahc_check_cmdcmpltqueues(struct ahc_softc *ahc)
+{
+       u_int retval;
+
+       retval = 0;
+       ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
+                       /*offset*/ahc->qoutfifonext, /*len*/1,
+                       BUS_DMASYNC_POSTREAD);
+       if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL)
+               retval |= AHC_RUN_QOUTFIFO;
+#ifdef AHC_TARGET_MODE
+       if ((ahc->flags & AHC_TARGETROLE) != 0
+        && (ahc->flags & AHC_TQINFIFO_BLOCKED) == 0) {
+               ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
+                               ahc->shared_data_dmamap,
+                               ahc_targetcmd_offset(ahc, ahc->tqinfifofnext),
+                               /*len*/sizeof(struct target_cmd),
+                               BUS_DMASYNC_POSTREAD);
+               if (ahc->targetcmds[ahc->tqinfifonext].cmd_valid != 0)
+                       retval |= AHC_RUN_TQINFIFO;
+       }
+#endif
+       return (retval);
+}
+
+/*
+ * Catch an interrupt from the adapter
+ */
+int
+ahc_intr(struct ahc_softc *ahc)
+{
+       u_int   intstat;
+
+       if ((ahc->pause & INTEN) == 0) {
+               /*
+                * Our interrupt is not enabled on the chip
+                * and may be disabled for re-entrancy reasons,
+                * so just return.  This is likely just a shared
+                * interrupt.
+                */
+               return (0);
+       }
+       /*
+        * Instead of directly reading the interrupt status register,
+        * infer the cause of the interrupt by checking our in-core
+        * completion queues.  This avoids a costly PCI bus read in
+        * most cases.
+        */
+       if ((ahc->flags & (AHC_ALL_INTERRUPTS|AHC_EDGE_INTERRUPT)) == 0
+        && (ahc_check_cmdcmpltqueues(ahc) != 0))
+               intstat = CMDCMPLT;
+       else {
+               intstat = ahc_inb(ahc, INTSTAT);
+       }
+
+       if ((intstat & INT_PEND) == 0) {
+#if AHC_PCI_CONFIG > 0
+               if (ahc->unsolicited_ints > 500) {
+                       ahc->unsolicited_ints = 0;
+                       if ((ahc->chip & AHC_PCI) != 0
+                        && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0)
+                               ahc->bus_intr(ahc);
+               }
+#endif
+               ahc->unsolicited_ints++;
+               return (0);
+       }
+       ahc->unsolicited_ints = 0;
+
+       if (intstat & CMDCMPLT) {
+               ahc_outb(ahc, CLRINT, CLRCMDINT);
+
+               /*
+                * Ensure that the chip sees that we've cleared
+                * this interrupt before we walk the output fifo.
+                * Otherwise, we may, due to posted bus writes,
+                * clear the interrupt after we finish the scan,
+                * and after the sequencer has added new entries
+                * and asserted the interrupt again.
+                */
+               ahc_flush_device_writes(ahc);
+               ahc_run_qoutfifo(ahc);
+#ifdef AHC_TARGET_MODE
+               if ((ahc->flags & AHC_TARGETROLE) != 0)
+                       ahc_run_tqinfifo(ahc, /*paused*/FALSE);
+#endif
+       }
+
+       /*
+        * Handle statuses that may invalidate our cached
+        * copy of INTSTAT separately.
+        */
+       if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0) {
+               /* Hot eject.  Do nothing */
+       } else if (intstat & BRKADRINT) {
+               ahc_handle_brkadrint(ahc);
+       } else if ((intstat & (SEQINT|SCSIINT)) != 0) {
+
+               ahc_pause_bug_fix(ahc);
+
+               if ((intstat & SEQINT) != 0)
+                       ahc_handle_seqint(ahc, intstat);
+
+               if ((intstat & SCSIINT) != 0)
+                       ahc_handle_scsiint(ahc, intstat);
+       }
+       return (1);
+}
+
+/************************* Sequencer Execution Control ************************/
+/*
+ * Restart the sequencer program from address zero
+ */
+static void
 ahc_restart(struct ahc_softc *ahc)
 {
 
@@ -302,7 +872,7 @@ ahc_restart(struct ahc_softc *ahc)
 }
 
 /************************* Input/Output Queues ********************************/
-void
+static void
 ahc_run_qoutfifo(struct ahc_softc *ahc)
 {
        struct scb *scb;
@@ -349,7 +919,7 @@ ahc_run_qoutfifo(struct ahc_softc *ahc)
        }
 }
 
-void
+static void
 ahc_run_untagged_queues(struct ahc_softc *ahc)
 {
        int i;
@@ -358,7 +928,7 @@ ahc_run_untagged_queues(struct ahc_softc *ahc)
                ahc_run_untagged_queue(ahc, &ahc->untagged_queues[i]);
 }
 
-void
+static void
 ahc_run_untagged_queue(struct ahc_softc *ahc, struct scb_tailq *queue)
 {
        struct scb *scb;
@@ -374,7 +944,7 @@ ahc_run_untagged_queue(struct ahc_softc *ahc, struct scb_tailq *queue)
 }
 
 /************************* Interrupt Handling *********************************/
-void
+static void
 ahc_handle_brkadrint(struct ahc_softc *ahc)
 {
        /*
@@ -403,7 +973,7 @@ ahc_handle_brkadrint(struct ahc_softc *ahc)
        ahc_shutdown(ahc);
 }
 
-void
+static void
 ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
 {
        struct scb *scb;
@@ -954,7 +1524,7 @@ unpause:
        ahc_unpause(ahc);
 }
 
-void
+static void
 ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
 {
        u_int   scb_index;
@@ -1407,7 +1977,7 @@ ahc_force_renegotiation(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
 }
 
 #define AHC_MAX_STEPS 2000
-void
+static void
 ahc_clear_critical_section(struct ahc_softc *ahc)
 {
        int     stepping;
@@ -1500,7 +2070,7 @@ ahc_clear_critical_section(struct ahc_softc *ahc)
 /*
  * Clear any pending interrupt status.
  */
-void
+static void
 ahc_clear_intstat(struct ahc_softc *ahc)
 {
        /* Clear any interrupt conditions this may have caused */
@@ -1519,7 +2089,8 @@ ahc_clear_intstat(struct ahc_softc *ahc)
 uint32_t ahc_debug = AHC_DEBUG_OPTS;
 #endif
 
-void
+#if 0 /* unused */
+static void
 ahc_print_scb(struct scb *scb)
 {
        int i;
@@ -1551,6 +2122,7 @@ ahc_print_scb(struct scb *scb)
                }
        }
 }
+#endif
 
 /************************* Transfer Negotiation *******************************/
 /*
@@ -1634,7 +2206,7 @@ ahc_free_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel, int force)
  * by the capabilities of the bus connectivity of and sync settings for
  * the target.
  */
-struct ahc_syncrate *
+const struct ahc_syncrate *
 ahc_devlimited_syncrate(struct ahc_softc *ahc,
                        struct ahc_initiator_tinfo *tinfo,
                        u_int *period, u_int *ppr_options, role_t role)
@@ -1689,11 +2261,11 @@ ahc_devlimited_syncrate(struct ahc_softc *ahc,
  * Return the period and offset that should be sent to the target
  * if this was the beginning of an SDTR.
  */
-struct ahc_syncrate *
+const struct ahc_syncrate *
 ahc_find_syncrate(struct ahc_softc *ahc, u_int *period,
                  u_int *ppr_options, u_int maxsync)
 {
-       struct ahc_syncrate *syncrate;
+       const struct ahc_syncrate *syncrate;
 
        if ((ahc->features & AHC_DT) == 0)
                *ppr_options &= ~MSG_EXT_PPR_DT_REQ;
@@ -1768,7 +2340,7 @@ ahc_find_syncrate(struct ahc_softc *ahc, u_int *period,
 u_int
 ahc_find_period(struct ahc_softc *ahc, u_int scsirate, u_int maxsync)
 {
-       struct ahc_syncrate *syncrate;
+       const struct ahc_syncrate *syncrate;
 
        if ((ahc->features & AHC_ULTRA2) != 0)
                scsirate &= SXFR_ULTRA2;
@@ -1806,10 +2378,10 @@ ahc_find_period(struct ahc_softc *ahc, u_int scsirate, u_int maxsync)
  * Truncate the given synchronous offset to a value the
  * current adapter type and syncrate are capable of.
  */
-void
+static void
 ahc_validate_offset(struct ahc_softc *ahc,
                    struct ahc_initiator_tinfo *tinfo,
-                   struct ahc_syncrate *syncrate,
+                   const struct ahc_syncrate *syncrate,
                    u_int *offset, int wide, role_t role)
 {
        u_int maxoffset;
@@ -1838,7 +2410,7 @@ ahc_validate_offset(struct ahc_softc *ahc,
  * Truncate the given transfer width parameter to a value the
  * current adapter type is capable of.
  */
-void
+static void
 ahc_validate_width(struct ahc_softc *ahc, struct ahc_initiator_tinfo *tinfo,
                   u_int *bus_width, role_t role)
 {
@@ -1913,7 +2485,7 @@ ahc_update_neg_request(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
  */
 void
 ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
-                struct ahc_syncrate *syncrate, u_int period,
+                const struct ahc_syncrate *syncrate, u_int period,
                 u_int offset, u_int ppr_options, u_int type, int paused)
 {
        struct  ahc_initiator_tinfo *tinfo;
@@ -2220,11 +2792,11 @@ ahc_fetch_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
                            role);
 }
 
-struct ahc_phase_table_entry*
+static const struct ahc_phase_table_entry*
 ahc_lookup_phase_entry(int phase)
 {
-       struct ahc_phase_table_entry *entry;
-       struct ahc_phase_table_entry *last_entry;
+       const struct ahc_phase_table_entry *entry;
+       const struct ahc_phase_table_entry *last_entry;
 
        /*
         * num_phases doesn't include the default entry which
@@ -2390,7 +2962,7 @@ ahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
         */
        struct  ahc_initiator_tinfo *tinfo;
        struct  ahc_tmode_tstate *tstate;
-       struct  ahc_syncrate *rate;
+       const struct ahc_syncrate *rate;
        int     dowide;
        int     dosync;
        int     doppr;
@@ -2655,7 +3227,7 @@ proto_violation_reset:
  */
 static void
 ahc_handle_message_phase(struct ahc_softc *ahc)
-{ 
+{
        struct  ahc_devinfo devinfo;
        u_int   bus_phase;
        int     end_session;
@@ -3056,7 +3628,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
                switch (ahc->msgin_buf[2]) {
                case MSG_EXT_SDTR:
                {
-                       struct   ahc_syncrate *syncrate;
+                       const struct ahc_syncrate *syncrate;
                        u_int    period;
                        u_int    ppr_options;
                        u_int    offset;
@@ -3231,7 +3803,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
                }
                case MSG_EXT_PPR:
                {
-                       struct  ahc_syncrate *syncrate;
+                       const struct ahc_syncrate *syncrate;
                        u_int   period;
                        u_int   offset;
                        u_int   bus_width;
@@ -3984,7 +4556,7 @@ ahc_free(struct ahc_softc *ahc)
        return;
 }
 
-void
+static void
 ahc_shutdown(void *arg)
 {
        struct  ahc_softc *ahc;
@@ -4388,7 +4960,7 @@ ahc_fini_scbdata(struct ahc_softc *ahc)
                free(scb_data->scbarray, M_DEVBUF);
 }
 
-void
+static void
 ahc_alloc_scbs(struct ahc_softc *ahc)
 {
        struct scb_data *scb_data;
@@ -5121,7 +5693,7 @@ ahc_resume(struct ahc_softc *ahc)
  * Return the untagged transaction id for a given target/channel lun.
  * Optionally, clear the entry.
  */
-u_int
+static u_int
 ahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl)
 {
        u_int scbid;
@@ -5142,7 +5714,7 @@ ahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl)
        return (scbid);
 }
 
-void
+static void
 ahc_unbusy_tcl(struct ahc_softc *ahc, u_int tcl)
 {
        u_int target_offset;
@@ -5160,7 +5732,7 @@ ahc_unbusy_tcl(struct ahc_softc *ahc, u_int tcl)
        }
 }
 
-void
+static void
 ahc_busy_tcl(struct ahc_softc *ahc, u_int tcl, u_int scbid)
 {
        u_int target_offset;
@@ -5215,7 +5787,7 @@ ahc_match_scb(struct ahc_softc *ahc, struct scb *scb, int target,
        return match;
 }
 
-void
+static void
 ahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb)
 {
        int     target;
@@ -5707,7 +6279,7 @@ ahc_add_curscb_to_free_list(struct ahc_softc *ahc)
  */
 static u_int
 ahc_rem_wscb(struct ahc_softc *ahc, u_int scbpos, u_int prev)
-{       
+{
        u_int curscb, next;
 
        /*
@@ -5756,7 +6328,7 @@ ahc_rem_wscb(struct ahc_softc *ahc, u_int scbpos, u_int prev)
  * been modified from CAM_REQ_INPROG.  This routine assumes that the sequencer
  * is paused before it is called.
  */
-int
+static int
 ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel,
               int lun, u_int tag, role_t role, uint32_t status)
 {
@@ -6078,7 +6650,7 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset)
 /*
  * Calculate the residual for a just completed SCB.
  */
-void
+static void
 ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb)
 {
        struct hardware_scb *hscb;
@@ -6279,7 +6851,7 @@ ahc_loadseq(struct ahc_softc *ahc)
        struct  cs cs_table[num_critical_sections];
        u_int   begin_set[num_critical_sections];
        u_int   end_set[num_critical_sections];
-       struct  patch *cur_patch;
+       const struct patch *cur_patch;
        u_int   cs_count;
        u_int   cur_cs;
        u_int   i;
@@ -6384,11 +6956,11 @@ ahc_loadseq(struct ahc_softc *ahc)
 }
 
 static int
-ahc_check_patch(struct ahc_softc *ahc, struct patch **start_patch,
+ahc_check_patch(struct ahc_softc *ahc, const struct patch **start_patch,
                u_int start_instr, u_int *skip_addr)
 {
-       struct  patch *cur_patch;
-       struct  patch *last_patch;
+       const struct patch *cur_patch;
+       const struct patch *last_patch;
        u_int   num_patches;
 
        num_patches = ARRAY_SIZE(patches);
@@ -6447,7 +7019,7 @@ ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts)
        case AIC_OP_JE:
        case AIC_OP_JZ:
        {
-               struct patch *cur_patch;
+               const struct patch *cur_patch;
                int address_offset;
                u_int address;
                u_int skip_addr;
@@ -6545,7 +7117,7 @@ ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts)
 }
 
 int
-ahc_print_register(ahc_reg_parse_entry_t *table, u_int num_entries,
+ahc_print_register(const ahc_reg_parse_entry_t *table, u_int num_entries,
                   const char *name, u_int address, u_int value,
                   u_int *cur_column, u_int wrap_point)
 {
@@ -7229,7 +7801,7 @@ ahc_update_scsiid(struct ahc_softc *ahc, u_int targid_mask)
                ahc_outb(ahc, SCSIID, scsiid);
 }
 
-void
+static void
 ahc_run_tqinfifo(struct ahc_softc *ahc, int paused)
 {
        struct target_cmd *cmd;
index cba2f23bbe7954974aab44408b480269d16bae92..09bf2f4d78d58d953a5b025bf3201aaf8fd76441 100644 (file)
 #define _AIC7XXX_INLINE_H_
 
 /************************* Sequencer Execution Control ************************/
-static __inline void ahc_pause_bug_fix(struct ahc_softc *ahc);
-static __inline int  ahc_is_paused(struct ahc_softc *ahc);
-static __inline void ahc_pause(struct ahc_softc *ahc);
-static __inline void ahc_unpause(struct ahc_softc *ahc);
-
-/*
- * Work around any chip bugs related to halting sequencer execution.
- * On Ultra2 controllers, we must clear the CIOBUS stretch signal by
- * reading a register that will set this signal and deassert it.
- * Without this workaround, if the chip is paused, by an interrupt or
- * manual pause while accessing scb ram, accesses to certain registers
- * will hang the system (infinite pci retries).
- */
-static __inline void
-ahc_pause_bug_fix(struct ahc_softc *ahc)
-{
-       if ((ahc->features & AHC_ULTRA2) != 0)
-               (void)ahc_inb(ahc, CCSCBCTL);
-}
-
-/*
- * Determine whether the sequencer has halted code execution.
- * Returns non-zero status if the sequencer is stopped.
- */
-static __inline int
-ahc_is_paused(struct ahc_softc *ahc)
-{
-       return ((ahc_inb(ahc, HCNTRL) & PAUSE) != 0);
-}
-
-/*
- * Request that the sequencer stop and wait, indefinitely, for it
- * to stop.  The sequencer will only acknowledge that it is paused
- * once it has reached an instruction boundary and PAUSEDIS is
- * cleared in the SEQCTL register.  The sequencer may use PAUSEDIS
- * for critical sections.
- */
-static __inline void
-ahc_pause(struct ahc_softc *ahc)
-{
-       ahc_outb(ahc, HCNTRL, ahc->pause);
-
-       /*
-        * Since the sequencer can disable pausing in a critical section, we
-        * must loop until it actually stops.
-        */
-       while (ahc_is_paused(ahc) == 0)
-               ;
-
-       ahc_pause_bug_fix(ahc);
-}
-
-/*
- * Allow the sequencer to continue program execution.
- * We check here to ensure that no additional interrupt
- * sources that would cause the sequencer to halt have been
- * asserted.  If, for example, a SCSI bus reset is detected
- * while we are fielding a different, pausing, interrupt type,
- * we don't want to release the sequencer before going back
- * into our interrupt handler and dealing with this new
- * condition.
- */
-static __inline void
-ahc_unpause(struct ahc_softc *ahc)
-{
-       if ((ahc_inb(ahc, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) == 0)
-               ahc_outb(ahc, HCNTRL, ahc->unpause);
-}
-
-/*********************** Untagged Transaction Routines ************************/
-static __inline void   ahc_freeze_untagged_queues(struct ahc_softc *ahc);
-static __inline void   ahc_release_untagged_queues(struct ahc_softc *ahc);
-
-/*
- * Block our completion routine from starting the next untagged
- * transaction for this target or target lun.
- */
-static __inline void
-ahc_freeze_untagged_queues(struct ahc_softc *ahc)
-{
-       if ((ahc->flags & AHC_SCB_BTT) == 0)
-               ahc->untagged_queue_lock++;
-}
-
-/*
- * Allow the next untagged transaction for this target or target lun
- * to be executed.  We use a counting semaphore to allow the lock
- * to be acquired recursively.  Once the count drops to zero, the
- * transaction queues will be run.
- */
-static __inline void
-ahc_release_untagged_queues(struct ahc_softc *ahc)
-{
-       if ((ahc->flags & AHC_SCB_BTT) == 0) {
-               ahc->untagged_queue_lock--;
-               if (ahc->untagged_queue_lock == 0)
-                       ahc_run_untagged_queues(ahc);
-       }
-}
+int  ahc_is_paused(struct ahc_softc *ahc);
+void ahc_pause(struct ahc_softc *ahc);
+void ahc_unpause(struct ahc_softc *ahc);
 
 /************************** Memory mapping routines ***************************/
-static __inline struct ahc_dma_seg *
-                       ahc_sg_bus_to_virt(struct scb *scb,
-                                          uint32_t sg_busaddr);
-static __inline uint32_t
-                       ahc_sg_virt_to_bus(struct scb *scb,
-                                          struct ahc_dma_seg *sg);
-static __inline uint32_t
-                       ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index);
-static __inline void   ahc_sync_scb(struct ahc_softc *ahc,
-                                    struct scb *scb, int op);
-static __inline void   ahc_sync_sglist(struct ahc_softc *ahc,
-                                       struct scb *scb, int op);
-static __inline uint32_t
-                       ahc_targetcmd_offset(struct ahc_softc *ahc,
-                                            u_int index);
-
-static __inline struct ahc_dma_seg *
-ahc_sg_bus_to_virt(struct scb *scb, uint32_t sg_busaddr)
-{
-       int sg_index;
-
-       sg_index = (sg_busaddr - scb->sg_list_phys)/sizeof(struct ahc_dma_seg);
-       /* sg_list_phys points to entry 1, not 0 */
-       sg_index++;
-
-       return (&scb->sg_list[sg_index]);
-}
-
-static __inline uint32_t
-ahc_sg_virt_to_bus(struct scb *scb, struct ahc_dma_seg *sg)
-{
-       int sg_index;
-
-       /* sg_list_phys points to entry 1, not 0 */
-       sg_index = sg - &scb->sg_list[1];
-
-       return (scb->sg_list_phys + (sg_index * sizeof(*scb->sg_list)));
-}
-
-static __inline uint32_t
-ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index)
-{
-       return (ahc->scb_data->hscb_busaddr
-               + (sizeof(struct hardware_scb) * index));
-}
-
-static __inline void
-ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op)
-{
-       ahc_dmamap_sync(ahc, ahc->scb_data->hscb_dmat,
-                       ahc->scb_data->hscb_dmamap,
-                       /*offset*/(scb->hscb - ahc->hscbs) * sizeof(*scb->hscb),
-                       /*len*/sizeof(*scb->hscb), op);
-}
-
-static __inline void
-ahc_sync_sglist(struct ahc_softc *ahc, struct scb *scb, int op)
-{
-       if (scb->sg_count == 0)
-               return;
-
-       ahc_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap,
-                       /*offset*/(scb->sg_list - scb->sg_map->sg_vaddr)
-                               * sizeof(struct ahc_dma_seg),
-                       /*len*/sizeof(struct ahc_dma_seg) * scb->sg_count, op);
-}
-
-static __inline uint32_t
-ahc_targetcmd_offset(struct ahc_softc *ahc, u_int index)
-{
-       return (((uint8_t *)&ahc->targetcmds[index]) - ahc->qoutfifo);
-}
+void   ahc_sync_sglist(struct ahc_softc *ahc,
+                       struct scb *scb, int op);
 
 /******************************** Debugging ***********************************/
 static __inline char *ahc_name(struct ahc_softc *ahc);
@@ -231,420 +65,34 @@ ahc_name(struct ahc_softc *ahc)
 
 /*********************** Miscellaneous Support Functions ***********************/
 
-static __inline void   ahc_update_residual(struct ahc_softc *ahc,
-                                           struct scb *scb);
-static __inline struct ahc_initiator_tinfo *
-                       ahc_fetch_transinfo(struct ahc_softc *ahc,
-                                           char channel, u_int our_id,
-                                           u_int remote_id,
-                                           struct ahc_tmode_tstate **tstate);
-static __inline uint16_t
-                       ahc_inw(struct ahc_softc *ahc, u_int port);
-static __inline void   ahc_outw(struct ahc_softc *ahc, u_int port,
-                                u_int value);
-static __inline uint32_t
-                       ahc_inl(struct ahc_softc *ahc, u_int port);
-static __inline void   ahc_outl(struct ahc_softc *ahc, u_int port,
-                                uint32_t value);
-static __inline uint64_t
-                       ahc_inq(struct ahc_softc *ahc, u_int port);
-static __inline void   ahc_outq(struct ahc_softc *ahc, u_int port,
-                                uint64_t value);
-static __inline struct scb*
-                       ahc_get_scb(struct ahc_softc *ahc);
-static __inline void   ahc_free_scb(struct ahc_softc *ahc, struct scb *scb);
-static __inline void   ahc_swap_with_next_hscb(struct ahc_softc *ahc,
-                                               struct scb *scb);
-static __inline void   ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb);
-static __inline struct scsi_sense_data *
-                       ahc_get_sense_buf(struct ahc_softc *ahc,
-                                         struct scb *scb);
-static __inline uint32_t
-                       ahc_get_sense_bufaddr(struct ahc_softc *ahc,
-                                             struct scb *scb);
-
-/*
- * Determine whether the sequencer reported a residual
- * for this SCB/transaction.
- */
-static __inline void
-ahc_update_residual(struct ahc_softc *ahc, struct scb *scb)
-{
-       uint32_t sgptr;
-
-       sgptr = ahc_le32toh(scb->hscb->sgptr);
-       if ((sgptr & SG_RESID_VALID) != 0)
-               ahc_calc_residual(ahc, scb);
-}
-
-/*
- * Return pointers to the transfer negotiation information
- * for the specified our_id/remote_id pair.
- */
-static __inline struct ahc_initiator_tinfo *
-ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id,
-                   u_int remote_id, struct ahc_tmode_tstate **tstate)
-{
-       /*
-        * Transfer data structures are stored from the perspective
-        * of the target role.  Since the parameters for a connection
-        * in the initiator role to a given target are the same as
-        * when the roles are reversed, we pretend we are the target.
-        */
-       if (channel == 'B')
-               our_id += 8;
-       *tstate = ahc->enabled_targets[our_id];
-       return (&(*tstate)->transinfo[remote_id]);
-}
-
-static __inline uint16_t
-ahc_inw(struct ahc_softc *ahc, u_int port)
-{
-       uint16_t r = ahc_inb(ahc, port+1) << 8;
-       return r | ahc_inb(ahc, port);
-}
-
-static __inline void
-ahc_outw(struct ahc_softc *ahc, u_int port, u_int value)
-{
-       ahc_outb(ahc, port, value & 0xFF);
-       ahc_outb(ahc, port+1, (value >> 8) & 0xFF);
-}
-
-static __inline uint32_t
-ahc_inl(struct ahc_softc *ahc, u_int port)
-{
-       return ((ahc_inb(ahc, port))
-             | (ahc_inb(ahc, port+1) << 8)
-             | (ahc_inb(ahc, port+2) << 16)
-             | (ahc_inb(ahc, port+3) << 24));
-}
-
-static __inline void
-ahc_outl(struct ahc_softc *ahc, u_int port, uint32_t value)
-{
-       ahc_outb(ahc, port, (value) & 0xFF);
-       ahc_outb(ahc, port+1, ((value) >> 8) & 0xFF);
-       ahc_outb(ahc, port+2, ((value) >> 16) & 0xFF);
-       ahc_outb(ahc, port+3, ((value) >> 24) & 0xFF);
-}
-
-static __inline uint64_t
-ahc_inq(struct ahc_softc *ahc, u_int port)
-{
-       return ((ahc_inb(ahc, port))
-             | (ahc_inb(ahc, port+1) << 8)
-             | (ahc_inb(ahc, port+2) << 16)
-             | (ahc_inb(ahc, port+3) << 24)
-             | (((uint64_t)ahc_inb(ahc, port+4)) << 32)
-             | (((uint64_t)ahc_inb(ahc, port+5)) << 40)
-             | (((uint64_t)ahc_inb(ahc, port+6)) << 48)
-             | (((uint64_t)ahc_inb(ahc, port+7)) << 56));
-}
-
-static __inline void
-ahc_outq(struct ahc_softc *ahc, u_int port, uint64_t value)
-{
-       ahc_outb(ahc, port, value & 0xFF);
-       ahc_outb(ahc, port+1, (value >> 8) & 0xFF);
-       ahc_outb(ahc, port+2, (value >> 16) & 0xFF);
-       ahc_outb(ahc, port+3, (value >> 24) & 0xFF);
-       ahc_outb(ahc, port+4, (value >> 32) & 0xFF);
-       ahc_outb(ahc, port+5, (value >> 40) & 0xFF);
-       ahc_outb(ahc, port+6, (value >> 48) & 0xFF);
-       ahc_outb(ahc, port+7, (value >> 56) & 0xFF);
-}
-
-/*
- * Get a free scb. If there are none, see if we can allocate a new SCB.
- */
-static __inline struct scb *
-ahc_get_scb(struct ahc_softc *ahc)
-{
-       struct scb *scb;
-
-       if ((scb = SLIST_FIRST(&ahc->scb_data->free_scbs)) == NULL) {
-               ahc_alloc_scbs(ahc);
-               scb = SLIST_FIRST(&ahc->scb_data->free_scbs);
-               if (scb == NULL)
-                       return (NULL);
-       }
-       SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links.sle);
-       return (scb);
-}
-
-/*
- * Return an SCB resource to the free list.
- */
-static __inline void
-ahc_free_scb(struct ahc_softc *ahc, struct scb *scb)
-{       
-       struct hardware_scb *hscb;
-
-       hscb = scb->hscb;
-       /* Clean up for the next user */
-       ahc->scb_data->scbindex[hscb->tag] = NULL;
-       scb->flags = SCB_FREE;
-       hscb->control = 0;
-
-       SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle);
-
-       /* Notify the OSM that a resource is now available. */
-       ahc_platform_scb_free(ahc, scb);
-}
-
-static __inline struct scb *
-ahc_lookup_scb(struct ahc_softc *ahc, u_int tag)
-{
-       struct scb* scb;
-
-       scb = ahc->scb_data->scbindex[tag];
-       if (scb != NULL)
-               ahc_sync_scb(ahc, scb,
-                            BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
-       return (scb);
-}
-
-static __inline void
-ahc_swap_with_next_hscb(struct ahc_softc *ahc, struct scb *scb)
-{
-       struct hardware_scb *q_hscb;
-       u_int  saved_tag;
-
-       /*
-        * Our queuing method is a bit tricky.  The card
-        * knows in advance which HSCB to download, and we
-        * can't disappoint it.  To achieve this, the next
-        * SCB to download is saved off in ahc->next_queued_scb.
-        * When we are called to queue "an arbitrary scb",
-        * we copy the contents of the incoming HSCB to the one
-        * the sequencer knows about, swap HSCB pointers and
-        * finally assign the SCB to the tag indexed location
-        * in the scb_array.  This makes sure that we can still
-        * locate the correct SCB by SCB_TAG.
-        */
-       q_hscb = ahc->next_queued_scb->hscb;
-       saved_tag = q_hscb->tag;
-       memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
-       if ((scb->flags & SCB_CDB32_PTR) != 0) {
-               q_hscb->shared_data.cdb_ptr =
-                   ahc_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag)
-                             + offsetof(struct hardware_scb, cdb32));
-       }
-       q_hscb->tag = saved_tag;
-       q_hscb->next = scb->hscb->tag;
-
-       /* Now swap HSCB pointers. */
-       ahc->next_queued_scb->hscb = scb->hscb;
-       scb->hscb = q_hscb;
-
-       /* Now define the mapping from tag to SCB in the scbindex */
-       ahc->scb_data->scbindex[scb->hscb->tag] = scb;
-}
-
-/*
- * Tell the sequencer about a new transaction to execute.
- */
-static __inline void
-ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb)
-{
-       ahc_swap_with_next_hscb(ahc, scb);
-
-       if (scb->hscb->tag == SCB_LIST_NULL
-        || scb->hscb->next == SCB_LIST_NULL)
-               panic("Attempt to queue invalid SCB tag %x:%x\n",
-                     scb->hscb->tag, scb->hscb->next);
-
-       /*
-        * Setup data "oddness".
-        */
-       scb->hscb->lun &= LID;
-       if (ahc_get_transfer_length(scb) & 0x1)
-               scb->hscb->lun |= SCB_XFERLEN_ODD;
-
-       /*
-        * Keep a history of SCBs we've downloaded in the qinfifo.
-        */
-       ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag;
-
-       /*
-        * Make sure our data is consistent from the
-        * perspective of the adapter.
-        */
-       ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
-
-       /* Tell the adapter about the newly queued SCB */
-       if ((ahc->features & AHC_QUEUE_REGS) != 0) {
-               ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
-       } else {
-               if ((ahc->features & AHC_AUTOPAUSE) == 0)
-                       ahc_pause(ahc);
-               ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext);
-               if ((ahc->features & AHC_AUTOPAUSE) == 0)
-                       ahc_unpause(ahc);
-       }
-}
-
-static __inline struct scsi_sense_data *
-ahc_get_sense_buf(struct ahc_softc *ahc, struct scb *scb)
-{
-       int offset;
-
-       offset = scb - ahc->scb_data->scbarray;
-       return (&ahc->scb_data->sense[offset]);
-}
-
-static __inline uint32_t
-ahc_get_sense_bufaddr(struct ahc_softc *ahc, struct scb *scb)
-{
-       int offset;
-
-       offset = scb - ahc->scb_data->scbarray;
-       return (ahc->scb_data->sense_busaddr
-             + (offset * sizeof(struct scsi_sense_data)));
-}
+struct ahc_initiator_tinfo *
+       ahc_fetch_transinfo(struct ahc_softc *ahc,
+                           char channel, u_int our_id,
+                           u_int remote_id,
+                           struct ahc_tmode_tstate **tstate);
+uint16_t
+       ahc_inw(struct ahc_softc *ahc, u_int port);
+void   ahc_outw(struct ahc_softc *ahc, u_int port,
+                u_int value);
+uint32_t
+       ahc_inl(struct ahc_softc *ahc, u_int port);
+void   ahc_outl(struct ahc_softc *ahc, u_int port,
+                uint32_t value);
+uint64_t
+       ahc_inq(struct ahc_softc *ahc, u_int port);
+void   ahc_outq(struct ahc_softc *ahc, u_int port,
+                uint64_t value);
+struct scb*
+       ahc_get_scb(struct ahc_softc *ahc);
+void   ahc_free_scb(struct ahc_softc *ahc, struct scb *scb);
+struct scb *
+       ahc_lookup_scb(struct ahc_softc *ahc, u_int tag);
+void   ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb);
+struct scsi_sense_data *
+       ahc_get_sense_buf(struct ahc_softc *ahc,
+                         struct scb *scb);
 
 /************************** Interrupt Processing ******************************/
-static __inline void   ahc_sync_qoutfifo(struct ahc_softc *ahc, int op);
-static __inline void   ahc_sync_tqinfifo(struct ahc_softc *ahc, int op);
-static __inline u_int  ahc_check_cmdcmpltqueues(struct ahc_softc *ahc);
-static __inline int    ahc_intr(struct ahc_softc *ahc);
-
-static __inline void
-ahc_sync_qoutfifo(struct ahc_softc *ahc, int op)
-{
-       ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
-                       /*offset*/0, /*len*/256, op);
-}
-
-static __inline void
-ahc_sync_tqinfifo(struct ahc_softc *ahc, int op)
-{
-#ifdef AHC_TARGET_MODE
-       if ((ahc->flags & AHC_TARGETROLE) != 0) {
-               ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
-                               ahc->shared_data_dmamap,
-                               ahc_targetcmd_offset(ahc, 0),
-                               sizeof(struct target_cmd) * AHC_TMODE_CMDS,
-                               op);
-       }
-#endif
-}
-
-/*
- * See if the firmware has posted any completed commands
- * into our in-core command complete fifos.
- */
-#define AHC_RUN_QOUTFIFO 0x1
-#define AHC_RUN_TQINFIFO 0x2
-static __inline u_int
-ahc_check_cmdcmpltqueues(struct ahc_softc *ahc)
-{
-       u_int retval;
-
-       retval = 0;
-       ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
-                       /*offset*/ahc->qoutfifonext, /*len*/1,
-                       BUS_DMASYNC_POSTREAD);
-       if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL)
-               retval |= AHC_RUN_QOUTFIFO;
-#ifdef AHC_TARGET_MODE
-       if ((ahc->flags & AHC_TARGETROLE) != 0
-        && (ahc->flags & AHC_TQINFIFO_BLOCKED) == 0) {
-               ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
-                               ahc->shared_data_dmamap,
-                               ahc_targetcmd_offset(ahc, ahc->tqinfifofnext),
-                               /*len*/sizeof(struct target_cmd),
-                               BUS_DMASYNC_POSTREAD);
-               if (ahc->targetcmds[ahc->tqinfifonext].cmd_valid != 0)
-                       retval |= AHC_RUN_TQINFIFO;
-       }
-#endif
-       return (retval);
-}
-
-/*
- * Catch an interrupt from the adapter
- */
-static __inline int
-ahc_intr(struct ahc_softc *ahc)
-{
-       u_int   intstat;
-
-       if ((ahc->pause & INTEN) == 0) {
-               /*
-                * Our interrupt is not enabled on the chip
-                * and may be disabled for re-entrancy reasons,
-                * so just return.  This is likely just a shared
-                * interrupt.
-                */
-               return (0);
-       }
-       /*
-        * Instead of directly reading the interrupt status register,
-        * infer the cause of the interrupt by checking our in-core
-        * completion queues.  This avoids a costly PCI bus read in
-        * most cases.
-        */
-       if ((ahc->flags & (AHC_ALL_INTERRUPTS|AHC_EDGE_INTERRUPT)) == 0
-        && (ahc_check_cmdcmpltqueues(ahc) != 0))
-               intstat = CMDCMPLT;
-       else {
-               intstat = ahc_inb(ahc, INTSTAT);
-       }
-
-       if ((intstat & INT_PEND) == 0) {
-#if AHC_PCI_CONFIG > 0
-               if (ahc->unsolicited_ints > 500) {
-                       ahc->unsolicited_ints = 0;
-                       if ((ahc->chip & AHC_PCI) != 0
-                        && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0)
-                               ahc->bus_intr(ahc);
-               }
-#endif
-               ahc->unsolicited_ints++;
-               return (0);
-       }
-       ahc->unsolicited_ints = 0;
-
-       if (intstat & CMDCMPLT) {
-               ahc_outb(ahc, CLRINT, CLRCMDINT);
-
-               /*
-                * Ensure that the chip sees that we've cleared
-                * this interrupt before we walk the output fifo.
-                * Otherwise, we may, due to posted bus writes,
-                * clear the interrupt after we finish the scan,
-                * and after the sequencer has added new entries
-                * and asserted the interrupt again.
-                */
-               ahc_flush_device_writes(ahc);
-               ahc_run_qoutfifo(ahc);
-#ifdef AHC_TARGET_MODE
-               if ((ahc->flags & AHC_TARGETROLE) != 0)
-                       ahc_run_tqinfifo(ahc, /*paused*/FALSE);
-#endif
-       }
-
-       /*
-        * Handle statuses that may invalidate our cached
-        * copy of INTSTAT separately.
-        */
-       if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0) {
-               /* Hot eject.  Do nothing */
-       } else if (intstat & BRKADRINT) {
-               ahc_handle_brkadrint(ahc);
-       } else if ((intstat & (SEQINT|SCSIINT)) != 0) {
-
-               ahc_pause_bug_fix(ahc);
-
-               if ((intstat & SEQINT) != 0)
-                       ahc_handle_seqint(ahc, intstat);
-
-               if ((intstat & SCSIINT) != 0)
-                       ahc_handle_scsiint(ahc, intstat);
-       }
-       return (1);
-}
+int    ahc_intr(struct ahc_softc *ahc);
 
 #endif  /* _AIC7XXX_INLINE_H_ */
index 42ad48e09f022ae4409338a225a818c111527611..fd2b9785ff4fe9aa452cf86cb21ab14f31beb072 100644 (file)
@@ -388,14 +388,83 @@ static int  aic7xxx_setup(char *s);
 static int ahc_linux_unit;
 
 
+/************************** OS Utility Wrappers *******************************/
+void
+ahc_delay(long usec)
+{
+       /*
+        * udelay on Linux can have problems for
+        * multi-millisecond waits.  Wait at most
+        * 1024us per call.
+        */
+       while (usec > 0) {
+               udelay(usec % 1024);
+               usec -= 1024;
+       }
+}
+
+/***************************** Low Level I/O **********************************/
+uint8_t
+ahc_inb(struct ahc_softc * ahc, long port)
+{
+       uint8_t x;
+
+       if (ahc->tag == BUS_SPACE_MEMIO) {
+               x = readb(ahc->bsh.maddr + port);
+       } else {
+               x = inb(ahc->bsh.ioport + port);
+       }
+       mb();
+       return (x);
+}
+
+void
+ahc_outb(struct ahc_softc * ahc, long port, uint8_t val)
+{
+       if (ahc->tag == BUS_SPACE_MEMIO) {
+               writeb(val, ahc->bsh.maddr + port);
+       } else {
+               outb(val, ahc->bsh.ioport + port);
+       }
+       mb();
+}
+
+void
+ahc_outsb(struct ahc_softc * ahc, long port, uint8_t *array, int count)
+{
+       int i;
+
+       /*
+        * There is probably a more efficient way to do this on Linux
+        * but we don't use this for anything speed critical and this
+        * should work.
+        */
+       for (i = 0; i < count; i++)
+               ahc_outb(ahc, port, *array++);
+}
+
+void
+ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int count)
+{
+       int i;
+
+       /*
+        * There is probably a more efficient way to do this on Linux
+        * but we don't use this for anything speed critical and this
+        * should work.
+        */
+       for (i = 0; i < count; i++)
+               *array++ = ahc_inb(ahc, port);
+}
+
 /********************************* Inlines ************************************/
-static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*);
+static void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*);
 
-static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
+static int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
                                      struct ahc_dma_seg *sg,
                                      dma_addr_t addr, bus_size_t len);
 
-static __inline void
+static void
 ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb)
 {
        struct scsi_cmnd *cmd;
@@ -406,7 +475,7 @@ ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb)
        scsi_dma_unmap(cmd);
 }
 
-static __inline int
+static int
 ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
                  struct ahc_dma_seg *sg, dma_addr_t addr, bus_size_t len)
 {
@@ -442,13 +511,11 @@ ahc_linux_info(struct Scsi_Host *host)
        bp = &buffer[0];
        ahc = *(struct ahc_softc **)host->hostdata;
        memset(bp, 0, sizeof(buffer));
-       strcpy(bp, "Adaptec AIC7XXX EISA/VLB/PCI SCSI HBA DRIVER, Rev ");
-       strcat(bp, AIC7XXX_DRIVER_VERSION);
-       strcat(bp, "\n");
-       strcat(bp, "        <");
+       strcpy(bp, "Adaptec AIC7XXX EISA/VLB/PCI SCSI HBA DRIVER, Rev " AIC7XXX_DRIVER_VERSION "\n"
+                       "        <");
        strcat(bp, ahc->description);
-       strcat(bp, ">\n");
-       strcat(bp, "        ");
+       strcat(bp, ">\n"
+                       "        ");
        ahc_controller_info(ahc, ahc_info);
        strcat(bp, ahc_info);
        strcat(bp, "\n");
@@ -964,7 +1031,7 @@ aic7xxx_setup(char *s)
        char   *p;
        char   *end;
 
-       static struct {
+       static const struct {
                const char *name;
                uint32_t *flag;
        } options[] = {
@@ -2317,7 +2384,7 @@ static void ahc_linux_set_period(struct scsi_target *starget, int period)
        unsigned int ppr_options = tinfo->goal.ppr_options;
        unsigned long flags;
        unsigned long offset = tinfo->goal.offset;
-       struct ahc_syncrate *syncrate;
+       const struct ahc_syncrate *syncrate;
 
        if (offset == 0)
                offset = MAX_OFFSET;
@@ -2361,7 +2428,7 @@ static void ahc_linux_set_offset(struct scsi_target *starget, int offset)
        unsigned int ppr_options = 0;
        unsigned int period = 0;
        unsigned long flags;
-       struct ahc_syncrate *syncrate = NULL;
+       const struct ahc_syncrate *syncrate = NULL;
 
        ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
                            starget->channel + 'A', ROLE_INITIATOR);
@@ -2391,7 +2458,7 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt)
        unsigned int period = tinfo->goal.period;
        unsigned int width = tinfo->goal.width;
        unsigned long flags;
-       struct ahc_syncrate *syncrate;
+       const struct ahc_syncrate *syncrate;
 
        if (dt && spi_max_width(starget)) {
                ppr_options |= MSG_EXT_PPR_DT_REQ;
index b48dab447bde6cdc185fef846bba132677c3af1d..3f7238db35e5f129b693ed356e33d37cb6f9d49f 100644 (file)
@@ -365,7 +365,7 @@ struct ahc_platform_data {
 #define AHC_LINUX_NOIRQ        ((uint32_t)~0)
        uint32_t                 irq;           /* IRQ for this adapter */
        uint32_t                 bios_address;
-       uint32_t                 mem_busaddr;   /* Mem Base Addr */
+       resource_size_t          mem_busaddr;   /* Mem Base Addr */
 };
 
 /************************** OS Utility Wrappers *******************************/
@@ -375,82 +375,16 @@ struct ahc_platform_data {
 #define malloc(size, type, flags) kmalloc(size, flags)
 #define free(ptr, type) kfree(ptr)
 
-static __inline void ahc_delay(long);
-static __inline void
-ahc_delay(long usec)
-{
-       /*
-        * udelay on Linux can have problems for
-        * multi-millisecond waits.  Wait at most
-        * 1024us per call.
-        */
-       while (usec > 0) {
-               udelay(usec % 1024);
-               usec -= 1024;
-       }
-}
+void ahc_delay(long);
 
 
 /***************************** Low Level I/O **********************************/
-static __inline uint8_t ahc_inb(struct ahc_softc * ahc, long port);
-static __inline void ahc_outb(struct ahc_softc * ahc, long port, uint8_t val);
-static __inline void ahc_outsb(struct ahc_softc * ahc, long port,
-                              uint8_t *, int count);
-static __inline void ahc_insb(struct ahc_softc * ahc, long port,
-                              uint8_t *, int count);
-
-static __inline uint8_t
-ahc_inb(struct ahc_softc * ahc, long port)
-{
-       uint8_t x;
-
-       if (ahc->tag == BUS_SPACE_MEMIO) {
-               x = readb(ahc->bsh.maddr + port);
-       } else {
-               x = inb(ahc->bsh.ioport + port);
-       }
-       mb();
-       return (x);
-}
-
-static __inline void
-ahc_outb(struct ahc_softc * ahc, long port, uint8_t val)
-{
-       if (ahc->tag == BUS_SPACE_MEMIO) {
-               writeb(val, ahc->bsh.maddr + port);
-       } else {
-               outb(val, ahc->bsh.ioport + port);
-       }
-       mb();
-}
-
-static __inline void
-ahc_outsb(struct ahc_softc * ahc, long port, uint8_t *array, int count)
-{
-       int i;
-
-       /*
-        * There is probably a more efficient way to do this on Linux
-        * but we don't use this for anything speed critical and this
-        * should work.
-        */
-       for (i = 0; i < count; i++)
-               ahc_outb(ahc, port, *array++);
-}
-
-static __inline void
-ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int count)
-{
-       int i;
-
-       /*
-        * There is probably a more efficient way to do this on Linux
-        * but we don't use this for anything speed critical and this
-        * should work.
-        */
-       for (i = 0; i < count; i++)
-               *array++ = ahc_inb(ahc, port);
-}
+uint8_t ahc_inb(struct ahc_softc * ahc, long port);
+void ahc_outb(struct ahc_softc * ahc, long port, uint8_t val);
+void ahc_outsb(struct ahc_softc * ahc, long port,
+              uint8_t *, int count);
+void ahc_insb(struct ahc_softc * ahc, long port,
+              uint8_t *, int count);
 
 /**************************** Initialization **********************************/
 int            ahc_linux_register_host(struct ahc_softc *,
@@ -464,9 +398,6 @@ struct info_str {
        int pos;
 };
 
-void   ahc_format_transinfo(struct info_str *info,
-                            struct ahc_transinfo *tinfo);
-
 /******************************** Locking *************************************/
 /* Lock protecting internal data structures */
 
@@ -555,61 +486,12 @@ void                       ahc_linux_pci_exit(void);
 int                     ahc_pci_map_registers(struct ahc_softc *ahc);
 int                     ahc_pci_map_int(struct ahc_softc *ahc);
 
-static __inline uint32_t ahc_pci_read_config(ahc_dev_softc_t pci,
+uint32_t                ahc_pci_read_config(ahc_dev_softc_t pci,
                                             int reg, int width);
 
-static __inline uint32_t
-ahc_pci_read_config(ahc_dev_softc_t pci, int reg, int width)
-{
-       switch (width) {
-       case 1:
-       {
-               uint8_t retval;
-
-               pci_read_config_byte(pci, reg, &retval);
-               return (retval);
-       }
-       case 2:
-       {
-               uint16_t retval;
-               pci_read_config_word(pci, reg, &retval);
-               return (retval);
-       }
-       case 4:
-       {
-               uint32_t retval;
-               pci_read_config_dword(pci, reg, &retval);
-               return (retval);
-       }
-       default:
-               panic("ahc_pci_read_config: Read size too big");
-               /* NOTREACHED */
-               return (0);
-       }
-}
-
-static __inline void ahc_pci_write_config(ahc_dev_softc_t pci,
-                                         int reg, uint32_t value,
-                                         int width);
-
-static __inline void
-ahc_pci_write_config(ahc_dev_softc_t pci, int reg, uint32_t value, int width)
-{
-       switch (width) {
-       case 1:
-               pci_write_config_byte(pci, reg, value);
-               break;
-       case 2:
-               pci_write_config_word(pci, reg, value);
-               break;
-       case 4:
-               pci_write_config_dword(pci, reg, value);
-               break;
-       default:
-               panic("ahc_pci_write_config: Write size too big");
-               /* NOTREACHED */
-       }
-}
+void                    ahc_pci_write_config(ahc_dev_softc_t pci,
+                                             int reg, uint32_t value,
+                                             int width);
 
 static __inline int ahc_get_pci_function(ahc_dev_softc_t);
 static __inline int
index 3d3eaef65fb3e6ded30a548eb7e1d25eab1e5300..0d7628f1f1eff4edd573befaa4037c2111644ac3 100644 (file)
@@ -46,7 +46,7 @@
 */
 #define ID(x)  ID_C(x, PCI_CLASS_STORAGE_SCSI)
 
-static struct pci_device_id ahc_linux_pci_id_table[] = {
+static const struct pci_device_id ahc_linux_pci_id_table[] = {
        /* aic7850 based controllers */
        ID(ID_AHA_2902_04_10_15_20C_30C),
        /* aic7860 based controllers */
@@ -206,7 +206,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        const uint64_t   mask_39bit = 0x7FFFFFFFFFULL;
        struct           ahc_softc *ahc;
        ahc_dev_softc_t  pci;
-       struct           ahc_pci_identity *entry;
+       const struct ahc_pci_identity *entry;
        char            *name;
        int              error;
        struct device   *dev = &pdev->dev;
@@ -269,6 +269,57 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        return (0);
 }
 
+/******************************* PCI Routines *********************************/
+uint32_t
+ahc_pci_read_config(ahc_dev_softc_t pci, int reg, int width)
+{
+       switch (width) {
+       case 1:
+       {
+               uint8_t retval;
+
+               pci_read_config_byte(pci, reg, &retval);
+               return (retval);
+       }
+       case 2:
+       {
+               uint16_t retval;
+               pci_read_config_word(pci, reg, &retval);
+               return (retval);
+       }
+       case 4:
+       {
+               uint32_t retval;
+               pci_read_config_dword(pci, reg, &retval);
+               return (retval);
+       }
+       default:
+               panic("ahc_pci_read_config: Read size too big");
+               /* NOTREACHED */
+               return (0);
+       }
+}
+
+void
+ahc_pci_write_config(ahc_dev_softc_t pci, int reg, uint32_t value, int width)
+{
+       switch (width) {
+       case 1:
+               pci_write_config_byte(pci, reg, value);
+               break;
+       case 2:
+               pci_write_config_word(pci, reg, value);
+               break;
+       case 4:
+               pci_write_config_dword(pci, reg, value);
+               break;
+       default:
+               panic("ahc_pci_write_config: Write size too big");
+               /* NOTREACHED */
+       }
+}
+
+
 static struct pci_driver aic7xxx_pci_driver = {
        .name           = "aic7xxx",
        .probe          = ahc_linux_pci_dev_probe,
@@ -293,7 +344,7 @@ ahc_linux_pci_exit(void)
 }
 
 static int
-ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, u_long *base)
+ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, resource_size_t *base)
 {
        if (aic7xxx_allow_memio == 0)
                return (ENOMEM);
@@ -308,10 +359,10 @@ ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, u_long *base)
 
 static int
 ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
-                                u_long *bus_addr,
+                                resource_size_t *bus_addr,
                                 uint8_t __iomem **maddr)
 {
-       u_long  start;
+       resource_size_t start;
        int     error;
 
        error = 0;
@@ -336,7 +387,7 @@ int
 ahc_pci_map_registers(struct ahc_softc *ahc)
 {
        uint32_t command;
-       u_long   base;
+       resource_size_t base;
        uint8_t __iomem *maddr;
        int      error;
 
@@ -374,12 +425,12 @@ ahc_pci_map_registers(struct ahc_softc *ahc)
                } else
                        command |= PCIM_CMD_MEMEN;
        } else {
-               printf("aic7xxx: PCI%d:%d:%d MEM region 0x%lx "
+               printf("aic7xxx: PCI%d:%d:%d MEM region 0x%llx "
                       "unavailable. Cannot memory map device.\n",
                       ahc_get_pci_bus(ahc->dev_softc),
                       ahc_get_pci_slot(ahc->dev_softc),
                       ahc_get_pci_function(ahc->dev_softc),
-                      base);
+                      (unsigned long long)base);
        }
 
        /*
@@ -390,15 +441,15 @@ ahc_pci_map_registers(struct ahc_softc *ahc)
                error = ahc_linux_pci_reserve_io_region(ahc, &base);
                if (error == 0) {
                        ahc->tag = BUS_SPACE_PIO;
-                       ahc->bsh.ioport = base;
+                       ahc->bsh.ioport = (u_long)base;
                        command |= PCIM_CMD_PORTEN;
                } else {
-                       printf("aic7xxx: PCI%d:%d:%d IO region 0x%lx[0..255] "
+                       printf("aic7xxx: PCI%d:%d:%d IO region 0x%llx[0..255] "
                               "unavailable. Cannot map device.\n",
                               ahc_get_pci_bus(ahc->dev_softc),
                               ahc_get_pci_slot(ahc->dev_softc),
                               ahc_get_pci_function(ahc->dev_softc),
-                              base);
+                              (unsigned long long)base);
                }
        }
        ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, 4);
index 56848f41e4f961f7a70d66964a8d770671ff0663..c07cb6eebb0294cac8ae9e93820e14562719c9fd 100644 (file)
@@ -168,8 +168,7 @@ static ahc_device_setup_t ahc_aha394XX_setup;
 static ahc_device_setup_t ahc_aha494XX_setup;
 static ahc_device_setup_t ahc_aha398XX_setup;
 
-static struct ahc_pci_identity ahc_pci_ident_table [] =
-{
+static const struct ahc_pci_identity ahc_pci_ident_table[] = {
        /* aic7850 based controllers */
        {
                ID_AHA_2902_04_10_15_20C_30C,
@@ -668,7 +667,7 @@ ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor,
        return (result);
 }
 
-struct ahc_pci_identity *
+const struct ahc_pci_identity *
 ahc_find_pci_device(ahc_dev_softc_t pci)
 {
        uint64_t  full_id;
@@ -676,7 +675,7 @@ ahc_find_pci_device(ahc_dev_softc_t pci)
        uint16_t  vendor;
        uint16_t  subdevice;
        uint16_t  subvendor;
-       struct    ahc_pci_identity *entry;
+       const struct ahc_pci_identity *entry;
        u_int     i;
 
        vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
@@ -710,7 +709,7 @@ ahc_find_pci_device(ahc_dev_softc_t pci)
 }
 
 int
-ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
+ahc_pci_config(struct ahc_softc *ahc, const struct ahc_pci_identity *entry)
 {
        u_int    command;
        u_int    our_id;
index 99e5443e75352cecf9383c247b5d8107dfd109fe..e92991a7c48554314877231870ff38cec3821bcd 100644 (file)
@@ -58,7 +58,7 @@ static int    ahc_proc_write_seeprom(struct ahc_softc *ahc,
  * Table of syncrates that don't follow the "divisible by 4"
  * rule. This table will be expanded in future SCSI specs.
  */
-static struct {
+static const struct {
        u_int period_factor;
        u_int period;   /* in 100ths of ns */
 } scsi_syncrates[] = {
@@ -137,7 +137,7 @@ copy_info(struct info_str *info, char *fmt, ...)
        return (len);
 }
 
-void
+static void
 ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo)
 {
        u_int speed;
index 88bfd767c51c2e7be9f2fa757b5e2362c8f9b720..309a562b009ef284294ff27fbbe6ea7950dc2cab 100644 (file)
@@ -8,7 +8,7 @@
 
 #include "aic7xxx_osm.h"
 
-static ahc_reg_parse_entry_t SCSISEQ_parse_table[] = {
+static const ahc_reg_parse_entry_t SCSISEQ_parse_table[] = {
        { "SCSIRSTO",           0x01, 0x01 },
        { "ENAUTOATNP",         0x02, 0x02 },
        { "ENAUTOATNI",         0x04, 0x04 },
@@ -26,7 +26,7 @@ ahc_scsiseq_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x00, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SXFRCTL0_parse_table[] = {
+static const ahc_reg_parse_entry_t SXFRCTL0_parse_table[] = {
        { "CLRCHN",             0x02, 0x02 },
        { "SCAMEN",             0x04, 0x04 },
        { "SPIOEN",             0x08, 0x08 },
@@ -43,7 +43,7 @@ ahc_sxfrctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x01, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SXFRCTL1_parse_table[] = {
+static const ahc_reg_parse_entry_t SXFRCTL1_parse_table[] = {
        { "STPWEN",             0x01, 0x01 },
        { "ACTNEGEN",           0x02, 0x02 },
        { "ENSTIMER",           0x04, 0x04 },
@@ -60,7 +60,7 @@ ahc_sxfrctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x02, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SCSISIGO_parse_table[] = {
+static const ahc_reg_parse_entry_t SCSISIGO_parse_table[] = {
        { "ACKO",               0x01, 0x01 },
        { "REQO",               0x02, 0x02 },
        { "BSYO",               0x04, 0x04 },
@@ -85,7 +85,7 @@ ahc_scsisigo_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x03, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SCSISIGI_parse_table[] = {
+static const ahc_reg_parse_entry_t SCSISIGI_parse_table[] = {
        { "ACKI",               0x01, 0x01 },
        { "REQI",               0x02, 0x02 },
        { "BSYI",               0x04, 0x04 },
@@ -112,7 +112,7 @@ ahc_scsisigi_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x03, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SCSIRATE_parse_table[] = {
+static const ahc_reg_parse_entry_t SCSIRATE_parse_table[] = {
        { "SINGLE_EDGE",        0x10, 0x10 },
        { "ENABLE_CRC",         0x40, 0x40 },
        { "WIDEXFER",           0x80, 0x80 },
@@ -128,7 +128,7 @@ ahc_scsirate_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x04, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SCSIID_parse_table[] = {
+static const ahc_reg_parse_entry_t SCSIID_parse_table[] = {
        { "TWIN_CHNLB",         0x80, 0x80 },
        { "OID",                0x0f, 0x0f },
        { "TWIN_TID",           0x70, 0x70 },
@@ -150,13 +150,6 @@ ahc_scsidatl_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x06, regvalue, cur_col, wrap));
 }
 
-int
-ahc_scsidath_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahc_print_register(NULL, 0, "SCSIDATH",
-           0x07, regvalue, cur_col, wrap));
-}
-
 int
 ahc_stcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -164,7 +157,7 @@ ahc_stcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x08, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t OPTIONMODE_parse_table[] = {
+static const ahc_reg_parse_entry_t OPTIONMODE_parse_table[] = {
        { "DIS_MSGIN_DUALEDGE", 0x01, 0x01 },
        { "AUTO_MSGOUT_DE",     0x02, 0x02 },
        { "SCSIDATL_IMGEN",     0x04, 0x04 },
@@ -190,7 +183,7 @@ ahc_targcrccnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x0a, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t CLRSINT0_parse_table[] = {
+static const ahc_reg_parse_entry_t CLRSINT0_parse_table[] = {
        { "CLRSPIORDY",         0x02, 0x02 },
        { "CLRSWRAP",           0x08, 0x08 },
        { "CLRIOERR",           0x08, 0x08 },
@@ -206,7 +199,7 @@ ahc_clrsint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x0b, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SSTAT0_parse_table[] = {
+static const ahc_reg_parse_entry_t SSTAT0_parse_table[] = {
        { "DMADONE",            0x01, 0x01 },
        { "SPIORDY",            0x02, 0x02 },
        { "SDONE",              0x04, 0x04 },
@@ -225,7 +218,7 @@ ahc_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x0b, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t CLRSINT1_parse_table[] = {
+static const ahc_reg_parse_entry_t CLRSINT1_parse_table[] = {
        { "CLRREQINIT",         0x01, 0x01 },
        { "CLRPHASECHG",        0x02, 0x02 },
        { "CLRSCSIPERR",        0x04, 0x04 },
@@ -242,7 +235,7 @@ ahc_clrsint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x0c, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SSTAT1_parse_table[] = {
+static const ahc_reg_parse_entry_t SSTAT1_parse_table[] = {
        { "REQINIT",            0x01, 0x01 },
        { "PHASECHG",           0x02, 0x02 },
        { "SCSIPERR",           0x04, 0x04 },
@@ -260,7 +253,7 @@ ahc_sstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x0c, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SSTAT2_parse_table[] = {
+static const ahc_reg_parse_entry_t SSTAT2_parse_table[] = {
        { "DUAL_EDGE_ERR",      0x01, 0x01 },
        { "CRCREQERR",          0x02, 0x02 },
        { "CRCENDERR",          0x04, 0x04 },
@@ -278,7 +271,7 @@ ahc_sstat2_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x0d, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SSTAT3_parse_table[] = {
+static const ahc_reg_parse_entry_t SSTAT3_parse_table[] = {
        { "OFFCNT",             0x0f, 0x0f },
        { "U2OFFCNT",           0x7f, 0x7f },
        { "SCSICNT",            0xf0, 0xf0 }
@@ -291,7 +284,7 @@ ahc_sstat3_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x0e, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SCSIID_ULTRA2_parse_table[] = {
+static const ahc_reg_parse_entry_t SCSIID_ULTRA2_parse_table[] = {
        { "OID",                0x0f, 0x0f },
        { "TID",                0xf0, 0xf0 }
 };
@@ -303,7 +296,7 @@ ahc_scsiid_ultra2_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x0f, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SIMODE0_parse_table[] = {
+static const ahc_reg_parse_entry_t SIMODE0_parse_table[] = {
        { "ENDMADONE",          0x01, 0x01 },
        { "ENSPIORDY",          0x02, 0x02 },
        { "ENSDONE",            0x04, 0x04 },
@@ -321,7 +314,7 @@ ahc_simode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x10, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SIMODE1_parse_table[] = {
+static const ahc_reg_parse_entry_t SIMODE1_parse_table[] = {
        { "ENREQINIT",          0x01, 0x01 },
        { "ENPHASECHG",         0x02, 0x02 },
        { "ENSCSIPERR",         0x04, 0x04 },
@@ -346,26 +339,6 @@ ahc_scsibusl_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x12, regvalue, cur_col, wrap));
 }
 
-int
-ahc_scsibush_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahc_print_register(NULL, 0, "SCSIBUSH",
-           0x13, regvalue, cur_col, wrap));
-}
-
-static ahc_reg_parse_entry_t SXFRCTL2_parse_table[] = {
-       { "CMDDMAEN",           0x08, 0x08 },
-       { "AUTORSTDIS",         0x10, 0x10 },
-       { "ASYNC_SETUP",        0x07, 0x07 }
-};
-
-int
-ahc_sxfrctl2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahc_print_register(SXFRCTL2_parse_table, 3, "SXFRCTL2",
-           0x13, regvalue, cur_col, wrap));
-}
-
 int
 ahc_shaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -373,7 +346,7 @@ ahc_shaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x14, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SELTIMER_parse_table[] = {
+static const ahc_reg_parse_entry_t SELTIMER_parse_table[] = {
        { "STAGE1",             0x01, 0x01 },
        { "STAGE2",             0x02, 0x02 },
        { "STAGE3",             0x04, 0x04 },
@@ -389,7 +362,7 @@ ahc_seltimer_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x18, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SELID_parse_table[] = {
+static const ahc_reg_parse_entry_t SELID_parse_table[] = {
        { "ONEBIT",             0x08, 0x08 },
        { "SELID_MASK",         0xf0, 0xf0 }
 };
@@ -401,21 +374,6 @@ ahc_selid_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x19, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SCAMCTL_parse_table[] = {
-       { "DFLTTID",            0x10, 0x10 },
-       { "ALTSTIM",            0x20, 0x20 },
-       { "CLRSCAMSELID",       0x40, 0x40 },
-       { "ENSCAMSELO",         0x80, 0x80 },
-       { "SCAMLVL",            0x03, 0x03 }
-};
-
-int
-ahc_scamctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahc_print_register(SCAMCTL_parse_table, 5, "SCAMCTL",
-           0x1a, regvalue, cur_col, wrap));
-}
-
 int
 ahc_targid_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -423,7 +381,7 @@ ahc_targid_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x1b, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SPIOCAP_parse_table[] = {
+static const ahc_reg_parse_entry_t SPIOCAP_parse_table[] = {
        { "SSPIOCPS",           0x01, 0x01 },
        { "ROM",                0x02, 0x02 },
        { "EEPROM",             0x04, 0x04 },
@@ -441,7 +399,7 @@ ahc_spiocap_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x1b, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t BRDCTL_parse_table[] = {
+static const ahc_reg_parse_entry_t BRDCTL_parse_table[] = {
        { "BRDCTL0",            0x01, 0x01 },
        { "BRDSTB_ULTRA2",      0x01, 0x01 },
        { "BRDCTL1",            0x02, 0x02 },
@@ -464,7 +422,7 @@ ahc_brdctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x1d, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SEECTL_parse_table[] = {
+static const ahc_reg_parse_entry_t SEECTL_parse_table[] = {
        { "SEEDI",              0x01, 0x01 },
        { "SEEDO",              0x02, 0x02 },
        { "SEECK",              0x04, 0x04 },
@@ -482,7 +440,7 @@ ahc_seectl_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x1e, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SBLKCTL_parse_table[] = {
+static const ahc_reg_parse_entry_t SBLKCTL_parse_table[] = {
        { "XCVR",               0x01, 0x01 },
        { "SELWIDE",            0x02, 0x02 },
        { "ENAB20",             0x04, 0x04 },
@@ -521,13 +479,6 @@ ahc_disc_dsb_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x32, regvalue, cur_col, wrap));
 }
 
-int
-ahc_cmdsize_table_tail_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahc_print_register(NULL, 0, "CMDSIZE_TABLE_TAIL",
-           0x34, regvalue, cur_col, wrap));
-}
-
 int
 ahc_mwi_residual_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -549,7 +500,7 @@ ahc_msg_out_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x3a, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t DMAPARAMS_parse_table[] = {
+static const ahc_reg_parse_entry_t DMAPARAMS_parse_table[] = {
        { "FIFORESET",          0x01, 0x01 },
        { "FIFOFLUSH",          0x02, 0x02 },
        { "DIRECTION",          0x04, 0x04 },
@@ -569,7 +520,7 @@ ahc_dmaparams_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x3b, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
+static const ahc_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
        { "NO_DISCONNECT",      0x01, 0x01 },
        { "SPHASE_PENDING",     0x02, 0x02 },
        { "DPHASE_PENDING",     0x04, 0x04 },
@@ -602,7 +553,7 @@ ahc_saved_lun_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x3e, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t LASTPHASE_parse_table[] = {
+static const ahc_reg_parse_entry_t LASTPHASE_parse_table[] = {
        { "MSGI",               0x20, 0x20 },
        { "IOI",                0x40, 0x40 },
        { "CDI",                0x80, 0x80 },
@@ -644,13 +595,6 @@ ahc_free_scbh_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x42, regvalue, cur_col, wrap));
 }
 
-int
-ahc_complete_scbh_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahc_print_register(NULL, 0, "COMPLETE_SCBH",
-           0x43, regvalue, cur_col, wrap));
-}
-
 int
 ahc_hscb_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -700,7 +644,7 @@ ahc_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x50, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t ARG_1_parse_table[] = {
+static const ahc_reg_parse_entry_t ARG_1_parse_table[] = {
        { "CONT_TARG_SESSION",  0x02, 0x02 },
        { "CONT_MSG_LOOP",      0x04, 0x04 },
        { "EXIT_MSG_LOOP",      0x08, 0x08 },
@@ -731,7 +675,7 @@ ahc_last_msg_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x53, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = {
+static const ahc_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = {
        { "ENAUTOATNP",         0x02, 0x02 },
        { "ENAUTOATNI",         0x04, 0x04 },
        { "ENAUTOATNO",         0x08, 0x08 },
@@ -747,7 +691,7 @@ ahc_scsiseq_template_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x54, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t HA_274_BIOSGLOBAL_parse_table[] = {
+static const ahc_reg_parse_entry_t HA_274_BIOSGLOBAL_parse_table[] = {
        { "HA_274_EXTENDED_TRANS",0x01, 0x01 }
 };
 
@@ -758,7 +702,7 @@ ahc_ha_274_biosglobal_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x56, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
+static const ahc_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
        { "SCB_DMA",            0x01, 0x01 },
        { "TARGET_MSG_PENDING", 0x02, 0x02 }
 };
@@ -770,7 +714,7 @@ ahc_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x57, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SCSICONF_parse_table[] = {
+static const ahc_reg_parse_entry_t SCSICONF_parse_table[] = {
        { "ENSPCHK",            0x20, 0x20 },
        { "RESET_SCSI",         0x40, 0x40 },
        { "TERM_ENB",           0x80, 0x80 },
@@ -785,7 +729,7 @@ ahc_scsiconf_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x5a, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t INTDEF_parse_table[] = {
+static const ahc_reg_parse_entry_t INTDEF_parse_table[] = {
        { "EDGE_TRIG",          0x80, 0x80 },
        { "VECTOR",             0x0f, 0x0f }
 };
@@ -804,7 +748,7 @@ ahc_hostconf_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x5d, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t HA_274_BIOSCTRL_parse_table[] = {
+static const ahc_reg_parse_entry_t HA_274_BIOSCTRL_parse_table[] = {
        { "CHANNEL_B_PRIMARY",  0x08, 0x08 },
        { "BIOSMODE",           0x30, 0x30 },
        { "BIOSDISABLED",       0x30, 0x30 }
@@ -817,7 +761,7 @@ ahc_ha_274_biosctrl_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x5f, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SEQCTL_parse_table[] = {
+static const ahc_reg_parse_entry_t SEQCTL_parse_table[] = {
        { "LOADRAM",            0x01, 0x01 },
        { "SEQRESET",           0x02, 0x02 },
        { "STEP",               0x04, 0x04 },
@@ -849,7 +793,7 @@ ahc_seqaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x62, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SEQADDR1_parse_table[] = {
+static const ahc_reg_parse_entry_t SEQADDR1_parse_table[] = {
        { "SEQADDR1_MASK",      0x01, 0x01 }
 };
 
@@ -902,7 +846,7 @@ ahc_none_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x6a, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t FLAGS_parse_table[] = {
+static const ahc_reg_parse_entry_t FLAGS_parse_table[] = {
        { "CARRY",              0x01, 0x01 },
        { "ZERO",               0x02, 0x02 }
 };
@@ -928,13 +872,6 @@ ahc_dindir_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x6d, regvalue, cur_col, wrap));
 }
 
-int
-ahc_function1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahc_print_register(NULL, 0, "FUNCTION1",
-           0x6e, regvalue, cur_col, wrap));
-}
-
 int
 ahc_stack_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -956,19 +893,7 @@ ahc_sram_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x70, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t BCTL_parse_table[] = {
-       { "ENABLE",             0x01, 0x01 },
-       { "ACE",                0x08, 0x08 }
-};
-
-int
-ahc_bctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahc_print_register(BCTL_parse_table, 2, "BCTL",
-           0x84, regvalue, cur_col, wrap));
-}
-
-static ahc_reg_parse_entry_t DSCOMMAND0_parse_table[] = {
+static const ahc_reg_parse_entry_t DSCOMMAND0_parse_table[] = {
        { "CIOPARCKEN",         0x01, 0x01 },
        { "USCBSIZE32",         0x02, 0x02 },
        { "RAMPS",              0x04, 0x04 },
@@ -986,7 +911,7 @@ ahc_dscommand0_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x84, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t BUSTIME_parse_table[] = {
+static const ahc_reg_parse_entry_t BUSTIME_parse_table[] = {
        { "BON",                0x0f, 0x0f },
        { "BOFF",               0xf0, 0xf0 }
 };
@@ -998,7 +923,7 @@ ahc_bustime_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x85, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t DSCOMMAND1_parse_table[] = {
+static const ahc_reg_parse_entry_t DSCOMMAND1_parse_table[] = {
        { "HADDLDSEL0",         0x01, 0x01 },
        { "HADDLDSEL1",         0x02, 0x02 },
        { "DSLATT",             0xfc, 0xfc }
@@ -1011,7 +936,7 @@ ahc_dscommand1_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x85, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t BUSSPD_parse_table[] = {
+static const ahc_reg_parse_entry_t BUSSPD_parse_table[] = {
        { "STBON",              0x07, 0x07 },
        { "STBOFF",             0x38, 0x38 },
        { "DFTHRSH_75",         0x80, 0x80 },
@@ -1026,7 +951,7 @@ ahc_busspd_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x86, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t HS_MAILBOX_parse_table[] = {
+static const ahc_reg_parse_entry_t HS_MAILBOX_parse_table[] = {
        { "SEQ_MAILBOX",        0x0f, 0x0f },
        { "HOST_TQINPOS",       0x80, 0x80 },
        { "HOST_MAILBOX",       0xf0, 0xf0 }
@@ -1039,7 +964,7 @@ ahc_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x86, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t DSPCISTATUS_parse_table[] = {
+static const ahc_reg_parse_entry_t DSPCISTATUS_parse_table[] = {
        { "DFTHRSH_100",        0xc0, 0xc0 }
 };
 
@@ -1050,7 +975,7 @@ ahc_dspcistatus_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x86, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t HCNTRL_parse_table[] = {
+static const ahc_reg_parse_entry_t HCNTRL_parse_table[] = {
        { "CHIPRST",            0x01, 0x01 },
        { "CHIPRSTACK",         0x01, 0x01 },
        { "INTEN",              0x02, 0x02 },
@@ -1088,7 +1013,7 @@ ahc_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x90, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t INTSTAT_parse_table[] = {
+static const ahc_reg_parse_entry_t INTSTAT_parse_table[] = {
        { "SEQINT",             0x01, 0x01 },
        { "CMDCMPLT",           0x02, 0x02 },
        { "SCSIINT",            0x04, 0x04 },
@@ -1119,7 +1044,7 @@ ahc_intstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x91, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t CLRINT_parse_table[] = {
+static const ahc_reg_parse_entry_t CLRINT_parse_table[] = {
        { "CLRSEQINT",          0x01, 0x01 },
        { "CLRCMDINT",          0x02, 0x02 },
        { "CLRSCSIINT",         0x04, 0x04 },
@@ -1134,7 +1059,7 @@ ahc_clrint_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x92, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t ERROR_parse_table[] = {
+static const ahc_reg_parse_entry_t ERROR_parse_table[] = {
        { "ILLHADDR",           0x01, 0x01 },
        { "ILLSADDR",           0x02, 0x02 },
        { "ILLOPCODE",          0x04, 0x04 },
@@ -1152,7 +1077,7 @@ ahc_error_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x92, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t DFCNTRL_parse_table[] = {
+static const ahc_reg_parse_entry_t DFCNTRL_parse_table[] = {
        { "FIFORESET",          0x01, 0x01 },
        { "FIFOFLUSH",          0x02, 0x02 },
        { "DIRECTION",          0x04, 0x04 },
@@ -1172,7 +1097,7 @@ ahc_dfcntrl_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x93, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t DFSTATUS_parse_table[] = {
+static const ahc_reg_parse_entry_t DFSTATUS_parse_table[] = {
        { "FIFOEMP",            0x01, 0x01 },
        { "FIFOFULL",           0x02, 0x02 },
        { "DFTHRESH",           0x04, 0x04 },
@@ -1197,13 +1122,6 @@ ahc_dfwaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x95, regvalue, cur_col, wrap));
 }
 
-int
-ahc_dfraddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahc_print_register(NULL, 0, "DFRADDR",
-           0x97, regvalue, cur_col, wrap));
-}
-
 int
 ahc_dfdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -1211,7 +1129,7 @@ ahc_dfdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x99, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SCBCNT_parse_table[] = {
+static const ahc_reg_parse_entry_t SCBCNT_parse_table[] = {
        { "SCBAUTO",            0x80, 0x80 },
        { "SCBCNT_MASK",        0x1f, 0x1f }
 };
@@ -1230,13 +1148,6 @@ ahc_qinfifo_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x9b, regvalue, cur_col, wrap));
 }
 
-int
-ahc_qincnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahc_print_register(NULL, 0, "QINCNT",
-           0x9c, regvalue, cur_col, wrap));
-}
-
 int
 ahc_qoutfifo_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -1244,7 +1155,7 @@ ahc_qoutfifo_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x9d, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t CRCCONTROL1_parse_table[] = {
+static const ahc_reg_parse_entry_t CRCCONTROL1_parse_table[] = {
        { "TARGCRCCNTEN",       0x04, 0x04 },
        { "TARGCRCENDEN",       0x08, 0x08 },
        { "CRCREQCHKEN",        0x10, 0x10 },
@@ -1260,14 +1171,7 @@ ahc_crccontrol1_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x9d, regvalue, cur_col, wrap));
 }
 
-int
-ahc_qoutcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahc_print_register(NULL, 0, "QOUTCNT",
-           0x9e, regvalue, cur_col, wrap));
-}
-
-static ahc_reg_parse_entry_t SCSIPHASE_parse_table[] = {
+static const ahc_reg_parse_entry_t SCSIPHASE_parse_table[] = {
        { "DATA_OUT_PHASE",     0x01, 0x01 },
        { "DATA_IN_PHASE",      0x02, 0x02 },
        { "MSG_OUT_PHASE",      0x04, 0x04 },
@@ -1284,7 +1188,7 @@ ahc_scsiphase_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x9e, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SFUNCT_parse_table[] = {
+static const ahc_reg_parse_entry_t SFUNCT_parse_table[] = {
        { "ALT_MODE",           0x80, 0x80 }
 };
 
@@ -1351,7 +1255,7 @@ ahc_scb_dataptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xac, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SCB_DATACNT_parse_table[] = {
+static const ahc_reg_parse_entry_t SCB_DATACNT_parse_table[] = {
        { "SG_LAST_SEG",        0x80, 0x80 },
        { "SG_HIGH_ADDR_BITS",  0x7f, 0x7f }
 };
@@ -1363,7 +1267,7 @@ ahc_scb_datacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xb0, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SCB_SGPTR_parse_table[] = {
+static const ahc_reg_parse_entry_t SCB_SGPTR_parse_table[] = {
        { "SG_LIST_NULL",       0x01, 0x01 },
        { "SG_FULL_RESID",      0x02, 0x02 },
        { "SG_RESID_VALID",     0x04, 0x04 }
@@ -1376,7 +1280,7 @@ ahc_scb_sgptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xb4, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SCB_CONTROL_parse_table[] = {
+static const ahc_reg_parse_entry_t SCB_CONTROL_parse_table[] = {
        { "DISCONNECTED",       0x04, 0x04 },
        { "ULTRAENB",           0x08, 0x08 },
        { "MK_MESSAGE",         0x10, 0x10 },
@@ -1394,7 +1298,7 @@ ahc_scb_control_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xb8, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SCB_SCSIID_parse_table[] = {
+static const ahc_reg_parse_entry_t SCB_SCSIID_parse_table[] = {
        { "TWIN_CHNLB",         0x80, 0x80 },
        { "OID",                0x0f, 0x0f },
        { "TWIN_TID",           0x70, 0x70 },
@@ -1408,7 +1312,7 @@ ahc_scb_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xb9, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SCB_LUN_parse_table[] = {
+static const ahc_reg_parse_entry_t SCB_LUN_parse_table[] = {
        { "SCB_XFERLEN_ODD",    0x80, 0x80 },
        { "LID",                0x3f, 0x3f }
 };
@@ -1455,14 +1359,7 @@ ahc_scb_next_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xbf, regvalue, cur_col, wrap));
 }
 
-int
-ahc_scb_64_spare_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-       return (ahc_print_register(NULL, 0, "SCB_64_SPARE",
-           0xc0, regvalue, cur_col, wrap));
-}
-
-static ahc_reg_parse_entry_t SEECTL_2840_parse_table[] = {
+static const ahc_reg_parse_entry_t SEECTL_2840_parse_table[] = {
        { "DO_2840",            0x01, 0x01 },
        { "CK_2840",            0x02, 0x02 },
        { "CS_2840",            0x04, 0x04 }
@@ -1475,7 +1372,7 @@ ahc_seectl_2840_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xc0, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t STATUS_2840_parse_table[] = {
+static const ahc_reg_parse_entry_t STATUS_2840_parse_table[] = {
        { "DI_2840",            0x01, 0x01 },
        { "EEPROM_TF",          0x80, 0x80 },
        { "ADSEL",              0x1e, 0x1e },
@@ -1524,7 +1421,7 @@ ahc_ccsgaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xea, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t CCSGCTL_parse_table[] = {
+static const ahc_reg_parse_entry_t CCSGCTL_parse_table[] = {
        { "CCSGRESET",          0x01, 0x01 },
        { "SG_FETCH_NEEDED",    0x02, 0x02 },
        { "CCSGEN",             0x08, 0x08 },
@@ -1552,7 +1449,7 @@ ahc_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xed, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t CCSCBCTL_parse_table[] = {
+static const ahc_reg_parse_entry_t CCSCBCTL_parse_table[] = {
        { "CCSCBRESET",         0x01, 0x01 },
        { "CCSCBDIR",           0x04, 0x04 },
        { "CCSCBEN",            0x08, 0x08 },
@@ -1610,7 +1507,7 @@ ahc_sdscb_qoff_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xf8, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t QOFF_CTLSTA_parse_table[] = {
+static const ahc_reg_parse_entry_t QOFF_CTLSTA_parse_table[] = {
        { "SDSCB_ROLLOVER",     0x10, 0x10 },
        { "SNSCB_ROLLOVER",     0x20, 0x20 },
        { "SCB_AVAIL",          0x40, 0x40 },
@@ -1625,7 +1522,7 @@ ahc_qoff_ctlsta_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xfa, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t DFF_THRSH_parse_table[] = {
+static const ahc_reg_parse_entry_t DFF_THRSH_parse_table[] = {
        { "RD_DFTHRSH_MIN",     0x00, 0x00 },
        { "WR_DFTHRSH_MIN",     0x00, 0x00 },
        { "RD_DFTHRSH_25",      0x01, 0x01 },
@@ -1653,7 +1550,7 @@ ahc_dff_thrsh_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xfb, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SG_CACHE_SHADOW_parse_table[] = {
+static const ahc_reg_parse_entry_t SG_CACHE_SHADOW_parse_table[] = {
        { "LAST_SEG_DONE",      0x01, 0x01 },
        { "LAST_SEG",           0x02, 0x02 },
        { "SG_ADDR_MASK",       0xf8, 0xf8 }
@@ -1666,7 +1563,7 @@ ahc_sg_cache_shadow_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0xfc, regvalue, cur_col, wrap));
 }
 
-static ahc_reg_parse_entry_t SG_CACHE_PRE_parse_table[] = {
+static const ahc_reg_parse_entry_t SG_CACHE_PRE_parse_table[] = {
        { "LAST_SEG_DONE",      0x01, 0x01 },
        { "LAST_SEG",           0x02, 0x02 },
        { "SG_ADDR_MASK",       0xf8, 0xf8 }
index 4cee08521e75f6cb0c9f1a00580ce9ac683958c2..07e93fbae70661b2eee2518b0fcaf70e61241c9c 100644 (file)
@@ -5,7 +5,7 @@
  * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
  * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
  */
-static uint8_t seqprog[] = {
+static const uint8_t seqprog[] = {
        0xb2, 0x00, 0x00, 0x08,
        0xf7, 0x11, 0x22, 0x08,
        0x00, 0x65, 0xee, 0x59,
@@ -1081,7 +1081,7 @@ ahc_patch0_func(struct ahc_softc *ahc)
        return (0);
 }
 
-static struct patch {
+static const struct patch {
        ahc_patch_func_t                *patch_func;
        uint32_t                 begin          :10,
                                 skip_instr     :10,
@@ -1291,7 +1291,7 @@ static struct patch {
        { ahc_patch4_func, 865, 12, 1 }
 };
 
-static struct cs {
+static const struct cs {
        uint16_t        begin;
        uint16_t        end;
 } critical_sections[] = {
index 924102720b141fe969f0891924fa1384e8269a2f..e4a778720301d4f5bcae7a5ed50b2785ad8ccf3b 100644 (file)
@@ -362,7 +362,7 @@ output_code()
 " *\n"
 "%s */\n", versions);
 
-       fprintf(ofile, "static uint8_t seqprog[] = {\n");
+       fprintf(ofile, "static const uint8_t seqprog[] = {\n");
        for (cur_instr = STAILQ_FIRST(&seq_program);
             cur_instr != NULL;
             cur_instr = STAILQ_NEXT(cur_instr, links)) {
@@ -415,7 +415,7 @@ output_code()
        }
 
        fprintf(ofile,
-"static struct patch {\n"
+"static const struct patch {\n"
 "      %spatch_func_t          *patch_func;\n"
 "      uint32_t                 begin          :10,\n"
 "                               skip_instr     :10,\n"
@@ -435,7 +435,7 @@ output_code()
        fprintf(ofile, "\n};\n\n");
 
        fprintf(ofile,
-"static struct cs {\n"
+"static const struct cs {\n"
 "      uint16_t        begin;\n"
 "      uint16_t        end;\n"
 "} critical_sections[] = {\n");
index 702e2dbd11fb5b2feecfc701b52520fa76aade15..81be6a261cc8503a0853699b9e6719139cb9b5f6 100644 (file)
@@ -101,11 +101,12 @@ static void format_3_instr(int opcode, symbol_ref_t *src,
                           expression_t *immed, symbol_ref_t *address);
 static void test_readable_symbol(symbol_t *symbol);
 static void test_writable_symbol(symbol_t *symbol);
-static void type_check(symbol_t *symbol, expression_t *expression, int and_op);
+static void type_check(symbol_ref_t *sym, expression_t *expression, int and_op);
 static void make_expression(expression_t *immed, int value);
 static void add_conditional(symbol_t *symbol);
 static void add_version(const char *verstring);
 static int  is_download_const(expression_t *immed);
+static int  is_location_address(symbol_t *symbol);
 void yyerror(const char *string);
 
 #define SRAM_SYMNAME "SRAM_BASE"
@@ -142,6 +143,8 @@ void yyerror(const char *string);
 
 %token <value> T_ADDRESS
 
+%token T_COUNT
+
 %token T_ACCESS_MODE
 
 %token T_MODES
@@ -192,10 +195,10 @@ void yyerror(const char *string);
 
 %token <value> T_OR
 
-/* 16 bit extensions */
-%token <value> T_OR16 T_AND16 T_XOR16 T_ADD16
-%token <value> T_ADC16 T_MVI16 T_TEST16 T_CMP16 T_CMPXCHG
-
+/* 16 bit extensions, not implemented
+ * %token <value> T_OR16 T_AND16 T_XOR16 T_ADD16
+ * %token <value> T_ADC16 T_MVI16 T_TEST16 T_CMP16 T_CMPXCHG
+ */
 %token T_RET
 
 %token T_NOP
@@ -214,7 +217,7 @@ void yyerror(const char *string);
 
 %type <expression> expression immediate immediate_or_a
 
-%type <value> export ret f1_opcode f2_opcode f4_opcode jmp_jc_jnc_call jz_jnz je_jne
+%type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne
 
 %type <value> mode_value mode_list macro_arglist
 
@@ -313,13 +316,13 @@ reg_definition:
                                stop("Register multiply defined", EX_DATAERR);
                                /* NOTREACHED */
                        }
-                       cur_symbol = $1; 
+                       cur_symbol = $1;
                        cur_symbol->type = cur_symtype;
                        initialize_symbol(cur_symbol);
                }
                reg_attribute_list
        '}'
-               {                    
+               {
                        /*
                         * Default to allowing everything in for registers
                         * with no bit or mask definitions.
@@ -349,9 +352,10 @@ reg_attribute_list:
 |      reg_attribute_list reg_attribute
 ;
 
-reg_attribute:         
+reg_attribute:
        reg_address
 |      size
+|      count
 |      access_mode
 |      modes
 |      field_defn
@@ -392,6 +396,13 @@ size:
        }
 ;
 
+count:
+       T_COUNT T_NUMBER
+       {
+               cur_symbol->count += $2;
+       }
+;
+
 access_mode:
        T_ACCESS_MODE T_MODE
        {
@@ -641,14 +652,14 @@ expression:
                               &($1.referenced_syms),
                               &($3.referenced_syms));
        }
-|      expression T_EXPR_LSHIFT expression
+|      expression T_EXPR_LSHIFT expression
        {
                $$.value = $1.value << $3.value;
                symlist_merge(&$$.referenced_syms,
                               &$1.referenced_syms,
                               &$3.referenced_syms);
        }
-|      expression T_EXPR_RSHIFT expression
+|      expression T_EXPR_RSHIFT expression
        {
                $$.value = $1.value >> $3.value;
                symlist_merge(&$$.referenced_syms,
@@ -714,7 +725,7 @@ expression:
 ;
 
 constant:
-       T_CONST T_SYMBOL expression 
+       T_CONST T_SYMBOL expression
        {
                if ($2->type != UNINITIALIZED) {
                        stop("Re-definition of symbol as a constant",
@@ -800,6 +811,7 @@ scratch_ram:
                        cur_symtype = SRAMLOC;
                        cur_symbol->type = SRAMLOC;
                        initialize_symbol(cur_symbol);
+                       cur_symbol->count += 1;
                }
                reg_address
                {
@@ -831,6 +843,7 @@ scb:
                        initialize_symbol(cur_symbol);
                        /* 64 bytes of SCB space */
                        cur_symbol->info.rinfo->size = 64;
+                       cur_symbol->count += 1;
                }
                reg_address
                {
@@ -1311,14 +1324,18 @@ f2_opcode:
 |      T_ROR { $$ = AIC_OP_ROR; }
 ;
 
-f4_opcode:
-       T_OR16  { $$ = AIC_OP_OR16; }
-|      T_AND16 { $$ = AIC_OP_AND16; }
-|      T_XOR16 { $$ = AIC_OP_XOR16; }
-|      T_ADD16 { $$ = AIC_OP_ADD16; }
-|      T_ADC16 { $$ = AIC_OP_ADC16; }
-|      T_MVI16 { $$ = AIC_OP_MVI16; }
-;
+/*
+ * 16bit opcodes, not used
+ *
+ *f4_opcode:
+ *     T_OR16  { $$ = AIC_OP_OR16; }
+ *|    T_AND16 { $$ = AIC_OP_AND16; }
+ *|    T_XOR16 { $$ = AIC_OP_XOR16; }
+ *|    T_ADD16 { $$ = AIC_OP_ADD16; }
+ *|    T_ADC16 { $$ = AIC_OP_ADC16; }
+ *|    T_MVI16 { $$ = AIC_OP_MVI16; }
+ *;
+ */
 
 code:
        f2_opcode destination ',' expression opt_source ret ';'
@@ -1357,6 +1374,7 @@ code:
 code:
        T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';'
        {
+               type_check(&$2, &$4, AIC_OP_OR);
                format_3_instr($5, &$2, &$4, &$6);
        }
 ;
@@ -1528,7 +1546,7 @@ initialize_symbol(symbol_t *symbol)
                       sizeof(struct cond_info));
                break;
        case MACRO:
-               symbol->info.macroinfo = 
+               symbol->info.macroinfo =
                    (struct macro_info *)malloc(sizeof(struct macro_info));
                if (symbol->info.macroinfo == NULL) {
                        stop("Can't create macro info", EX_SOFTWARE);
@@ -1552,7 +1570,6 @@ add_macro_arg(const char *argtext, int argnum)
        struct macro_arg *marg;
        int i;
        int retval;
-               
 
        if (cur_symbol == NULL || cur_symbol->type != MACRO) {
                stop("Invalid current symbol for adding macro arg",
@@ -1633,8 +1650,10 @@ format_1_instr(int opcode, symbol_ref_t *dest, expression_t *immed,
        test_writable_symbol(dest->symbol);
        test_readable_symbol(src->symbol);
 
-       /* Ensure that immediate makes sense for this destination */
-       type_check(dest->symbol, immed, opcode);
+       if (!is_location_address(dest->symbol)) {
+               /* Ensure that immediate makes sense for this destination */
+               type_check(dest, immed, opcode);
+       }
 
        /* Allocate sequencer space for the instruction and fill it out */
        instr = seq_alloc();
@@ -1766,9 +1785,6 @@ format_3_instr(int opcode, symbol_ref_t *src,
        /* Test register permissions */
        test_readable_symbol(src->symbol);
 
-       /* Ensure that immediate makes sense for this source */
-       type_check(src->symbol, immed, opcode);
-
        /* Allocate sequencer space for the instruction and fill it out */
        instr = seq_alloc();
        f3_instr = &instr->format.format3;
@@ -1797,7 +1813,6 @@ format_3_instr(int opcode, symbol_ref_t *src,
 static void
 test_readable_symbol(symbol_t *symbol)
 {
-       
        if ((symbol->info.rinfo->modes & (0x1 << src_mode)) == 0) {
                snprintf(errbuf, sizeof(errbuf),
                        "Register %s unavailable in source reg mode %d",
@@ -1815,7 +1830,6 @@ test_readable_symbol(symbol_t *symbol)
 static void
 test_writable_symbol(symbol_t *symbol)
 {
-       
        if ((symbol->info.rinfo->modes & (0x1 << dst_mode)) == 0) {
                snprintf(errbuf, sizeof(errbuf),
                        "Register %s unavailable in destination reg mode %d",
@@ -1831,25 +1845,34 @@ test_writable_symbol(symbol_t *symbol)
 }
 
 static void
-type_check(symbol_t *symbol, expression_t *expression, int opcode)
+type_check(symbol_ref_t *sym, expression_t *expression, int opcode)
 {
+       symbol_t *symbol = sym->symbol;
        symbol_node_t *node;
        int and_op;
+       int8_t value, mask;
 
        and_op = FALSE;
-       if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || opcode == AIC_OP_JZ)
-               and_op = TRUE;
-
        /*
         * Make sure that we aren't attempting to write something
         * that hasn't been defined.  If this is an and operation,
         * this is a mask, so "undefined" bits are okay.
         */
-       if (and_op == FALSE
-        && (expression->value & ~symbol->info.rinfo->valid_bitmask) != 0) {
+       if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ ||
+           opcode == AIC_OP_JZ  || opcode == AIC_OP_JNE ||
+           opcode == AIC_OP_BMOV)
+               and_op = TRUE;
+
+       /*
+        * Defaulting to 8 bit logic
+        */
+       mask = (int8_t)~symbol->info.rinfo->valid_bitmask;
+       value = (int8_t)expression->value;
+
+       if (and_op == FALSE && (mask & value) != 0 ) {
                snprintf(errbuf, sizeof(errbuf),
                         "Invalid bit(s) 0x%x in immediate written to %s",
-                        expression->value & ~symbol->info.rinfo->valid_bitmask,
+                        (mask & value),
                         symbol->name);
                stop(errbuf, EX_DATAERR);
                /* NOTREACHED */
@@ -1959,3 +1982,13 @@ is_download_const(expression_t *immed)
 
        return (FALSE);
 }
+
+static int
+is_location_address(symbol_t *sym)
+{
+       if (sym->type == SCBLOC ||
+           sym->type == SRAMLOC)
+               return (TRUE);
+       return (FALSE);
+}
+
index 7c3983f868a9a8c171d9d165438abf5f187be6fd..2c7f02daf88d21387967be473c660dcc9a2c1a0e 100644 (file)
@@ -162,6 +162,7 @@ register            { return T_REGISTER; }
 const                  { yylval.value = FALSE; return T_CONST; }
 download               { return T_DOWNLOAD; }
 address                        { return T_ADDRESS; }
+count                  { return T_COUNT; }
 access_mode            { return T_ACCESS_MODE; }
 modes                  { return T_MODES; }
 RW|RO|WO               {
@@ -228,15 +229,15 @@ ret                       { return T_RET; }
 nop                    { return T_NOP; }
 
        /* ARP2 16bit extensions */
-or16                   { return T_OR16; }
-and16                  { return T_AND16; }
-xor16                  { return T_XOR16; }
-add16                  { return T_ADD16; }
-adc16                  { return T_ADC16; }
-mvi16                  { return T_MVI16; }
-test16                 { return T_TEST16; }
-cmp16                  { return T_CMP16; }
-cmpxchg                        { return T_CMPXCHG; }
+       /* or16                 { return T_OR16; } */
+       /* and16                        { return T_AND16; }*/
+       /* xor16                        { return T_XOR16; }*/
+       /* add16                        { return T_ADD16; }*/
+       /* adc16                        { return T_ADC16; }*/
+       /* mvi16                        { return T_MVI16; }*/
+       /* test16                       { return T_TEST16; }*/
+       /* cmp16                        { return T_CMP16; }*/
+       /* cmpxchg                      { return T_CMPXCHG; }*/
 
        /* Allowed Symbols */
 \<\<                   { return T_EXPR_LSHIFT; }
index f1f448dff569fef218055b4ecc6ad5aba0b70137..fcd357872b43d0e360456e732dbdb868f7eb013c 100644 (file)
@@ -77,6 +77,7 @@ symbol_create(char *name)
        if (new_symbol->name == NULL)
                 stop("Unable to strdup symbol name", EX_SOFTWARE);
        new_symbol->type = UNINITIALIZED;
+       new_symbol->count = 1;
        return (new_symbol);
 }
 
@@ -198,6 +199,12 @@ symtable_get(char *name)
                }
        }
        memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
+       stored_ptr->count++;
+       data.data = &stored_ptr;
+       if (symtable->put(symtable, &key, &data, /*flags*/0) !=0) {
+               perror("Symtable put failed");
+               exit(EX_SOFTWARE);
+       }
        return (stored_ptr);
 }
 
@@ -256,7 +263,7 @@ symlist_add(symlist_t *symlist, symbol_t *symbol, int how)
                    && (curnode->symbol->info.finfo->value >
                        newnode->symbol->info.finfo->value))))
                 || (!field && (curnode->symbol->info.rinfo->address >
-                              newnode->symbol->info.rinfo->address))) {
+                               newnode->symbol->info.rinfo->address))) {
                        SLIST_INSERT_HEAD(symlist, newnode, links);
                        return;
                }
@@ -271,7 +278,7 @@ symlist_add(symlist_t *symlist, symbol_t *symbol, int how)
 
                                cursymbol = SLIST_NEXT(curnode, links)->symbol;
                                if ((field
-                                 && (cursymbol->type > symbol->type
+                                 && (cursymbol->type > symbol->type
                                   || (cursymbol->type == symbol->type
                                    && (cursymbol->info.finfo->value >
                                        symbol->info.finfo->value))))
@@ -351,7 +358,7 @@ aic_print_reg_dump_types(FILE *ofile)
 {
        if (ofile == NULL)
                return;
-               
+
        fprintf(ofile,
 "typedef int (%sreg_print_t)(u_int, u_int *, u_int);\n"
 "typedef struct %sreg_parse_entry {\n"
@@ -370,7 +377,7 @@ aic_print_reg_dump_start(FILE *dfile, symbol_node_t *regnode)
                return;
 
        fprintf(dfile,
-"static %sreg_parse_entry_t %s_parse_table[] = {\n",
+"static const %sreg_parse_entry_t %s_parse_table[] = {\n",
                prefix,
                regnode->symbol->name);
 }
@@ -385,7 +392,7 @@ aic_print_reg_dump_end(FILE *ofile, FILE *dfile,
        lower_name = strdup(regnode->symbol->name);
        if (lower_name == NULL)
                 stop("Unable to strdup symbol name", EX_SOFTWARE);
-       
+
        for (letter = lower_name; *letter != '\0'; letter++)
                *letter = tolower(*letter);
 
@@ -472,6 +479,7 @@ symtable_dump(FILE *ofile, FILE *dfile)
        DBT              key;
        DBT              data;
        int              flag;
+       int              reg_count = 0, reg_used = 0;
        u_int            i;
 
        if (symtable == NULL)
@@ -541,6 +549,9 @@ symtable_dump(FILE *ofile, FILE *dfile)
                        int              num_entries;
 
                        num_entries = 0;
+                       reg_count++;
+                       if (curnode->symbol->count == 1)
+                               break;
                        fields = &curnode->symbol->info.rinfo->fields;
                        SLIST_FOREACH(fieldnode, fields, links) {
                                if (num_entries == 0)
@@ -553,11 +564,14 @@ symtable_dump(FILE *ofile, FILE *dfile)
                        }
                        aic_print_reg_dump_end(ofile, dfile,
                                               curnode, num_entries);
+                       reg_used++;
                }
                default:
                        break;
                }
        }
+       fprintf(stderr, "%s: %d of %d register definitions used\n", appname,
+               reg_used, reg_count);
 
        /* Fold in the masks and bits */
        while (SLIST_FIRST(&masks) != NULL) {
@@ -646,7 +660,6 @@ symtable_dump(FILE *ofile, FILE *dfile)
                free(curnode);
        }
 
-       
        fprintf(ofile, "\n\n/* Downloaded Constant Definitions */\n");
 
        for (i = 0; SLIST_FIRST(&download_constants) != NULL; i++) {
index afc22e8b4903cfc3caf81290636e13293989fe70..05190c1a2fb779b880efbb2cc672b65da2058e4c 100644 (file)
@@ -128,6 +128,7 @@ typedef struct expression_info {
 typedef struct symbol {
        char    *name;
        symtype type;
+       int     count;
        union   {
                struct reg_info   *rinfo;
                struct field_info *finfo;
index 8be3d76656faab6fdbfa92548febc77bb4db03e5..a73a6bbb1b2bb37d2426c19987992b4f6f1ef49c 100644 (file)
@@ -2286,17 +2286,14 @@ static void flush_dev(struct scsi_device *dev, unsigned long cursec,
        }
 }
 
-static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost)
+static irqreturn_t ihdlr(struct Scsi_Host *shost)
 {
        struct scsi_cmnd *SCpnt;
        unsigned int i, k, c, status, tstatus, reg;
        struct mssp *spp;
        struct mscp *cpp;
        struct hostdata *ha = (struct hostdata *)shost->hostdata;
-
-       if (shost->irq != irq)
-               panic("%s: ihdlr, irq %d, shost->irq %d.\n", ha->board_name, irq,
-                     shost->irq);
+       int irq = shost->irq;
 
        /* Check if this board need to be serviced */
        if (!(inb(shost->io_port + REG_AUX_STATUS) & IRQ_ASSERTED))
@@ -2535,7 +2532,7 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost)
        return IRQ_NONE;
 }
 
-static irqreturn_t do_interrupt_handler(int irq, void *shap)
+static irqreturn_t do_interrupt_handler(int dummy, void *shap)
 {
        struct Scsi_Host *shost;
        unsigned int j;
@@ -2548,7 +2545,7 @@ static irqreturn_t do_interrupt_handler(int irq, void *shap)
        shost = sh[j];
 
        spin_lock_irqsave(shost->host_lock, spin_flags);
-       ret = ihdlr(irq, shost);
+       ret = ihdlr(shost);
        spin_unlock_irqrestore(shost->host_lock, spin_flags);
        return ret;
 }
index bfdee596889296f3c4ef3a6db1f7201c3f30e34a..a0b6d414953dda3128acc7477827a7dcfbdd429b 100644 (file)
@@ -978,7 +978,7 @@ static int esp_check_spur_intr(struct esp *esp)
                         */
                        if (!esp->ops->dma_error(esp)) {
                                printk(KERN_ERR PFX "esp%d: Spurious irq, "
-                                      "sreg=%x.\n",
+                                      "sreg=%02x.\n",
                                       esp->host->unique_id, esp->sreg);
                                return -1;
                        }
@@ -1447,6 +1447,9 @@ static void esp_msgin_sdtr(struct esp *esp, struct esp_target_data *tp)
        if (offset > 15)
                goto do_reject;
 
+       if (esp->flags & ESP_FLAG_DISABLE_SYNC)
+               offset = 0;
+
        if (offset) {
                int rounded_up, one_clock;
 
@@ -1697,7 +1700,12 @@ again:
                else
                        ent->flags &= ~ESP_CMD_FLAG_WRITE;
 
-               dma_len = esp_dma_length_limit(esp, dma_addr, dma_len);
+               if (esp->ops->dma_length_limit)
+                       dma_len = esp->ops->dma_length_limit(esp, dma_addr,
+                                                            dma_len);
+               else
+                       dma_len = esp_dma_length_limit(esp, dma_addr, dma_len);
+
                esp->data_dma_len = dma_len;
 
                if (!dma_len) {
@@ -1761,7 +1769,6 @@ again:
                esp_advance_dma(esp, ent, cmd, bytes_sent);
                esp_event(esp, ESP_EVENT_CHECK_PHASE);
                goto again;
-               break;
        }
 
        case ESP_EVENT_STATUS: {
@@ -2235,7 +2242,7 @@ static void esp_bootup_reset(struct esp *esp)
 
 static void esp_set_clock_params(struct esp *esp)
 {
-       int fmhz;
+       int fhz;
        u8 ccf;
 
        /* This is getting messy but it has to be done correctly or else
@@ -2270,9 +2277,9 @@ static void esp_set_clock_params(struct esp *esp)
         *    This entails the smallest and largest sync period we could ever
         *    handle on this ESP.
         */
-       fmhz = esp->cfreq;
+       fhz = esp->cfreq;
 
-       ccf = ((fmhz / 1000000) + 4) / 5;
+       ccf = ((fhz / 1000000) + 4) / 5;
        if (ccf == 1)
                ccf = 2;
 
@@ -2281,16 +2288,16 @@ static void esp_set_clock_params(struct esp *esp)
         * been unable to find the clock-frequency PROM property.  All
         * other machines provide useful values it seems.
         */
-       if (fmhz <= 5000000 || ccf < 1 || ccf > 8) {
-               fmhz = 20000000;
+       if (fhz <= 5000000 || ccf < 1 || ccf > 8) {
+               fhz = 20000000;
                ccf = 4;
        }
 
        esp->cfact = (ccf == 8 ? 0 : ccf);
-       esp->cfreq = fmhz;
-       esp->ccycle = ESP_MHZ_TO_CYCLE(fmhz);
+       esp->cfreq = fhz;
+       esp->ccycle = ESP_HZ_TO_CYCLE(fhz);
        esp->ctick = ESP_TICK(ccf, esp->ccycle);
-       esp->neg_defp = ESP_NEG_DEFP(fmhz, ccf);
+       esp->neg_defp = ESP_NEG_DEFP(fhz, ccf);
        esp->sync_defp = SYNC_DEFP_SLOW;
 }
 
@@ -2382,6 +2389,12 @@ static int esp_slave_configure(struct scsi_device *dev)
        struct esp_target_data *tp = &esp->target[dev->id];
        int goal_tags, queue_depth;
 
+       if (esp->flags & ESP_FLAG_DISABLE_SYNC) {
+               /* Bypass async domain validation */
+               dev->ppr  = 0;
+               dev->sdtr = 0;
+       }
+
        goal_tags = 0;
 
        if (dev->tagged_supported) {
index d5576d54ce768f6e801e174c29f69901f36bc111..bb43a138818805d6d3ca683c2c75ce27cef4d87e 100644 (file)
 #define ESP_TIMEO_CONST       8192
 #define ESP_NEG_DEFP(mhz, cfact) \
         ((ESP_BUS_TIMEOUT * ((mhz) / 1000)) / (8192 * (cfact)))
-#define ESP_MHZ_TO_CYCLE(mhertz)  ((1000000000) / ((mhertz) / 1000))
+#define ESP_HZ_TO_CYCLE(hertz)  ((1000000000) / ((hertz) / 1000))
 #define ESP_TICK(ccf, cycle)  ((7682 * (ccf) * (cycle) / 1000))
 
 /* For slow to medium speed input clock rates we shoot for 5mb/s, but for high
@@ -240,9 +240,9 @@ struct esp_cmd_priv {
                int             num_sg;
        } u;
 
-       unsigned int            cur_residue;
+       int                     cur_residue;
        struct scatterlist      *cur_sg;
-       unsigned int            tot_residue;
+       int                     tot_residue;
 };
 #define ESP_CMD_PRIV(CMD)      ((struct esp_cmd_priv *)(&(CMD)->SCp))
 
@@ -368,6 +368,12 @@ struct esp_driver_ops {
         */
        int (*irq_pending)(struct esp *esp);
 
+       /* Return the maximum allowable size of a DMA transfer for a
+        * given buffer.
+        */
+       u32 (*dma_length_limit)(struct esp *esp, u32 dma_addr,
+                               u32 dma_len);
+
        /* Reset the DMA engine entirely.  On return, ESP interrupts
         * should be enabled.  Often the interrupt enabling is
         * controlled in the DMA engine.
@@ -471,6 +477,7 @@ struct esp {
 #define ESP_FLAG_DOING_SLOWCMD 0x00000004
 #define ESP_FLAG_WIDE_CAPABLE  0x00000008
 #define ESP_FLAG_QUICKIRQ_CHECK        0x00000010
+#define ESP_FLAG_DISABLE_SYNC  0x00000020
 
        u8                      select_state;
 #define ESP_SELECT_NONE                0x00 /* Not selecting */
index c264a8c5f01e1f362284476f1513a38f38b56ed1..3690360d7a798ec98f73e58bb83880fe01e99de3 100644 (file)
@@ -199,9 +199,13 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
        if (!shost->can_queue) {
                printk(KERN_ERR "%s: can_queue = 0 no longer supported\n",
                                sht->name);
-               goto out;
+               goto fail;
        }
 
+       error = scsi_setup_command_freelist(shost);
+       if (error)
+               goto fail;
+
        if (!shost->shost_gendev.parent)
                shost->shost_gendev.parent = dev ? dev : &platform_bus;
 
@@ -255,6 +259,8 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
  out_del_gendev:
        device_del(&shost->shost_gendev);
  out:
+       scsi_destroy_command_freelist(shost);
+ fail:
        return error;
 }
 EXPORT_SYMBOL(scsi_add_host);
@@ -284,6 +290,11 @@ static void scsi_host_dev_release(struct device *dev)
        kfree(shost);
 }
 
+struct device_type scsi_host_type = {
+       .name =         "scsi_host",
+       .release =      scsi_host_dev_release,
+};
+
 /**
  * scsi_host_alloc - register a scsi host adapter instance.
  * @sht:       pointer to scsi host template
@@ -376,33 +387,31 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
        else
                shost->dma_boundary = 0xffffffff;
 
-       rval = scsi_setup_command_freelist(shost);
-       if (rval)
-               goto fail_kfree;
-
        device_initialize(&shost->shost_gendev);
        snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d",
                shost->host_no);
-       shost->shost_gendev.release = scsi_host_dev_release;
+#ifndef CONFIG_SYSFS_DEPRECATED
+       shost->shost_gendev.bus = &scsi_bus_type;
+#endif
+       shost->shost_gendev.type = &scsi_host_type;
 
        device_initialize(&shost->shost_dev);
        shost->shost_dev.parent = &shost->shost_gendev;
        shost->shost_dev.class = &shost_class;
        snprintf(shost->shost_dev.bus_id, BUS_ID_SIZE, "host%d",
                 shost->host_no);
+       shost->shost_dev.groups = scsi_sysfs_shost_attr_groups;
 
        shost->ehandler = kthread_run(scsi_error_handler, shost,
                        "scsi_eh_%d", shost->host_no);
        if (IS_ERR(shost->ehandler)) {
                rval = PTR_ERR(shost->ehandler);
-               goto fail_destroy_freelist;
+               goto fail_kfree;
        }
 
        scsi_proc_hostdir_add(shost->hostt);
        return shost;
 
- fail_destroy_freelist:
-       scsi_destroy_command_freelist(shost);
  fail_kfree:
        kfree(shost);
        return NULL;
@@ -496,7 +505,7 @@ void scsi_exit_hosts(void)
 
 int scsi_is_host_device(const struct device *dev)
 {
-       return dev->release == scsi_host_dev_release;
+       return dev->type == &scsi_host_type;
 }
 EXPORT_SYMBOL(scsi_is_host_device);
 
index 93c3fc20aa591f6f243e67f0691a4cf1811a75bf..32553639aded4d9e80ee9f54cf398250adaf0ddf 100644 (file)
@@ -258,8 +258,7 @@ idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
 
        if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
                /* force an abort */
-               hwif->OUTB(WIN_IDLEIMMEDIATE,
-                          hwif->io_ports[IDE_COMMAND_OFFSET]);
+               hwif->OUTB(WIN_IDLEIMMEDIATE, hwif->io_ports.command_addr);
 
        rq->errors++;
 
@@ -393,7 +392,7 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
                printk ("ide-scsi: %s: DMA complete\n", drive->name);
 #endif /* IDESCSI_DEBUG_LOG */
                pc->xferred = pc->req_xfer;
-               (void) HWIF(drive)->ide_dma_end(drive);
+               (void)hwif->dma_ops->dma_end(drive);
        }
 
        /* Clear the interrupt */
@@ -410,9 +409,9 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
                idescsi_end_request (drive, 1, 0);
                return ide_stopped;
        }
-       bcount = (hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]) << 8) |
-                 hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]);
-       ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+       bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) |
+                 hwif->INB(hwif->io_ports.lbam_addr);
+       ireason = hwif->INB(hwif->io_ports.nsect_addr);
 
        if (ireason & CD) {
                printk(KERN_ERR "ide-scsi: CoD != 0 in idescsi_pc_intr\n");
@@ -485,7 +484,7 @@ static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive)
                        "initiated yet DRQ isn't asserted\n");
                return startstop;
        }
-       ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+       ireason = hwif->INB(hwif->io_ports.nsect_addr);
        if ((ireason & CD) == 0 || (ireason & IO)) {
                printk(KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while "
                                "issuing a packet command\n");
@@ -498,7 +497,7 @@ static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive)
        drive->hwif->atapi_output_bytes(drive, scsi->pc->c, 12);
        if (pc->flags & PC_FLAG_DMA_OK) {
                pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
-               hwif->dma_start(drive);
+               hwif->dma_ops->dma_start(drive);
        }
        return ide_started;
 }
@@ -560,7 +559,7 @@ static ide_startstop_t idescsi_issue_pc(ide_drive_t *drive,
 
        if (drive->using_dma && !idescsi_map_sg(drive, pc)) {
                hwif->sg_mapped = 1;
-               dma = !hwif->dma_setup(drive);
+               dma = !hwif->dma_ops->dma_setup(drive);
                hwif->sg_mapped = 0;
        }
 
@@ -575,7 +574,7 @@ static ide_startstop_t idescsi_issue_pc(ide_drive_t *drive,
                return ide_started;
        } else {
                /* Issue the packet command */
-               hwif->OUTB(WIN_PACKETCMD, hwif->io_ports[IDE_COMMAND_OFFSET]);
+               hwif->OUTB(WIN_PACKETCMD, hwif->io_ports.command_addr);
                return idescsi_transfer_pc(drive);
        }
 }
index 5d231015bb2058abebe009fbfdadae98f85cf8d9..b2d481dd37505f43f25d9c0cc79659e900bb25ca 100644 (file)
@@ -217,11 +217,15 @@ static int __devexit esp_jazz_remove(struct platform_device *dev)
        return 0;
 }
 
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:jazz_esp");
+
 static struct platform_driver esp_jazz_driver = {
        .probe          = esp_jazz_probe,
        .remove         = __devexit_p(esp_jazz_remove),
        .driver = {
                .name   = "jazz_esp",
+               .owner  = THIS_MODULE,
        },
 };
 
index a9fbb3f88659bb7bbcb117d9f268df77fb786f61..960baaf11fb181d8e357cb124f35e98a5b883307 100644 (file)
@@ -182,8 +182,8 @@ lpfc_option_rom_version_show(struct device *dev, struct device_attribute *attr,
        return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion);
 }
 static ssize_t
-lpfc_state_show(struct device *dev, struct device_attribute *attr,
-               char *buf)
+lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
+                    char *buf)
 {
        struct Scsi_Host  *shost = class_to_shost(dev);
        struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
@@ -936,7 +936,7 @@ static DEVICE_ATTR(programtype, S_IRUGO, lpfc_programtype_show, NULL);
 static DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL);
 static DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL);
 static DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL);
-static DEVICE_ATTR(state, S_IRUGO, lpfc_state_show, NULL);
+static DEVICE_ATTR(link_state, S_IRUGO, lpfc_link_state_show, NULL);
 static DEVICE_ATTR(option_rom_version, S_IRUGO,
                   lpfc_option_rom_version_show, NULL);
 static DEVICE_ATTR(num_discovered_ports, S_IRUGO,
@@ -1666,7 +1666,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
        &dev_attr_fwrev,
        &dev_attr_hdw,
        &dev_attr_option_rom_version,
-       &dev_attr_state,
+       &dev_attr_link_state,
        &dev_attr_num_discovered_ports,
        &dev_attr_lpfc_drvr_version,
        &dev_attr_lpfc_temp_sensor,
@@ -1714,7 +1714,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
 
 struct device_attribute *lpfc_vport_attrs[] = {
        &dev_attr_info,
-       &dev_attr_state,
+       &dev_attr_link_state,
        &dev_attr_num_discovered_ports,
        &dev_attr_lpfc_drvr_version,
        &dev_attr_lpfc_log_verbose,
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
new file mode 100644 (file)
index 0000000..cd37bd6
--- /dev/null
@@ -0,0 +1,657 @@
+/* mac_esp.c: ESP front-end for Macintosh Quadra systems.
+ *
+ * Adapted from jazz_esp.c and the old mac_esp.c.
+ *
+ * The pseudo DMA algorithm is based on the one used in NetBSD.
+ * See sys/arch/mac68k/obio/esp.c for some background information.
+ *
+ * Copyright (C) 2007-2008 Finn Thain
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/nubus.h>
+
+#include <asm/irq.h>
+#include <asm/dma.h>
+
+#include <asm/macints.h>
+#include <asm/macintosh.h>
+
+#include <scsi/scsi_host.h>
+
+#include "esp_scsi.h"
+
+#define DRV_MODULE_NAME     "mac_esp"
+#define PFX                 DRV_MODULE_NAME ": "
+#define DRV_VERSION         "1.000"
+#define DRV_MODULE_RELDATE  "Sept 15, 2007"
+
+#define MAC_ESP_IO_BASE          0x50F00000
+#define MAC_ESP_REGS_QUADRA      (MAC_ESP_IO_BASE + 0x10000)
+#define MAC_ESP_REGS_QUADRA2     (MAC_ESP_IO_BASE + 0xF000)
+#define MAC_ESP_REGS_QUADRA3     (MAC_ESP_IO_BASE + 0x18000)
+#define MAC_ESP_REGS_SPACING     0x402
+#define MAC_ESP_PDMA_REG         0xF9800024
+#define MAC_ESP_PDMA_REG_SPACING 0x4
+#define MAC_ESP_PDMA_IO_OFFSET   0x100
+
+#define esp_read8(REG)         mac_esp_read8(esp, REG)
+#define esp_write8(VAL, REG)   mac_esp_write8(esp, VAL, REG)
+
+struct mac_esp_priv {
+       struct esp *esp;
+       void __iomem *pdma_regs;
+       void __iomem *pdma_io;
+       int error;
+};
+static struct platform_device *internal_esp, *external_esp;
+
+#define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \
+                              platform_get_drvdata((struct platform_device *) \
+                                                   (esp->dev)))
+
+static inline void mac_esp_write8(struct esp *esp, u8 val, unsigned long reg)
+{
+       nubus_writeb(val, esp->regs + reg * 16);
+}
+
+static inline u8 mac_esp_read8(struct esp *esp, unsigned long reg)
+{
+       return nubus_readb(esp->regs + reg * 16);
+}
+
+/* For pseudo DMA and PIO we need the virtual address
+ * so this address mapping is the identity mapping.
+ */
+
+static dma_addr_t mac_esp_map_single(struct esp *esp, void *buf,
+                                    size_t sz, int dir)
+{
+       return (dma_addr_t)buf;
+}
+
+static int mac_esp_map_sg(struct esp *esp, struct scatterlist *sg,
+                         int num_sg, int dir)
+{
+       int i;
+
+       for (i = 0; i < num_sg; i++)
+               sg[i].dma_address = (u32)sg_virt(&sg[i]);
+       return num_sg;
+}
+
+static void mac_esp_unmap_single(struct esp *esp, dma_addr_t addr,
+                                size_t sz, int dir)
+{
+       /* Nothing to do. */
+}
+
+static void mac_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
+                            int num_sg, int dir)
+{
+       /* Nothing to do. */
+}
+
+static void mac_esp_reset_dma(struct esp *esp)
+{
+       /* Nothing to do. */
+}
+
+static void mac_esp_dma_drain(struct esp *esp)
+{
+       /* Nothing to do. */
+}
+
+static void mac_esp_dma_invalidate(struct esp *esp)
+{
+       /* Nothing to do. */
+}
+
+static int mac_esp_dma_error(struct esp *esp)
+{
+       return MAC_ESP_GET_PRIV(esp)->error;
+}
+
+static inline int mac_esp_wait_for_empty_fifo(struct esp *esp)
+{
+       struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
+       int i = 500000;
+
+       do {
+               if (!(esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES))
+                       return 0;
+
+               if (esp_read8(ESP_STATUS) & ESP_STAT_INTR)
+                       return 1;
+
+               udelay(2);
+       } while (--i);
+
+       printk(KERN_ERR PFX "FIFO is not empty (sreg %02x)\n",
+              esp_read8(ESP_STATUS));
+       mep->error = 1;
+       return 1;
+}
+
+static inline int mac_esp_wait_for_dreq(struct esp *esp)
+{
+       struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
+       int i = 500000;
+
+       do {
+               if (mep->pdma_regs == NULL) {
+                       if (mac_irq_pending(IRQ_MAC_SCSIDRQ))
+                               return 0;
+               } else {
+                       if (nubus_readl(mep->pdma_regs) & 0x200)
+                               return 0;
+               }
+
+               if (esp_read8(ESP_STATUS) & ESP_STAT_INTR)
+                       return 1;
+
+               udelay(2);
+       } while (--i);
+
+       printk(KERN_ERR PFX "PDMA timeout (sreg %02x)\n",
+              esp_read8(ESP_STATUS));
+       mep->error = 1;
+       return 1;
+}
+
+#define MAC_ESP_PDMA_LOOP(operands) \
+       asm volatile ( \
+            "       tstw %2                   \n" \
+            "       jbeq 20f                  \n" \
+            "1:     movew " operands "        \n" \
+            "2:     movew " operands "        \n" \
+            "3:     movew " operands "        \n" \
+            "4:     movew " operands "        \n" \
+            "5:     movew " operands "        \n" \
+            "6:     movew " operands "        \n" \
+            "7:     movew " operands "        \n" \
+            "8:     movew " operands "        \n" \
+            "9:     movew " operands "        \n" \
+            "10:    movew " operands "        \n" \
+            "11:    movew " operands "        \n" \
+            "12:    movew " operands "        \n" \
+            "13:    movew " operands "        \n" \
+            "14:    movew " operands "        \n" \
+            "15:    movew " operands "        \n" \
+            "16:    movew " operands "        \n" \
+            "       subqw #1,%2               \n" \
+            "       jbne 1b                   \n" \
+            "20:    tstw %3                   \n" \
+            "       jbeq 30f                  \n" \
+            "21:    movew " operands "        \n" \
+            "       subqw #1,%3               \n" \
+            "       jbne 21b                  \n" \
+            "30:    tstw %4                   \n" \
+            "       jbeq 40f                  \n" \
+            "31:    moveb " operands "        \n" \
+            "32:    nop                       \n" \
+            "40:                              \n" \
+            "                                 \n" \
+            "       .section __ex_table,\"a\" \n" \
+            "       .align  4                 \n" \
+            "       .long   1b,40b            \n" \
+            "       .long   2b,40b            \n" \
+            "       .long   3b,40b            \n" \
+            "       .long   4b,40b            \n" \
+            "       .long   5b,40b            \n" \
+            "       .long   6b,40b            \n" \
+            "       .long   7b,40b            \n" \
+            "       .long   8b,40b            \n" \
+            "       .long   9b,40b            \n" \
+            "       .long  10b,40b            \n" \
+            "       .long  11b,40b            \n" \
+            "       .long  12b,40b            \n" \
+            "       .long  13b,40b            \n" \
+            "       .long  14b,40b            \n" \
+            "       .long  15b,40b            \n" \
+            "       .long  16b,40b            \n" \
+            "       .long  21b,40b            \n" \
+            "       .long  31b,40b            \n" \
+            "       .long  32b,40b            \n" \
+            "       .previous                 \n" \
+            : "+a" (addr) \
+            : "a" (mep->pdma_io), "r" (count32), "r" (count2), "g" (esp_count))
+
+static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count,
+                                 u32 dma_count, int write, u8 cmd)
+{
+       struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       mep->error = 0;
+
+       if (!write)
+               scsi_esp_cmd(esp, ESP_CMD_FLUSH);
+
+       esp_write8((esp_count >> 0) & 0xFF, ESP_TCLOW);
+       esp_write8((esp_count >> 8) & 0xFF, ESP_TCMED);
+
+       scsi_esp_cmd(esp, cmd);
+
+       do {
+               unsigned int count32 = esp_count >> 5;
+               unsigned int count2 = (esp_count & 0x1F) >> 1;
+               unsigned int start_addr = addr;
+
+               if (mac_esp_wait_for_dreq(esp))
+                       break;
+
+               if (write) {
+                       MAC_ESP_PDMA_LOOP("%1@,%0@+");
+
+                       esp_count -= addr - start_addr;
+               } else {
+                       unsigned int n;
+
+                       MAC_ESP_PDMA_LOOP("%0@+,%1@");
+
+                       if (mac_esp_wait_for_empty_fifo(esp))
+                               break;
+
+                       n = (esp_read8(ESP_TCMED) << 8) + esp_read8(ESP_TCLOW);
+                       addr = start_addr + esp_count - n;
+                       esp_count = n;
+               }
+       } while (esp_count);
+
+       local_irq_restore(flags);
+}
+
+/*
+ * Programmed IO routines follow.
+ */
+
+static inline int mac_esp_wait_for_fifo(struct esp *esp)
+{
+       int i = 500000;
+
+       do {
+               if (esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES)
+                       return 0;
+
+               udelay(2);
+       } while (--i);
+
+       printk(KERN_ERR PFX "FIFO is empty (sreg %02x)\n",
+              esp_read8(ESP_STATUS));
+       return 1;
+}
+
+static inline int mac_esp_wait_for_intr(struct esp *esp)
+{
+       int i = 500000;
+
+       do {
+               esp->sreg = esp_read8(ESP_STATUS);
+               if (esp->sreg & ESP_STAT_INTR)
+                       return 0;
+
+               udelay(2);
+       } while (--i);
+
+       printk(KERN_ERR PFX "IRQ timeout (sreg %02x)\n", esp->sreg);
+       return 1;
+}
+
+#define MAC_ESP_PIO_LOOP(operands, reg1) \
+       asm volatile ( \
+            "1:     moveb " operands " \n" \
+            "       subqw #1,%1        \n" \
+            "       jbne 1b            \n" \
+            : "+a" (addr), "+r" (reg1) \
+            : "a" (fifo))
+
+#define MAC_ESP_PIO_FILL(operands, reg1) \
+       asm volatile ( \
+            "       moveb " operands " \n" \
+            "       moveb " operands " \n" \
+            "       moveb " operands " \n" \
+            "       moveb " operands " \n" \
+            "       moveb " operands " \n" \
+            "       moveb " operands " \n" \
+            "       moveb " operands " \n" \
+            "       moveb " operands " \n" \
+            "       moveb " operands " \n" \
+            "       moveb " operands " \n" \
+            "       moveb " operands " \n" \
+            "       moveb " operands " \n" \
+            "       moveb " operands " \n" \
+            "       moveb " operands " \n" \
+            "       moveb " operands " \n" \
+            "       moveb " operands " \n" \
+            "       subqw #8,%1        \n" \
+            "       subqw #8,%1        \n" \
+            : "+a" (addr), "+r" (reg1) \
+            : "a" (fifo))
+
+#define MAC_ESP_FIFO_SIZE 16
+
+static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
+                                u32 dma_count, int write, u8 cmd)
+{
+       unsigned long flags;
+       struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
+       u8 *fifo = esp->regs + ESP_FDATA * 16;
+
+       local_irq_save(flags);
+
+       cmd &= ~ESP_CMD_DMA;
+       mep->error = 0;
+
+       if (write) {
+               scsi_esp_cmd(esp, cmd);
+
+               if (!mac_esp_wait_for_intr(esp)) {
+                       if (mac_esp_wait_for_fifo(esp))
+                               esp_count = 0;
+               } else {
+                       esp_count = 0;
+               }
+       } else {
+               scsi_esp_cmd(esp, ESP_CMD_FLUSH);
+
+               if (esp_count >= MAC_ESP_FIFO_SIZE)
+                       MAC_ESP_PIO_FILL("%0@+,%2@", esp_count);
+               else
+                       MAC_ESP_PIO_LOOP("%0@+,%2@", esp_count);
+
+               scsi_esp_cmd(esp, cmd);
+       }
+
+       while (esp_count) {
+               unsigned int n;
+
+               if (mac_esp_wait_for_intr(esp)) {
+                       mep->error = 1;
+                       break;
+               }
+
+               if (esp->sreg & ESP_STAT_SPAM) {
+                       printk(KERN_ERR PFX "gross error\n");
+                       mep->error = 1;
+                       break;
+               }
+
+               n = esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES;
+
+               if (write) {
+                       if (n > esp_count)
+                               n = esp_count;
+                       esp_count -= n;
+
+                       MAC_ESP_PIO_LOOP("%2@,%0@+", n);
+
+                       if ((esp->sreg & ESP_STAT_PMASK) == ESP_STATP)
+                               break;
+
+                       if (esp_count) {
+                               esp->ireg = esp_read8(ESP_INTRPT);
+                               if (esp->ireg & ESP_INTR_DC)
+                                       break;
+
+                               scsi_esp_cmd(esp, ESP_CMD_TI);
+                       }
+               } else {
+                       esp->ireg = esp_read8(ESP_INTRPT);
+                       if (esp->ireg & ESP_INTR_DC)
+                               break;
+
+                       n = MAC_ESP_FIFO_SIZE - n;
+                       if (n > esp_count)
+                               n = esp_count;
+
+                       if (n == MAC_ESP_FIFO_SIZE) {
+                               MAC_ESP_PIO_FILL("%0@+,%2@", esp_count);
+                       } else {
+                               esp_count -= n;
+                               MAC_ESP_PIO_LOOP("%0@+,%2@", n);
+                       }
+
+                       scsi_esp_cmd(esp, ESP_CMD_TI);
+               }
+       }
+
+       local_irq_restore(flags);
+}
+
+static int mac_esp_irq_pending(struct esp *esp)
+{
+       if (esp_read8(ESP_STATUS) & ESP_STAT_INTR)
+               return 1;
+       return 0;
+}
+
+static u32 mac_esp_dma_length_limit(struct esp *esp, u32 dma_addr, u32 dma_len)
+{
+       return dma_len > 0xFFFF ? 0xFFFF : dma_len;
+}
+
+static struct esp_driver_ops mac_esp_ops = {
+       .esp_write8       = mac_esp_write8,
+       .esp_read8        = mac_esp_read8,
+       .map_single       = mac_esp_map_single,
+       .map_sg           = mac_esp_map_sg,
+       .unmap_single     = mac_esp_unmap_single,
+       .unmap_sg         = mac_esp_unmap_sg,
+       .irq_pending      = mac_esp_irq_pending,
+       .dma_length_limit = mac_esp_dma_length_limit,
+       .reset_dma        = mac_esp_reset_dma,
+       .dma_drain        = mac_esp_dma_drain,
+       .dma_invalidate   = mac_esp_dma_invalidate,
+       .send_dma_cmd     = mac_esp_send_pdma_cmd,
+       .dma_error        = mac_esp_dma_error,
+};
+
+static int __devinit esp_mac_probe(struct platform_device *dev)
+{
+       struct scsi_host_template *tpnt = &scsi_esp_template;
+       struct Scsi_Host *host;
+       struct esp *esp;
+       int err;
+       int chips_present;
+       struct mac_esp_priv *mep;
+
+       if (!MACH_IS_MAC)
+               return -ENODEV;
+
+       switch (macintosh_config->scsi_type) {
+       case MAC_SCSI_QUADRA:
+       case MAC_SCSI_QUADRA3:
+               chips_present = 1;
+               break;
+       case MAC_SCSI_QUADRA2:
+               if ((macintosh_config->ident == MAC_MODEL_Q900) ||
+                   (macintosh_config->ident == MAC_MODEL_Q950))
+                       chips_present = 2;
+               else
+                       chips_present = 1;
+               break;
+       default:
+               chips_present = 0;
+       }
+
+       if (dev->id + 1 > chips_present)
+               return -ENODEV;
+
+       host = scsi_host_alloc(tpnt, sizeof(struct esp));
+
+       err = -ENOMEM;
+       if (!host)
+               goto fail;
+
+       host->max_id = 8;
+       host->use_clustering = DISABLE_CLUSTERING;
+       esp = shost_priv(host);
+
+       esp->host = host;
+       esp->dev = dev;
+
+       esp->command_block = kzalloc(16, GFP_KERNEL);
+       if (!esp->command_block)
+               goto fail_unlink;
+       esp->command_block_dma = (dma_addr_t)esp->command_block;
+
+       esp->scsi_id = 7;
+       host->this_id = esp->scsi_id;
+       esp->scsi_id_mask = 1 << esp->scsi_id;
+
+       mep = kzalloc(sizeof(struct mac_esp_priv), GFP_KERNEL);
+       if (!mep)
+               goto fail_free_command_block;
+       mep->esp = esp;
+       platform_set_drvdata(dev, mep);
+
+       switch (macintosh_config->scsi_type) {
+       case MAC_SCSI_QUADRA:
+               esp->cfreq     = 16500000;
+               esp->regs      = (void __iomem *)MAC_ESP_REGS_QUADRA;
+               mep->pdma_io   = esp->regs + MAC_ESP_PDMA_IO_OFFSET;
+               mep->pdma_regs = NULL;
+               break;
+       case MAC_SCSI_QUADRA2:
+               esp->cfreq     = 25000000;
+               esp->regs      = (void __iomem *)(MAC_ESP_REGS_QUADRA2 +
+                                dev->id * MAC_ESP_REGS_SPACING);
+               mep->pdma_io   = esp->regs + MAC_ESP_PDMA_IO_OFFSET;
+               mep->pdma_regs = (void __iomem *)(MAC_ESP_PDMA_REG +
+                                dev->id * MAC_ESP_PDMA_REG_SPACING);
+               nubus_writel(0x1d1, mep->pdma_regs);
+               break;
+       case MAC_SCSI_QUADRA3:
+               /* These quadras have a real DMA controller (the PSC) but we
+                * don't know how to drive it so we must use PIO instead.
+                */
+               esp->cfreq     = 25000000;
+               esp->regs      = (void __iomem *)MAC_ESP_REGS_QUADRA3;
+               mep->pdma_io   = NULL;
+               mep->pdma_regs = NULL;
+               break;
+       }
+
+       esp->ops = &mac_esp_ops;
+       if (mep->pdma_io == NULL) {
+               printk(KERN_INFO PFX "using PIO for controller %d\n", dev->id);
+               esp_write8(0, ESP_TCLOW);
+               esp_write8(0, ESP_TCMED);
+               esp->flags = ESP_FLAG_DISABLE_SYNC;
+               mac_esp_ops.send_dma_cmd = mac_esp_send_pio_cmd;
+       } else {
+               printk(KERN_INFO PFX "using PDMA for controller %d\n", dev->id);
+       }
+
+       host->irq = IRQ_MAC_SCSI;
+       err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "Mac ESP",
+                         esp);
+       if (err < 0)
+               goto fail_free_priv;
+
+       err = scsi_esp_register(esp, &dev->dev);
+       if (err)
+               goto fail_free_irq;
+
+       return 0;
+
+fail_free_irq:
+       free_irq(host->irq, esp);
+fail_free_priv:
+       kfree(mep);
+fail_free_command_block:
+       kfree(esp->command_block);
+fail_unlink:
+       scsi_host_put(host);
+fail:
+       return err;
+}
+
+static int __devexit esp_mac_remove(struct platform_device *dev)
+{
+       struct mac_esp_priv *mep = platform_get_drvdata(dev);
+       struct esp *esp = mep->esp;
+       unsigned int irq = esp->host->irq;
+
+       scsi_esp_unregister(esp);
+
+       free_irq(irq, esp);
+
+       kfree(mep);
+
+       kfree(esp->command_block);
+
+       scsi_host_put(esp->host);
+
+       return 0;
+}
+
+static struct platform_driver esp_mac_driver = {
+       .probe    = esp_mac_probe,
+       .remove   = __devexit_p(esp_mac_remove),
+       .driver   = {
+               .name     = DRV_MODULE_NAME,
+       },
+};
+
+static int __init mac_esp_init(void)
+{
+       int err;
+
+       err = platform_driver_register(&esp_mac_driver);
+       if (err)
+               return err;
+
+       internal_esp = platform_device_alloc(DRV_MODULE_NAME, 0);
+       if (internal_esp && platform_device_add(internal_esp)) {
+               platform_device_put(internal_esp);
+               internal_esp = NULL;
+       }
+
+       external_esp = platform_device_alloc(DRV_MODULE_NAME, 1);
+       if (external_esp && platform_device_add(external_esp)) {
+               platform_device_put(external_esp);
+               external_esp = NULL;
+       }
+
+       if (internal_esp || external_esp) {
+               return 0;
+       } else {
+               platform_driver_unregister(&esp_mac_driver);
+               return -ENOMEM;
+       }
+}
+
+static void __exit mac_esp_exit(void)
+{
+       platform_driver_unregister(&esp_mac_driver);
+
+       if (internal_esp) {
+               platform_device_unregister(internal_esp);
+               internal_esp = NULL;
+       }
+       if (external_esp) {
+               platform_device_unregister(external_esp);
+               external_esp = NULL;
+       }
+}
+
+MODULE_DESCRIPTION("Mac ESP SCSI driver");
+MODULE_AUTHOR("Finn Thain <fthain@telegraphics.com.au>");
+MODULE_LICENSE("GPLv2");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(mac_esp_init);
+module_exit(mac_esp_exit);
index d61df036910c1f46579807e5a17b9fee1ff73417..287690853caf2594ddc1fa1cd63f58b87b002562 100644 (file)
@@ -609,8 +609,8 @@ qla2x00_pci_info_show(struct device *dev, struct device_attribute *attr,
 }
 
 static ssize_t
-qla2x00_state_show(struct device *dev, struct device_attribute *attr,
-                  char *buf)
+qla2x00_link_state_show(struct device *dev, struct device_attribute *attr,
+                       char *buf)
 {
        scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
        int len = 0;
@@ -814,7 +814,7 @@ static DEVICE_ATTR(isp_id, S_IRUGO, qla2x00_isp_id_show, NULL);
 static DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL);
 static DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL);
 static DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL);
-static DEVICE_ATTR(state, S_IRUGO, qla2x00_state_show, NULL);
+static DEVICE_ATTR(link_state, S_IRUGO, qla2x00_link_state_show, NULL);
 static DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show, qla2x00_zio_store);
 static DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show,
                   qla2x00_zio_timer_store);
@@ -838,7 +838,7 @@ struct device_attribute *qla2x00_host_attrs[] = {
        &dev_attr_model_name,
        &dev_attr_model_desc,
        &dev_attr_pci_info,
-       &dev_attr_state,
+       &dev_attr_link_state,
        &dev_attr_zio,
        &dev_attr_zio_timer,
        &dev_attr_beacon,
index 9d12d9f2620930015ec2d56c29a11b58660fe4de..cbef785765cf2ead72b64899a260a75bfca849d2 100644 (file)
@@ -38,78 +38,38 @@ qla2xxx_copy_queues(scsi_qla_host_t *ha, void *ptr)
 }
 
 static int
-qla24xx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram,
-    uint32_t cram_size, uint32_t *ext_mem, void **nxt)
+qla24xx_dump_ram(scsi_qla_host_t *ha, uint32_t addr, uint32_t *ram,
+    uint32_t ram_dwords, void **nxt)
 {
        int rval;
-       uint32_t cnt, stat, timer, risc_address, ext_mem_cnt;
-       uint16_t mb[4];
+       uint32_t cnt, stat, timer, dwords, idx;
+       uint16_t mb0;
        struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+       dma_addr_t dump_dma = ha->gid_list_dma;
+       uint32_t *dump = (uint32_t *)ha->gid_list;
 
        rval = QLA_SUCCESS;
-       risc_address = ext_mem_cnt = 0;
-       memset(mb, 0, sizeof(mb));
+       mb0 = 0;
 
-       /* Code RAM. */
-       risc_address = 0x20000;
-       WRT_REG_WORD(&reg->mailbox0, MBC_READ_RAM_EXTENDED);
+       WRT_REG_WORD(&reg->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED);
        clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
 
-       for (cnt = 0; cnt < cram_size / 4 && rval == QLA_SUCCESS;
-           cnt++, risc_address++) {
-               WRT_REG_WORD(&reg->mailbox1, LSW(risc_address));
-               WRT_REG_WORD(&reg->mailbox8, MSW(risc_address));
-               RD_REG_WORD(&reg->mailbox8);
-               WRT_REG_DWORD(&reg->hccr, HCCRX_SET_HOST_INT);
-
-               for (timer = 6000000; timer; timer--) {
-                       /* Check for pending interrupts. */
-                       stat = RD_REG_DWORD(&reg->host_status);
-                       if (stat & HSRX_RISC_INT) {
-                               stat &= 0xff;
+       dwords = GID_LIST_SIZE / 4;
+       for (cnt = 0; cnt < ram_dwords && rval == QLA_SUCCESS;
+           cnt += dwords, addr += dwords) {
+               if (cnt + dwords > ram_dwords)
+                       dwords = ram_dwords - cnt;
 
-                               if (stat == 0x1 || stat == 0x2 ||
-                                   stat == 0x10 || stat == 0x11) {
-                                       set_bit(MBX_INTERRUPT,
-                                           &ha->mbx_cmd_flags);
+               WRT_REG_WORD(&reg->mailbox1, LSW(addr));
+               WRT_REG_WORD(&reg->mailbox8, MSW(addr));
 
-                                       mb[0] = RD_REG_WORD(&reg->mailbox0);
-                                       mb[2] = RD_REG_WORD(&reg->mailbox2);
-                                       mb[3] = RD_REG_WORD(&reg->mailbox3);
+               WRT_REG_WORD(&reg->mailbox2, MSW(dump_dma));
+               WRT_REG_WORD(&reg->mailbox3, LSW(dump_dma));
+               WRT_REG_WORD(&reg->mailbox6, MSW(MSD(dump_dma)));
+               WRT_REG_WORD(&reg->mailbox7, LSW(MSD(dump_dma)));
 
-                                       WRT_REG_DWORD(&reg->hccr,
-                                           HCCRX_CLR_RISC_INT);
-                                       RD_REG_DWORD(&reg->hccr);
-                                       break;
-                               }
-
-                               /* Clear this intr; it wasn't a mailbox intr */
-                               WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
-                               RD_REG_DWORD(&reg->hccr);
-                       }
-                       udelay(5);
-               }
-
-               if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
-                       rval = mb[0] & MBS_MASK;
-                       code_ram[cnt] = htonl((mb[3] << 16) | mb[2]);
-               } else {
-                       rval = QLA_FUNCTION_FAILED;
-               }
-       }
-
-       if (rval == QLA_SUCCESS) {
-               /* External Memory. */
-               risc_address = 0x100000;
-               ext_mem_cnt = ha->fw_memory_size - 0x100000 + 1;
-               WRT_REG_WORD(&reg->mailbox0, MBC_READ_RAM_EXTENDED);
-               clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
-       }
-       for (cnt = 0; cnt < ext_mem_cnt && rval == QLA_SUCCESS;
-           cnt++, risc_address++) {
-               WRT_REG_WORD(&reg->mailbox1, LSW(risc_address));
-               WRT_REG_WORD(&reg->mailbox8, MSW(risc_address));
-               RD_REG_WORD(&reg->mailbox8);
+               WRT_REG_WORD(&reg->mailbox4, MSW(dwords));
+               WRT_REG_WORD(&reg->mailbox5, LSW(dwords));
                WRT_REG_DWORD(&reg->hccr, HCCRX_SET_HOST_INT);
 
                for (timer = 6000000; timer; timer--) {
@@ -123,9 +83,7 @@ qla24xx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram,
                                        set_bit(MBX_INTERRUPT,
                                            &ha->mbx_cmd_flags);
 
-                                       mb[0] = RD_REG_WORD(&reg->mailbox0);
-                                       mb[2] = RD_REG_WORD(&reg->mailbox2);
-                                       mb[3] = RD_REG_WORD(&reg->mailbox3);
+                                       mb0 = RD_REG_WORD(&reg->mailbox0);
 
                                        WRT_REG_DWORD(&reg->hccr,
                                            HCCRX_CLR_RISC_INT);
@@ -141,17 +99,34 @@ qla24xx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram,
                }
 
                if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
-                       rval = mb[0] & MBS_MASK;
-                       ext_mem[cnt] = htonl((mb[3] << 16) | mb[2]);
+                       rval = mb0 & MBS_MASK;
+                       for (idx = 0; idx < dwords; idx++)
+                               ram[cnt + idx] = swab32(dump[idx]);
                } else {
                        rval = QLA_FUNCTION_FAILED;
                }
        }
 
-       *nxt = rval == QLA_SUCCESS ? &ext_mem[cnt]: NULL;
+       *nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL;
        return rval;
 }
 
+static int
+qla24xx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram,
+    uint32_t cram_size, void **nxt)
+{
+       int rval;
+
+       /* Code RAM. */
+       rval = qla24xx_dump_ram(ha, 0x20000, code_ram, cram_size / 4, nxt);
+       if (rval != QLA_SUCCESS)
+               return rval;
+
+       /* External Memory. */
+       return qla24xx_dump_ram(ha, 0x100000, *nxt,
+           ha->fw_memory_size - 0x100000 + 1, nxt);
+}
+
 static uint32_t *
 qla24xx_read_window(struct device_reg_24xx __iomem *reg, uint32_t iobase,
     uint32_t count, uint32_t *buf)
@@ -239,6 +214,90 @@ qla24xx_soft_reset(scsi_qla_host_t *ha)
        return rval;
 }
 
+static int
+qla2xxx_dump_ram(scsi_qla_host_t *ha, uint32_t addr, uint16_t *ram,
+    uint16_t ram_words, void **nxt)
+{
+       int rval;
+       uint32_t cnt, stat, timer, words, idx;
+       uint16_t mb0;
+       struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+       dma_addr_t dump_dma = ha->gid_list_dma;
+       uint16_t *dump = (uint16_t *)ha->gid_list;
+
+       rval = QLA_SUCCESS;
+       mb0 = 0;
+
+       WRT_MAILBOX_REG(ha, reg, 0, MBC_DUMP_RISC_RAM_EXTENDED);
+       clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+
+       words = GID_LIST_SIZE / 2;
+       for (cnt = 0; cnt < ram_words && rval == QLA_SUCCESS;
+           cnt += words, addr += words) {
+               if (cnt + words > ram_words)
+                       words = ram_words - cnt;
+
+               WRT_MAILBOX_REG(ha, reg, 1, LSW(addr));
+               WRT_MAILBOX_REG(ha, reg, 8, MSW(addr));
+
+               WRT_MAILBOX_REG(ha, reg, 2, MSW(dump_dma));
+               WRT_MAILBOX_REG(ha, reg, 3, LSW(dump_dma));
+               WRT_MAILBOX_REG(ha, reg, 6, MSW(MSD(dump_dma)));
+               WRT_MAILBOX_REG(ha, reg, 7, LSW(MSD(dump_dma)));
+
+               WRT_MAILBOX_REG(ha, reg, 4, words);
+               WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
+
+               for (timer = 6000000; timer; timer--) {
+                       /* Check for pending interrupts. */
+                       stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
+                       if (stat & HSR_RISC_INT) {
+                               stat &= 0xff;
+
+                               if (stat == 0x1 || stat == 0x2) {
+                                       set_bit(MBX_INTERRUPT,
+                                           &ha->mbx_cmd_flags);
+
+                                       mb0 = RD_MAILBOX_REG(ha, reg, 0);
+
+                                       /* Release mailbox registers. */
+                                       WRT_REG_WORD(&reg->semaphore, 0);
+                                       WRT_REG_WORD(&reg->hccr,
+                                           HCCR_CLR_RISC_INT);
+                                       RD_REG_WORD(&reg->hccr);
+                                       break;
+                               } else if (stat == 0x10 || stat == 0x11) {
+                                       set_bit(MBX_INTERRUPT,
+                                           &ha->mbx_cmd_flags);
+
+                                       mb0 = RD_MAILBOX_REG(ha, reg, 0);
+
+                                       WRT_REG_WORD(&reg->hccr,
+                                           HCCR_CLR_RISC_INT);
+                                       RD_REG_WORD(&reg->hccr);
+                                       break;
+                               }
+
+                               /* clear this intr; it wasn't a mailbox intr */
+                               WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
+                               RD_REG_WORD(&reg->hccr);
+                       }
+                       udelay(5);
+               }
+
+               if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
+                       rval = mb0 & MBS_MASK;
+                       for (idx = 0; idx < words; idx++)
+                               ram[cnt + idx] = swab16(dump[idx]);
+               } else {
+                       rval = QLA_FUNCTION_FAILED;
+               }
+       }
+
+       *nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL;
+       return rval;
+}
+
 static inline void
 qla2xxx_read_window(struct device_reg_2xxx __iomem *reg, uint32_t count,
     uint16_t *buf)
@@ -258,19 +317,14 @@ void
 qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
 {
        int             rval;
-       uint32_t        cnt, timer;
-       uint32_t        risc_address;
-       uint16_t        mb0, mb2;
+       uint32_t        cnt;
 
-       uint32_t        stat;
        struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
        uint16_t __iomem *dmp_reg;
        unsigned long   flags;
        struct qla2300_fw_dump  *fw;
-       uint32_t        data_ram_cnt;
+       void            *nxt;
 
-       risc_address = data_ram_cnt = 0;
-       mb0 = mb2 = 0;
        flags = 0;
 
        if (!hardware_locked)
@@ -388,185 +442,23 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
                }
        }
 
-       if (rval == QLA_SUCCESS) {
-               /* Get RISC SRAM. */
-               risc_address = 0x800;
-               WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_WORD);
-               clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
-       }
-       for (cnt = 0; cnt < sizeof(fw->risc_ram) / 2 && rval == QLA_SUCCESS;
-           cnt++, risc_address++) {
-               WRT_MAILBOX_REG(ha, reg, 1, (uint16_t)risc_address);
-               WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
-
-               for (timer = 6000000; timer; timer--) {
-                       /* Check for pending interrupts. */
-                       stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
-                       if (stat & HSR_RISC_INT) {
-                               stat &= 0xff;
-
-                               if (stat == 0x1 || stat == 0x2) {
-                                       set_bit(MBX_INTERRUPT,
-                                           &ha->mbx_cmd_flags);
-
-                                       mb0 = RD_MAILBOX_REG(ha, reg, 0);
-                                       mb2 = RD_MAILBOX_REG(ha, reg, 2);
-
-                                       /* Release mailbox registers. */
-                                       WRT_REG_WORD(&reg->semaphore, 0);
-                                       WRT_REG_WORD(&reg->hccr,
-                                           HCCR_CLR_RISC_INT);
-                                       RD_REG_WORD(&reg->hccr);
-                                       break;
-                               } else if (stat == 0x10 || stat == 0x11) {
-                                       set_bit(MBX_INTERRUPT,
-                                           &ha->mbx_cmd_flags);
-
-                                       mb0 = RD_MAILBOX_REG(ha, reg, 0);
-                                       mb2 = RD_MAILBOX_REG(ha, reg, 2);
-
-                                       WRT_REG_WORD(&reg->hccr,
-                                           HCCR_CLR_RISC_INT);
-                                       RD_REG_WORD(&reg->hccr);
-                                       break;
-                               }
-
-                               /* clear this intr; it wasn't a mailbox intr */
-                               WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
-                               RD_REG_WORD(&reg->hccr);
-                       }
-                       udelay(5);
-               }
-
-               if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
-                       rval = mb0 & MBS_MASK;
-                       fw->risc_ram[cnt] = htons(mb2);
-               } else {
-                       rval = QLA_FUNCTION_FAILED;
-               }
-       }
-
-       if (rval == QLA_SUCCESS) {
-               /* Get stack SRAM. */
-               risc_address = 0x10000;
-               WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_EXTENDED);
-               clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
-       }
-       for (cnt = 0; cnt < sizeof(fw->stack_ram) / 2 && rval == QLA_SUCCESS;
-           cnt++, risc_address++) {
-               WRT_MAILBOX_REG(ha, reg, 1, LSW(risc_address));
-               WRT_MAILBOX_REG(ha, reg, 8, MSW(risc_address));
-               WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
-
-               for (timer = 6000000; timer; timer--) {
-                       /* Check for pending interrupts. */
-                       stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
-                       if (stat & HSR_RISC_INT) {
-                               stat &= 0xff;
-
-                               if (stat == 0x1 || stat == 0x2) {
-                                       set_bit(MBX_INTERRUPT,
-                                           &ha->mbx_cmd_flags);
-
-                                       mb0 = RD_MAILBOX_REG(ha, reg, 0);
-                                       mb2 = RD_MAILBOX_REG(ha, reg, 2);
-
-                                       /* Release mailbox registers. */
-                                       WRT_REG_WORD(&reg->semaphore, 0);
-                                       WRT_REG_WORD(&reg->hccr,
-                                           HCCR_CLR_RISC_INT);
-                                       RD_REG_WORD(&reg->hccr);
-                                       break;
-                               } else if (stat == 0x10 || stat == 0x11) {
-                                       set_bit(MBX_INTERRUPT,
-                                           &ha->mbx_cmd_flags);
-
-                                       mb0 = RD_MAILBOX_REG(ha, reg, 0);
-                                       mb2 = RD_MAILBOX_REG(ha, reg, 2);
-
-                                       WRT_REG_WORD(&reg->hccr,
-                                           HCCR_CLR_RISC_INT);
-                                       RD_REG_WORD(&reg->hccr);
-                                       break;
-                               }
-
-                               /* clear this intr; it wasn't a mailbox intr */
-                               WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
-                               RD_REG_WORD(&reg->hccr);
-                       }
-                       udelay(5);
-               }
-
-               if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
-                       rval = mb0 & MBS_MASK;
-                       fw->stack_ram[cnt] = htons(mb2);
-               } else {
-                       rval = QLA_FUNCTION_FAILED;
-               }
-       }
-
-       if (rval == QLA_SUCCESS) {
-               /* Get data SRAM. */
-               risc_address = 0x11000;
-               data_ram_cnt = ha->fw_memory_size - risc_address + 1;
-               WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_EXTENDED);
-               clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
-       }
-       for (cnt = 0; cnt < data_ram_cnt && rval == QLA_SUCCESS;
-           cnt++, risc_address++) {
-               WRT_MAILBOX_REG(ha, reg, 1, LSW(risc_address));
-               WRT_MAILBOX_REG(ha, reg, 8, MSW(risc_address));
-               WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
-
-               for (timer = 6000000; timer; timer--) {
-                       /* Check for pending interrupts. */
-                       stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
-                       if (stat & HSR_RISC_INT) {
-                               stat &= 0xff;
-
-                               if (stat == 0x1 || stat == 0x2) {
-                                       set_bit(MBX_INTERRUPT,
-                                           &ha->mbx_cmd_flags);
-
-                                       mb0 = RD_MAILBOX_REG(ha, reg, 0);
-                                       mb2 = RD_MAILBOX_REG(ha, reg, 2);
-
-                                       /* Release mailbox registers. */
-                                       WRT_REG_WORD(&reg->semaphore, 0);
-                                       WRT_REG_WORD(&reg->hccr,
-                                           HCCR_CLR_RISC_INT);
-                                       RD_REG_WORD(&reg->hccr);
-                                       break;
-                               } else if (stat == 0x10 || stat == 0x11) {
-                                       set_bit(MBX_INTERRUPT,
-                                           &ha->mbx_cmd_flags);
-
-                                       mb0 = RD_MAILBOX_REG(ha, reg, 0);
-                                       mb2 = RD_MAILBOX_REG(ha, reg, 2);
-
-                                       WRT_REG_WORD(&reg->hccr,
-                                           HCCR_CLR_RISC_INT);
-                                       RD_REG_WORD(&reg->hccr);
-                                       break;
-                               }
+       /* Get RISC SRAM. */
+       if (rval == QLA_SUCCESS)
+               rval = qla2xxx_dump_ram(ha, 0x800, fw->risc_ram,
+                   sizeof(fw->risc_ram) / 2, &nxt);
 
-                               /* clear this intr; it wasn't a mailbox intr */
-                               WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
-                               RD_REG_WORD(&reg->hccr);
-                       }
-                       udelay(5);
-               }
+       /* Get stack SRAM. */
+       if (rval == QLA_SUCCESS)
+               rval = qla2xxx_dump_ram(ha, 0x10000, fw->stack_ram,
+                   sizeof(fw->stack_ram) / 2, &nxt);
 
-               if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
-                       rval = mb0 & MBS_MASK;
-                       fw->data_ram[cnt] = htons(mb2);
-               } else {
-                       rval = QLA_FUNCTION_FAILED;
-               }
-       }
+       /* Get data SRAM. */
+       if (rval == QLA_SUCCESS)
+               rval = qla2xxx_dump_ram(ha, 0x11000, fw->data_ram,
+                   ha->fw_memory_size - 0x11000 + 1, &nxt);
 
        if (rval == QLA_SUCCESS)
-               qla2xxx_copy_queues(ha, &fw->data_ram[cnt]);
+               qla2xxx_copy_queues(ha, nxt);
 
        if (rval != QLA_SUCCESS) {
                qla_printk(KERN_WARNING, ha,
@@ -1010,7 +902,7 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
                goto qla24xx_fw_dump_failed_0;
 
        rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
-           fw->ext_mem, &nxt);
+           &nxt);
        if (rval != QLA_SUCCESS)
                goto qla24xx_fw_dump_failed_0;
 
@@ -1318,7 +1210,7 @@ qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
                goto qla25xx_fw_dump_failed_0;
 
        rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
-           fw->ext_mem, &nxt);
+           &nxt);
        if (rval != QLA_SUCCESS)
                goto qla25xx_fw_dump_failed_0;
 
index 078f2a15f40bcb3814b53b7cb4942db61d08922e..cf194517400d4d8f76f34dd29319a3045124e670 100644 (file)
@@ -1036,22 +1036,6 @@ struct mid_db_entry_24xx {
        uint8_t reserved_1;
 };
 
- /*
- * Virtual Fabric ID type definition.
- */
-typedef struct vf_id {
-        uint16_t id : 12;
-        uint16_t priority : 4;
-} vf_id_t;
-
-/*
- * Virtual Fabric HopCt type definition.
- */
-typedef struct vf_hopct {
-        uint16_t reserved : 8;
-        uint16_t hopct : 8;
-} vf_hopct_t;
-
 /*
  * Virtual Port Control IOCB
  */
@@ -1082,10 +1066,10 @@ struct vp_ctrl_entry_24xx {
 
        uint8_t vp_idx_map[16];
        uint16_t flags;
-       struct vf_id    id;
+       uint16_t id;
        uint16_t reserved_4;
-       struct vf_hopct  hopct;
-       uint8_t reserved_5[8];
+       uint16_t hopct;
+       uint8_t reserved_5[24];
 };
 
 /*
@@ -1132,9 +1116,9 @@ struct vp_config_entry_24xx {
        uint16_t reserved_vp2;
        uint8_t port_name_idx2[WWN_SIZE];
        uint8_t node_name_idx2[WWN_SIZE];
-       struct vf_id    id;
+       uint16_t id;
        uint16_t reserved_4;
-       struct vf_hopct  hopct;
+       uint16_t hopct;
        uint8_t reserved_5;
 };
 
index 76eb4fecce656109bcb0ca5464e8c0150d9496e8..f8827068d30fb006165b2daccfd86f7d69d2f134 100644 (file)
@@ -151,10 +151,6 @@ qla2x00_verify_checksum(scsi_qla_host_t *, uint32_t);
 extern int
 qla2x00_issue_iocb(scsi_qla_host_t *, void *, dma_addr_t, size_t);
 
-extern int
-qla2x00_issue_iocb_timeout(scsi_qla_host_t *, void *, dma_addr_t, size_t,
-    uint32_t);
-
 extern int
 qla2x00_abort_command(scsi_qla_host_t *, srb_t *);
 
index 750d7ef83aaefb54f3f4c79fb468fdb579c8fc1b..4cb80b476c85c69c65277d5de2709f863f13a958 100644 (file)
@@ -1583,8 +1583,8 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
        eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
        eiter->len = __constant_cpu_to_be16(4 + 4);
        max_frame_size = IS_FWI2_CAPABLE(ha) ?
-               (uint32_t) icb24->frame_payload_size:
-               (uint32_t) ha->init_cb->frame_payload_size;
+           le16_to_cpu(icb24->frame_payload_size):
+           le16_to_cpu(ha->init_cb->frame_payload_size);
        eiter->a.max_frame_size = cpu_to_be32(max_frame_size);
        size += 4 + 4;
 
index 01e26087c1dd599036202bb862c608675960d3e6..bbbc5a632a1d22f2334761283bfa1db4254a5ff2 100644 (file)
@@ -3645,7 +3645,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
        if (le16_to_cpu(nv->login_timeout) < 4)
                nv->login_timeout = __constant_cpu_to_le16(4);
        ha->login_timeout = le16_to_cpu(nv->login_timeout);
-       icb->login_timeout = cpu_to_le16(nv->login_timeout);
+       icb->login_timeout = nv->login_timeout;
 
        /* Set minimum RATOV to 100 tenths of a second. */
        ha->r_a_tov = 100;
index 285479b62d8f02084ad0daebc12ab249f16348c0..5d9a64a7879bce722b4bb6b94ffce8d3facb7750 100644 (file)
@@ -409,6 +409,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                }
 
                set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
+               set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
 
                ha->flags.management_server_logged_in = 0;
                qla2x00_post_aen_work(ha, FCH_EVT_LIP, mb[1]);
@@ -454,8 +455,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
 
                ha->flags.management_server_logged_in = 0;
                ha->link_data_rate = PORT_SPEED_UNKNOWN;
-               if (ql2xfdmienable)
-                       set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
                qla2x00_post_aen_work(ha, FCH_EVT_LINKDOWN, 0);
                break;
 
@@ -511,6 +510,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                        set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
                }
                set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
+               set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
 
                ha->flags.gpsc_supported = 1;
                ha->flags.management_server_logged_in = 0;
index 7d0a8a4c77196ea302262dcfc2d61f0d6d8931b2..2100604208096f2b3e04d0cb1001614ffbcb7aa8 100644 (file)
@@ -681,7 +681,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
  * Context:
  *     Kernel context.
  */
-int
+static int
 qla2x00_issue_iocb_timeout(scsi_qla_host_t *ha, void *buffer,
     dma_addr_t phys_addr, size_t size, uint32_t tov)
 {
@@ -784,7 +784,6 @@ qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp)
                DEBUG2_3_11(printk("qla2x00_abort_command(%ld): failed=%x.\n",
                    ha->host_no, rval));
        } else {
-               sp->flags |= SRB_ABORT_PENDING;
                DEBUG11(printk("qla2x00_abort_command(%ld): done.\n",
                    ha->host_no));
        }
@@ -1469,7 +1468,7 @@ qla24xx_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
        lg->port_id[0] = al_pa;
        lg->port_id[1] = area;
        lg->port_id[2] = domain;
-       lg->vp_index = cpu_to_le16(ha->vp_idx);
+       lg->vp_index = ha->vp_idx;
        rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0);
        if (rval != QLA_SUCCESS) {
                DEBUG2_3_11(printk("%s(%ld): failed to issue Login IOCB "
@@ -1724,7 +1723,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
        lg->port_id[0] = al_pa;
        lg->port_id[1] = area;
        lg->port_id[2] = domain;
-       lg->vp_index = cpu_to_le16(ha->vp_idx);
+       lg->vp_index = ha->vp_idx;
        rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0);
        if (rval != QLA_SUCCESS) {
                DEBUG2_3_11(printk("%s(%ld): failed to issue Logout IOCB "
@@ -2210,7 +2209,6 @@ qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp)
                rval = QLA_FUNCTION_FAILED;
        } else {
                DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
-               sp->flags |= SRB_ABORT_PENDING;
        }
 
        dma_pool_free(ha->s_dma_pool, abt, abt_dma);
@@ -2644,12 +2642,11 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *ha,
        struct vp_rpt_id_entry_24xx *rptid_entry)
 {
        uint8_t vp_idx;
+       uint16_t stat = le16_to_cpu(rptid_entry->vp_idx);
        scsi_qla_host_t *vha;
 
        if (rptid_entry->entry_status != 0)
                return;
-       if (rptid_entry->entry_status != __constant_cpu_to_le16(CS_COMPLETE))
-               return;
 
        if (rptid_entry->format == 0) {
                DEBUG15(printk("%s:format 0 : scsi(%ld) number of VPs setup %d,"
@@ -2659,17 +2656,17 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *ha,
                        rptid_entry->port_id[2], rptid_entry->port_id[1],
                        rptid_entry->port_id[0]));
        } else if (rptid_entry->format == 1) {
-               vp_idx = LSB(rptid_entry->vp_idx);
+               vp_idx = LSB(stat);
                DEBUG15(printk("%s:format 1: scsi(%ld): VP[%d] enabled "
                    "- status %d - "
                    "with port id %02x%02x%02x\n",__func__,ha->host_no,
-                   vp_idx, MSB(rptid_entry->vp_idx),
+                   vp_idx, MSB(stat),
                    rptid_entry->port_id[2], rptid_entry->port_id[1],
                    rptid_entry->port_id[0]));
                if (vp_idx == 0)
                        return;
 
-               if (MSB(rptid_entry->vp_idx) == 1)
+               if (MSB(stat) == 1)
                        return;
 
                list_for_each_entry(vha, &ha->vp_list, vp_list)
@@ -2982,8 +2979,8 @@ qla84xx_verify_chip(struct scsi_qla_host *ha, uint16_t *status)
        /* We update the firmware with only one data sequence. */
        options |= VCO_END_OF_DATA;
 
-       retry = 0;
        do {
+               retry = 0;
                memset(mn, 0, sizeof(*mn));
                mn->p.req.entry_type = VERIFY_CHIP_IOCB_TYPE;
                mn->p.req.entry_count = 1;
index 8b33b163b1d427717ccea65b5e20f1822438e632..3223fd16bcfe3a72829662fc47998ec3a0e081f5 100644 (file)
@@ -67,7 +67,7 @@ static void qla2x00_free_device(scsi_qla_host_t *);
 
 static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha);
 
-int ql2xfdmienable;
+int ql2xfdmienable=1;
 module_param(ql2xfdmienable, int, S_IRUGO|S_IRUSR);
 MODULE_PARM_DESC(ql2xfdmienable,
                "Enables FDMI registratons "
@@ -2135,7 +2135,7 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
        kfree(ha->nvram);
 }
 
-struct qla_work_evt *
+static struct qla_work_evt *
 qla2x00_alloc_work(struct scsi_qla_host *ha, enum qla_work_type type,
     int locked)
 {
@@ -2152,7 +2152,7 @@ qla2x00_alloc_work(struct scsi_qla_host *ha, enum qla_work_type type,
        return e;
 }
 
-int
+static int
 qla2x00_post_work(struct scsi_qla_host *ha, struct qla_work_evt *e, int locked)
 {
        unsigned long flags;
@@ -2373,7 +2373,7 @@ qla2x00_do_dpc(void *data)
                                        } else {
                                                fcport->login_retry = 0;
                                        }
-                                       if (fcport->login_retry == 0)
+                                       if (fcport->login_retry == 0 && status != QLA_SUCCESS)
                                                fcport->loop_id = FC_NO_LOOP_ID;
                                }
                                if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))
@@ -2599,6 +2599,10 @@ qla2x00_timer(scsi_qla_host_t *ha)
                start_dpc++;
        }
 
+       /* Process any deferred work. */
+       if (!list_empty(&ha->work_list))
+               start_dpc++;
+
        /* Schedule the DPC routine if needed */
        if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
            test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) ||
index f42f17acf2cf21b7b5d9b62e5c0b18e7f4bc8040..afeae2bfe7eb090f337d114bf2ed52e3e2bff9af 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.02.01-k1"
+#define QLA2XXX_VERSION      "8.02.01-k2"
 
 #define QLA_DRIVER_MAJOR_VER   8
 #define QLA_DRIVER_MINOR_VER   2
index 3f34e9376b0aa148c8dafc58ee0c52c65849b1e1..b33e72516ef83ee685a5186e0894b0585faba4fd 100644 (file)
@@ -121,6 +121,7 @@ extern struct scsi_transport_template blank_transport_template;
 extern void __scsi_remove_device(struct scsi_device *);
 
 extern struct bus_type scsi_bus_type;
+extern struct attribute_group *scsi_sysfs_shost_attr_groups[];
 
 /* scsi_netlink.c */
 #ifdef CONFIG_SCSI_NETLINK
index ed395154a5b189e4043c271da8fc9042178a043d..3a1c99d5c775482efedcf2a550218c23e3cf139d 100644 (file)
@@ -190,10 +190,14 @@ void scsi_proc_host_rm(struct Scsi_Host *shost)
  */
 static int proc_print_scsidevice(struct device *dev, void *data)
 {
-       struct scsi_device *sdev = to_scsi_device(dev);
+       struct scsi_device *sdev;
        struct seq_file *s = data;
        int i;
 
+       if (!scsi_is_sdev_device(dev))
+               goto out;
+
+       sdev = to_scsi_device(dev);
        seq_printf(s,
                "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n  Vendor: ",
                sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
@@ -230,6 +234,7 @@ static int proc_print_scsidevice(struct device *dev, void *data)
        else
                seq_printf(s, "\n");
 
+out:
        return 0;
 }
 
index e67c14e31babba5913f0ab1852f7952e191502bb..fcd7455ffc39acf226233c10c3a45c1ee76537e0 100644 (file)
@@ -322,6 +322,21 @@ out:
        return NULL;
 }
 
+static void scsi_target_destroy(struct scsi_target *starget)
+{
+       struct device *dev = &starget->dev;
+       struct Scsi_Host *shost = dev_to_shost(dev->parent);
+       unsigned long flags;
+
+       transport_destroy_device(dev);
+       spin_lock_irqsave(shost->host_lock, flags);
+       if (shost->hostt->target_destroy)
+               shost->hostt->target_destroy(starget);
+       list_del_init(&starget->siblings);
+       spin_unlock_irqrestore(shost->host_lock, flags);
+       put_device(dev);
+}
+
 static void scsi_target_dev_release(struct device *dev)
 {
        struct device *parent = dev->parent;
@@ -331,9 +346,14 @@ static void scsi_target_dev_release(struct device *dev)
        put_device(parent);
 }
 
+struct device_type scsi_target_type = {
+       .name =         "scsi_target",
+       .release =      scsi_target_dev_release,
+};
+
 int scsi_is_target_device(const struct device *dev)
 {
-       return dev->release == scsi_target_dev_release;
+       return dev->type == &scsi_target_type;
 }
 EXPORT_SYMBOL(scsi_is_target_device);
 
@@ -391,14 +411,17 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
        device_initialize(dev);
        starget->reap_ref = 1;
        dev->parent = get_device(parent);
-       dev->release = scsi_target_dev_release;
        sprintf(dev->bus_id, "target%d:%d:%d",
                shost->host_no, channel, id);
+#ifndef CONFIG_SYSFS_DEPRECATED
+       dev->bus = &scsi_bus_type;
+#endif
+       dev->type = &scsi_target_type;
        starget->id = id;
        starget->channel = channel;
        INIT_LIST_HEAD(&starget->siblings);
        INIT_LIST_HEAD(&starget->devices);
-       starget->state = STARGET_RUNNING;
+       starget->state = STARGET_CREATED;
        starget->scsi_level = SCSI_2;
  retry:
        spin_lock_irqsave(shost->host_lock, flags);
@@ -411,18 +434,6 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
        spin_unlock_irqrestore(shost->host_lock, flags);
        /* allocate and add */
        transport_setup_device(dev);
-       error = device_add(dev);
-       if (error) {
-               dev_err(dev, "target device_add failed, error %d\n", error);
-               spin_lock_irqsave(shost->host_lock, flags);
-               list_del_init(&starget->siblings);
-               spin_unlock_irqrestore(shost->host_lock, flags);
-               transport_destroy_device(dev);
-               put_device(parent);
-               kfree(starget);
-               return NULL;
-       }
-       transport_add_device(dev);
        if (shost->hostt->target_alloc) {
                error = shost->hostt->target_alloc(starget);
 
@@ -430,9 +441,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
                        dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error);
                        /* don't want scsi_target_reap to do the final
                         * put because it will be under the host lock */
-                       get_device(dev);
-                       scsi_target_reap(starget);
-                       put_device(dev);
+                       scsi_target_destroy(starget);
                        return NULL;
                }
        }
@@ -459,18 +468,10 @@ static void scsi_target_reap_usercontext(struct work_struct *work)
 {
        struct scsi_target *starget =
                container_of(work, struct scsi_target, ew.work);
-       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-       unsigned long flags;
 
        transport_remove_device(&starget->dev);
        device_del(&starget->dev);
-       transport_destroy_device(&starget->dev);
-       spin_lock_irqsave(shost->host_lock, flags);
-       if (shost->hostt->target_destroy)
-               shost->hostt->target_destroy(starget);
-       list_del_init(&starget->siblings);
-       spin_unlock_irqrestore(shost->host_lock, flags);
-       put_device(&starget->dev);
+       scsi_target_destroy(starget);
 }
 
 /**
@@ -485,21 +486,25 @@ void scsi_target_reap(struct scsi_target *starget)
 {
        struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
        unsigned long flags;
+       enum scsi_target_state state;
+       int empty;
 
        spin_lock_irqsave(shost->host_lock, flags);
+       state = starget->state;
+       empty = --starget->reap_ref == 0 &&
+               list_empty(&starget->devices) ? 1 : 0;
+       spin_unlock_irqrestore(shost->host_lock, flags);
 
-       if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
-               BUG_ON(starget->state == STARGET_DEL);
-               starget->state = STARGET_DEL;
-               spin_unlock_irqrestore(shost->host_lock, flags);
-               execute_in_process_context(scsi_target_reap_usercontext,
-                                          &starget->ew);
+       if (!empty)
                return;
 
-       }
-       spin_unlock_irqrestore(shost->host_lock, flags);
-
-       return;
+       BUG_ON(state == STARGET_DEL);
+       starget->state = STARGET_DEL;
+       if (state == STARGET_CREATED)
+               scsi_target_destroy(starget);
+       else
+               execute_in_process_context(scsi_target_reap_usercontext,
+                                          &starget->ew);
 }
 
 /**
@@ -1048,8 +1053,9 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
                                        scsi_inq_str(vend, result, 8, 16),
                                        scsi_inq_str(mod, result, 16, 32));
                        });
+
                }
-               
+
                res = SCSI_SCAN_TARGET_PRESENT;
                goto out_free_result;
        }
@@ -1489,7 +1495,6 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
        if (scsi_host_scan_allowed(shost))
                scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
        mutex_unlock(&shost->scan_mutex);
-       transport_configure_device(&starget->dev);
        scsi_target_reap(starget);
        put_device(&starget->dev);
 
@@ -1570,7 +1575,6 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel,
  out_reap:
        /* now determine if the target has any children at all
         * and if not, nuke it */
-       transport_configure_device(&starget->dev);
        scsi_target_reap(starget);
 
        put_device(&starget->dev);
index 67bb20ed45d23ef431280a2c63a03e14ea252731..049103f1d16ffd320ca51a5544aca1966dc71585 100644 (file)
@@ -21,6 +21,8 @@
 #include "scsi_priv.h"
 #include "scsi_logging.h"
 
+static struct device_type scsi_dev_type;
+
 static const struct {
        enum scsi_device_state  value;
        char                    *name;
@@ -249,18 +251,27 @@ shost_rd_attr(sg_tablesize, "%hu\n");
 shost_rd_attr(unchecked_isa_dma, "%d\n");
 shost_rd_attr2(proc_name, hostt->proc_name, "%s\n");
 
-static struct device_attribute *scsi_sysfs_shost_attrs[] = {
-       &dev_attr_unique_id,
-       &dev_attr_host_busy,
-       &dev_attr_cmd_per_lun,
-       &dev_attr_can_queue,
-       &dev_attr_sg_tablesize,
-       &dev_attr_unchecked_isa_dma,
-       &dev_attr_proc_name,
-       &dev_attr_scan,
-       &dev_attr_hstate,
-       &dev_attr_supported_mode,
-       &dev_attr_active_mode,
+static struct attribute *scsi_sysfs_shost_attrs[] = {
+       &dev_attr_unique_id.attr,
+       &dev_attr_host_busy.attr,
+       &dev_attr_cmd_per_lun.attr,
+       &dev_attr_can_queue.attr,
+       &dev_attr_sg_tablesize.attr,
+       &dev_attr_unchecked_isa_dma.attr,
+       &dev_attr_proc_name.attr,
+       &dev_attr_scan.attr,
+       &dev_attr_hstate.attr,
+       &dev_attr_supported_mode.attr,
+       &dev_attr_active_mode.attr,
+       NULL
+};
+
+struct attribute_group scsi_shost_attr_group = {
+       .attrs =        scsi_sysfs_shost_attrs,
+};
+
+struct attribute_group *scsi_sysfs_shost_attr_groups[] = {
+       &scsi_shost_attr_group,
        NULL
 };
 
@@ -335,7 +346,12 @@ static struct class sdev_class = {
 /* all probing is done in the individual ->probe routines */
 static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
 {
-       struct scsi_device *sdp = to_scsi_device(dev);
+       struct scsi_device *sdp;
+
+       if (dev->type != &scsi_dev_type)
+               return 0;
+
+       sdp = to_scsi_device(dev);
        if (sdp->no_uld_attach)
                return 0;
        return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
@@ -351,10 +367,16 @@ static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
 
 static int scsi_bus_suspend(struct device * dev, pm_message_t state)
 {
-       struct device_driver *drv = dev->driver;
-       struct scsi_device *sdev = to_scsi_device(dev);
+       struct device_driver *drv;
+       struct scsi_device *sdev;
        int err;
 
+       if (dev->type != &scsi_dev_type)
+               return 0;
+
+       drv = dev->driver;
+       sdev = to_scsi_device(dev);
+
        err = scsi_device_quiesce(sdev);
        if (err)
                return err;
@@ -370,10 +392,16 @@ static int scsi_bus_suspend(struct device * dev, pm_message_t state)
 
 static int scsi_bus_resume(struct device * dev)
 {
-       struct device_driver *drv = dev->driver;
-       struct scsi_device *sdev = to_scsi_device(dev);
+       struct device_driver *drv;
+       struct scsi_device *sdev;
        int err = 0;
 
+       if (dev->type != &scsi_dev_type)
+               return 0;
+
+       drv = dev->driver;
+       sdev = to_scsi_device(dev);
+
        if (drv && drv->resume)
                err = drv->resume(dev);
 
@@ -781,6 +809,27 @@ sdev_store_queue_type_rw(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
+static int scsi_target_add(struct scsi_target *starget)
+{
+       int error;
+
+       if (starget->state != STARGET_CREATED)
+               return 0;
+
+       error = device_add(&starget->dev);
+       if (error) {
+               dev_err(&starget->dev, "target device_add failed, error %d\n", error);
+               get_device(&starget->dev);
+               scsi_target_reap(starget);
+               put_device(&starget->dev);
+               return error;
+       }
+       transport_add_device(&starget->dev);
+       starget->state = STARGET_RUNNING;
+
+       return 0;
+}
+
 static struct device_attribute sdev_attr_queue_type_rw =
        __ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field,
               sdev_store_queue_type_rw);
@@ -796,10 +845,16 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
 {
        int error, i;
        struct request_queue *rq = sdev->request_queue;
+       struct scsi_target *starget = sdev->sdev_target;
 
        if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0)
                return error;
 
+       error = scsi_target_add(starget);
+       if (error)
+               return error;
+
+       transport_configure_device(&starget->dev);
        error = device_add(&sdev->sdev_gendev);
        if (error) {
                put_device(sdev->sdev_gendev.parent);
@@ -834,7 +889,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
                goto out;
        }
 
-       error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL);
+       error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL, NULL);
 
        if (error)
                sdev_printk(KERN_INFO, sdev,
@@ -971,44 +1026,6 @@ int scsi_register_interface(struct class_interface *intf)
 }
 EXPORT_SYMBOL(scsi_register_interface);
 
-
-static struct device_attribute *class_attr_overridden(
-               struct device_attribute **attrs,
-               struct device_attribute *attr)
-{
-       int i;
-
-       if (!attrs)
-               return NULL;
-       for (i = 0; attrs[i]; i++)
-               if (!strcmp(attrs[i]->attr.name, attr->attr.name))
-                       return attrs[i];
-       return NULL;
-}
-
-static int class_attr_add(struct device *classdev,
-               struct device_attribute *attr)
-{
-       struct device_attribute *base_attr;
-
-       /*
-        * Spare the caller from having to copy things it's not interested in.
-        */
-       base_attr = class_attr_overridden(scsi_sysfs_shost_attrs, attr);
-       if (base_attr) {
-               /* extend permissions */
-               attr->attr.mode |= base_attr->attr.mode;
-
-               /* override null show/store with default */
-               if (!attr->show)
-                       attr->show = base_attr->show;
-               if (!attr->store)
-                       attr->store = base_attr->store;
-       }
-
-       return device_create_file(classdev, attr);
-}
-
 /**
  * scsi_sysfs_add_host - add scsi host to subsystem
  * @shost:     scsi host struct to add to subsystem
@@ -1018,20 +1035,11 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost)
 {
        int error, i;
 
+       /* add host specific attributes */
        if (shost->hostt->shost_attrs) {
                for (i = 0; shost->hostt->shost_attrs[i]; i++) {
-                       error = class_attr_add(&shost->shost_dev,
-                                       shost->hostt->shost_attrs[i]);
-                       if (error)
-                               return error;
-               }
-       }
-
-       for (i = 0; scsi_sysfs_shost_attrs[i]; i++) {
-               if (!class_attr_overridden(shost->hostt->shost_attrs,
-                                       scsi_sysfs_shost_attrs[i])) {
                        error = device_create_file(&shost->shost_dev,
-                                       scsi_sysfs_shost_attrs[i]);
+                                       shost->hostt->shost_attrs[i]);
                        if (error)
                                return error;
                }
index 6b092a6c295d52d0b63b7d5659b880c63c07ed7a..5fd64e70029dcd30d4c30c8c9dffd5a0f77648a6 100644 (file)
@@ -1961,12 +1961,17 @@ fc_timed_out(struct scsi_cmnd *scmd)
 }
 
 /*
- * Must be called with shost->host_lock held
+ * Called by fc_user_scan to locate an rport on the shost that
+ * matches the channel and target id, and invoke scsi_scan_target()
+ * on the rport.
  */
-static int fc_user_scan(struct Scsi_Host *shost, uint channel,
-               uint id, uint lun)
+static void
+fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, uint lun)
 {
        struct fc_rport *rport;
+       unsigned long flags;
+
+       spin_lock_irqsave(shost->host_lock, flags);
 
        list_for_each_entry(rport, &fc_host_rports(shost), peers) {
                if (rport->scsi_target_id == -1)
@@ -1975,13 +1980,54 @@ static int fc_user_scan(struct Scsi_Host *shost, uint channel,
                if (rport->port_state != FC_PORTSTATE_ONLINE)
                        continue;
 
-               if ((channel == SCAN_WILD_CARD || channel == rport->channel) &&
-                   (id == SCAN_WILD_CARD || id == rport->scsi_target_id)) {
-                       scsi_scan_target(&rport->dev, rport->channel,
-                                        rport->scsi_target_id, lun, 1);
+               if ((channel == rport->channel) &&
+                   (id == rport->scsi_target_id)) {
+                       spin_unlock_irqrestore(shost->host_lock, flags);
+                       scsi_scan_target(&rport->dev, channel, id, lun, 1);
+                       return;
                }
        }
 
+       spin_unlock_irqrestore(shost->host_lock, flags);
+}
+
+/*
+ * Called via sysfs scan routines. Necessary, as the FC transport
+ * wants to place all target objects below the rport object. So this
+ * routine must invoke the scsi_scan_target() routine with the rport
+ * object as the parent.
+ */
+static int
+fc_user_scan(struct Scsi_Host *shost, uint channel, uint id, uint lun)
+{
+       uint chlo, chhi;
+       uint tgtlo, tgthi;
+
+       if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||
+           ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) ||
+           ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
+               return -EINVAL;
+
+       if (channel == SCAN_WILD_CARD) {
+               chlo = 0;
+               chhi = shost->max_channel + 1;
+       } else {
+               chlo = channel;
+               chhi = channel + 1;
+       }
+
+       if (id == SCAN_WILD_CARD) {
+               tgtlo = 0;
+               tgthi = shost->max_id;
+       } else {
+               tgtlo = id;
+               tgthi = id + 1;
+       }
+
+       for ( ; chlo < chhi; chlo++)
+               for ( ; tgtlo < tgthi; tgtlo++)
+                       fc_user_scan_tgt(shost, chlo, tgtlo, lun);
+
        return 0;
 }
 
index 27ec625ab7719a2cdf59931ed1ecb6ce77431de5..7899e3dda9bfd7ccf357f98ed299c77af8b18013 100644 (file)
@@ -192,6 +192,16 @@ static void sas_non_host_smp_request(struct request_queue *q)
        sas_smp_request(q, rphy_to_shost(rphy), rphy);
 }
 
+static void sas_host_release(struct device *dev)
+{
+       struct Scsi_Host *shost = dev_to_shost(dev);
+       struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+       struct request_queue *q = sas_host->q;
+
+       if (q)
+               blk_cleanup_queue(q);
+}
+
 static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
 {
        struct request_queue *q;
@@ -199,6 +209,7 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
        struct device *dev;
        char namebuf[BUS_ID_SIZE];
        const char *name;
+       void (*release)(struct device *);
 
        if (!to_sas_internal(shost->transportt)->f->smp_handler) {
                printk("%s can't handle SMP requests\n", shost->hostt->name);
@@ -209,17 +220,19 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
                q = blk_init_queue(sas_non_host_smp_request, NULL);
                dev = &rphy->dev;
                name = dev->bus_id;
+               release = NULL;
        } else {
                q = blk_init_queue(sas_host_smp_request, NULL);
                dev = &shost->shost_gendev;
                snprintf(namebuf, sizeof(namebuf),
                         "sas_host%d", shost->host_no);
                name = namebuf;
+               release = sas_host_release;
        }
        if (!q)
                return -ENOMEM;
 
-       error = bsg_register_queue(q, dev, name);
+       error = bsg_register_queue(q, dev, name, release);
        if (error) {
                blk_cleanup_queue(q);
                return -ENOMEM;
@@ -253,7 +266,6 @@ static void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy)
                return;
 
        bsg_unregister_queue(q);
-       blk_cleanup_queue(q);
 }
 
 /*
@@ -1301,6 +1313,9 @@ static void sas_expander_release(struct device *dev)
        struct sas_rphy *rphy = dev_to_rphy(dev);
        struct sas_expander_device *edev = rphy_to_expander_device(rphy);
 
+       if (rphy->q)
+               blk_cleanup_queue(rphy->q);
+
        put_device(dev->parent);
        kfree(edev);
 }
@@ -1310,6 +1325,9 @@ static void sas_end_device_release(struct device *dev)
        struct sas_rphy *rphy = dev_to_rphy(dev);
        struct sas_end_device *edev = rphy_to_end_device(rphy);
 
+       if (rphy->q)
+               blk_cleanup_queue(rphy->q);
+
        put_device(dev->parent);
        kfree(edev);
 }
index bc12b5d5d676df7ab733fd23ea0ef8e929241363..75a64a6cae8ca873d70b259e61384b4763eed6ef 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/workqueue.h>
 #include <linux/blkdev.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 #include <scsi/scsi.h>
 #include "scsi_priv.h"
 #include <scsi/scsi_device.h>
@@ -1374,11 +1375,11 @@ static int spi_host_configure(struct transport_container *tc,
  * overloads the return by setting 1<<1 if the attribute should
  * be writeable */
 #define TARGET_ATTRIBUTE_HELPER(name) \
-       (si->f->show_##name ? 1 : 0) + \
-       (si->f->set_##name ? 2 : 0)
+       (si->f->show_##name ? S_IRUGO : 0) | \
+       (si->f->set_##name ? S_IWUSR : 0)
 
-static int target_attribute_is_visible(struct kobject *kobj,
-                                      struct attribute *attr, int i)
+static mode_t target_attribute_is_visible(struct kobject *kobj,
+                                         struct attribute *attr, int i)
 {
        struct device *cdev = container_of(kobj, struct device, kobj);
        struct scsi_target *starget = transport_class_to_starget(cdev);
@@ -1428,7 +1429,7 @@ static int target_attribute_is_visible(struct kobject *kobj,
                 spi_support_ius(starget))
                return TARGET_ATTRIBUTE_HELPER(hold_mcs);
        else if (attr == &dev_attr_revalidate.attr)
-               return 1;
+               return S_IWUSR;
 
        return 0;
 }
@@ -1462,25 +1463,9 @@ static int spi_target_configure(struct transport_container *tc,
                                struct device *cdev)
 {
        struct kobject *kobj = &cdev->kobj;
-       int i;
-       struct attribute *attr;
-       int rc;
-
-       for (i = 0; (attr = target_attributes[i]) != NULL; i++) {
-               int j = target_attribute_group.is_visible(kobj, attr, i);
-
-               /* FIXME: as well as returning -EEXIST, which we'd like
-                * to ignore, sysfs also does a WARN_ON and dumps a trace,
-                * which is bad, so temporarily, skip attributes that are
-                * already visible (the revalidate one) */
-               if (j && attr != &dev_attr_revalidate.attr)
-                       rc = sysfs_add_file_to_group(kobj, attr,
-                                               target_attribute_group.name);
-               /* and make the attribute writeable if we have a set
-                * function */
-               if ((j & 1))
-                       rc = sysfs_chmod_file(kobj, attr, attr->mode | S_IWUSR);
-       }
+
+       /* force an update based on parameters read from the device */
+       sysfs_update_group(kobj, &target_attribute_group);
 
        return 0;
 }
index 03e359670506cf1403463616a1c410d72a709fab..31fe6051c799869f76713ffa674d4d795baf73dc 100644 (file)
@@ -313,7 +313,8 @@ static struct platform_driver sgiwd93_driver = {
        .probe  = sgiwd93_probe,
        .remove = __devexit_p(sgiwd93_remove),
        .driver = {
-               .name   = "sgiwd93"
+               .name   = "sgiwd93",
+               .owner  = THIS_MODULE,
        }
 };
 
@@ -333,3 +334,4 @@ module_exit(sgiwd93_module_exit);
 MODULE_DESCRIPTION("SGI WD33C93 driver");
 MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:sgiwd93");
index 0a6b45b1b003a7a0d64a2dd896355bfb15b9e8a0..2bbef4c45a0d64404c11dfc1ae1fbc0b071d0c21 100644 (file)
@@ -53,6 +53,7 @@
 MODULE_AUTHOR("Thomas Bogendörfer");
 MODULE_DESCRIPTION("SNI RM 53c710 SCSI Driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:snirm_53c710");
 
 #define SNIRM710_CLOCK 32
 
@@ -136,6 +137,7 @@ static struct platform_driver snirm710_driver = {
        .remove = __devexit_p(snirm710_driver_remove),
        .driver = {
                .name   = "snirm_53c710",
+               .owner  = THIS_MODULE,
        },
 };
 
index a860c3a9ae9902b1b935802400f29c1b53903b5c..e8db66ad0bde787448f32c44980eb89328ddb212 100644 (file)
@@ -4322,7 +4322,7 @@ static void do_remove_sysfs_files(void)
 static ssize_t
 st_defined_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
+       struct st_modedef *STm = dev_get_drvdata(dev);
        ssize_t l = 0;
 
        l = snprintf(buf, PAGE_SIZE, "%d\n", STm->defined);
@@ -4334,7 +4334,7 @@ DEVICE_ATTR(defined, S_IRUGO, st_defined_show, NULL);
 static ssize_t
 st_defblk_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
+       struct st_modedef *STm = dev_get_drvdata(dev);
        ssize_t l = 0;
 
        l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_blksize);
@@ -4346,7 +4346,7 @@ DEVICE_ATTR(default_blksize, S_IRUGO, st_defblk_show, NULL);
 static ssize_t
 st_defdensity_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
+       struct st_modedef *STm = dev_get_drvdata(dev);
        ssize_t l = 0;
        char *fmt;
 
@@ -4361,7 +4361,7 @@ static ssize_t
 st_defcompression_show(struct device *dev, struct device_attribute *attr,
                       char *buf)
 {
-       struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
+       struct st_modedef *STm = dev_get_drvdata(dev);
        ssize_t l = 0;
 
        l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_compression - 1);
@@ -4373,7 +4373,7 @@ DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL);
 static ssize_t
 st_options_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
+       struct st_modedef *STm = dev_get_drvdata(dev);
        struct scsi_tape *STp;
        int i, j, options;
        ssize_t l = 0;
index 06152c7fa689bfd21e6dbd7df465ea060a0dcd85..7514b3a0390e5b19b75689a4493047a7ef3d67be 100644 (file)
@@ -294,6 +294,7 @@ static struct platform_driver esp_sun3x_driver = {
        .remove         = __devexit_p(esp_sun3x_remove),
        .driver = {
                .name   = "sun3x_esp",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -314,3 +315,4 @@ MODULE_VERSION(DRV_VERSION);
 
 module_init(sun3x_esp_init);
 module_exit(sun3x_esp_exit);
+MODULE_ALIAS("platform:sun3x_esp");
index 58d7eee4fe81133779d066b9a02f119273b027d8..640333b1e75c9b32565bfeab8721ef566fb903c4 100644 (file)
@@ -1715,13 +1715,12 @@ static void flush_dev(struct scsi_device *dev, unsigned long cursec, unsigned in
 
 }
 
-static irqreturn_t ihdlr(int irq, unsigned int j) {
+static irqreturn_t ihdlr(unsigned int j)
+{
    struct scsi_cmnd *SCpnt;
    unsigned int i, k, c, status, tstatus, reg, ret;
    struct mscp *spp, *cpp;
-
-   if (sh[j]->irq != irq)
-       panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq);
+   int irq = sh[j]->irq;
 
    /* Check if this board need to be serviced */
    if (!((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED)) goto none;
@@ -1935,7 +1934,7 @@ static irqreturn_t do_interrupt_handler(int irq, void *shap) {
    if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return IRQ_NONE;
 
    spin_lock_irqsave(sh[j]->host_lock, spin_flags);
-   ret = ihdlr(irq, j);
+   ret = ihdlr(j);
    spin_unlock_irqrestore(sh[j]->host_lock, spin_flags);
    return ret;
 }
index 8aacfb78deabe03e08ca8d8b4df0e6235eff35ee..25029c7570b65428c4b29f9e2f26c97fff5bc41b 100644 (file)
@@ -31,7 +31,8 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev,
        struct resource resource;
        struct device_node *np = ofdev->node;
        const unsigned int *clk, *spd;
-       int ret;
+       const u32 *prop;
+       int ret, prop_size;
 
        memset(port, 0, sizeof *port);
        spd = of_get_property(np, "current-speed", NULL);
@@ -49,6 +50,17 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev,
 
        spin_lock_init(&port->lock);
        port->mapbase = resource.start;
+
+       /* Check for shifted address mapping */
+       prop = of_get_property(np, "reg-offset", &prop_size);
+       if (prop && (prop_size == sizeof(u32)))
+               port->mapbase += *prop;
+
+       /* Check for registers offset within the devices address range */
+       prop = of_get_property(np, "reg-shift", &prop_size);
+       if (prop && (prop_size == sizeof(u32)))
+               port->regshift = *prop;
+
        port->irq = irq_of_parse_and_map(np, 0);
        port->iotype = UPIO_MEM;
        port->type = type;
index 4ffa2585429a4965d979b67cea2ba870357baef5..da5a02cb4f636605e5a9a2d30f9555a4f66093ed 100644 (file)
@@ -1022,6 +1022,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
        struct uart_port *port = &ourport->port;
        struct s3c2410_uartcfg *cfg;
        struct resource *res;
+       int ret;
 
        dbg("s3c24xx_serial_init_port: port=%p, platdev=%p\n", port, platdev);
 
@@ -1064,9 +1065,11 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
 
        port->mapbase   = res->start;
        port->membase   = S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART);
-       port->irq       = platform_get_irq(platdev, 0);
-       if (port->irq < 0)
+       ret = platform_get_irq(platdev, 0);
+       if (ret < 0)
                port->irq = 0;
+       else
+               port->irq = ret;
 
        ourport->clk    = clk_get(&platdev->dev, "uart");
 
index a51eeedc18d4860f83814948e0c5150c6d9aab26..d470c72b737e5295f875ff1433cdfce8c7f5111f 100644 (file)
@@ -444,7 +444,7 @@ CXACRU_ALL_FILES(INIT);
 /* the following three functions are stolen from drivers/usb/core/message.c */
 static void cxacru_blocking_completion(struct urb *urb)
 {
-       complete((struct completion *)urb->context);
+       complete(urb->context);
 }
 
 static void cxacru_timeout_kill(unsigned long data)
index c5ec1a55eee3e9956806a1b48222fc67dc6e76f4..abb7d7410e63c7588898300c362307341ba9c116 100644 (file)
@@ -83,7 +83,7 @@
                if (debug >= 1) \
                        dev_dbg(&(usb_dev)->dev, \
                                "[ueagle-atm dbg] %s: " format, \
-                                       __FUNCTION__, ##args); \
+                                       __func__, ##args); \
        } while (0)
 
 #define uea_vdbg(usb_dev, format, args...)     \
        } while (0)
 
 #define uea_enters(usb_dev) \
-       uea_vdbg(usb_dev, "entering %s\n", __FUNCTION__)
+       uea_vdbg(usb_dev, "entering %s\n", __func__)
 
 #define uea_leaves(usb_dev) \
-       uea_vdbg(usb_dev, "leaving  %s\n", __FUNCTION__)
+       uea_vdbg(usb_dev, "leaving  %s\n", __func__)
 
 #define uea_err(usb_dev, format,args...) \
        dev_err(&(usb_dev)->dev ,"[UEAGLE-ATM] " format , ##args)
index e717f5b1caeeedeadbf51634726356311faa4c95..07228721cafebda10100d3a1631d16473a8a6760 100644 (file)
@@ -80,6 +80,7 @@
 #include <linux/stat.h>
 #include <linux/timer.h>
 #include <linux/wait.h>
+#include <linux/kthread.h>
 
 #ifdef VERBOSE_DEBUG
 static int usbatm_print_packet(const unsigned char *data, int len);
@@ -1014,10 +1015,7 @@ static int usbatm_do_heavy_init(void *arg)
        struct usbatm_data *instance = arg;
        int ret;
 
-       daemonize(instance->driver->driver_name);
        allow_signal(SIGTERM);
-       instance->thread_pid = current->pid;
-
        complete(&instance->thread_started);
 
        ret = instance->driver->heavy_init(instance, instance->usb_intf);
@@ -1026,7 +1024,7 @@ static int usbatm_do_heavy_init(void *arg)
                ret = usbatm_atm_init(instance);
 
        mutex_lock(&instance->serialize);
-       instance->thread_pid = -1;
+       instance->thread = NULL;
        mutex_unlock(&instance->serialize);
 
        complete_and_exit(&instance->thread_exited, ret);
@@ -1034,13 +1032,18 @@ static int usbatm_do_heavy_init(void *arg)
 
 static int usbatm_heavy_init(struct usbatm_data *instance)
 {
-       int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_FS | CLONE_FILES);
-
-       if (ret < 0) {
-               usb_err(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret);
-               return ret;
+       struct task_struct *t;
+
+       t = kthread_create(usbatm_do_heavy_init, instance,
+                       instance->driver->driver_name);
+       if (IS_ERR(t)) {
+               usb_err(instance, "%s: failed to create kernel_thread (%ld)!\n",
+                               __func__, PTR_ERR(t));
+               return PTR_ERR(t);
        }
 
+       instance->thread = t;
+       wake_up_process(t);
        wait_for_completion(&instance->thread_started);
 
        return 0;
@@ -1124,7 +1127,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
        kref_init(&instance->refcount);         /* dropped in usbatm_usb_disconnect */
        mutex_init(&instance->serialize);
 
-       instance->thread_pid = -1;
+       instance->thread = NULL;
        init_completion(&instance->thread_started);
        init_completion(&instance->thread_exited);
 
@@ -1287,8 +1290,8 @@ void usbatm_usb_disconnect(struct usb_interface *intf)
 
        mutex_lock(&instance->serialize);
        instance->disconnected = 1;
-       if (instance->thread_pid >= 0)
-               kill_proc(instance->thread_pid, SIGTERM, 1);
+       if (instance->thread != NULL)
+               send_sig(SIGTERM, instance->thread, 1);
        mutex_unlock(&instance->serialize);
 
        wait_for_completion(&instance->thread_exited);
index fc6c2be5999c04574e506db1b01f80b07857db6f..e6887c6cf3cf5a26b7401ca4b7477b001df18b01 100644 (file)
@@ -175,7 +175,7 @@ struct usbatm_data {
        int disconnected;
 
        /* heavy init */
-       int thread_pid;
+       struct task_struct *thread;
        struct completion thread_started;
        struct completion thread_exited;
 
index 0147ea39340e25d38107507e31e615428f7841e4..7b572e75e73cac3046e2662d86f6521f4885db2a 100644 (file)
@@ -31,6 +31,7 @@
  *     v0.23 - use softirq for rx processing, as needed by tty layer
  *     v0.24 - change probe method to evaluate CDC union descriptor
  *     v0.25 - downstream tasks paralelized to maximize throughput
+ *     v0.26 - multiple write urbs, writesize increased
  */
 
 /*
@@ -72,7 +73,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.25"
+#define DRIVER_VERSION "v0.26"
 #define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek"
 #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
 
@@ -118,7 +119,7 @@ static int acm_wb_alloc(struct acm *acm)
        int i, wbn;
        struct acm_wb *wb;
 
-       wbn = acm->write_current;
+       wbn = 0;
        i = 0;
        for (;;) {
                wb = &acm->wb[wbn];
@@ -132,11 +133,6 @@ static int acm_wb_alloc(struct acm *acm)
        }
 }
 
-static void acm_wb_free(struct acm *acm, int wbn)
-{
-       acm->wb[wbn].use = 0;
-}
-
 static int acm_wb_is_avail(struct acm *acm)
 {
        int i, n;
@@ -156,26 +152,22 @@ static inline int acm_wb_is_used(struct acm *acm, int wbn)
 /*
  * Finish write.
  */
-static void acm_write_done(struct acm *acm)
+static void acm_write_done(struct acm *acm, struct acm_wb *wb)
 {
        unsigned long flags;
-       int wbn;
 
        spin_lock_irqsave(&acm->write_lock, flags);
        acm->write_ready = 1;
-       wbn = acm->write_current;
-       acm_wb_free(acm, wbn);
-       acm->write_current = (wbn + 1) % ACM_NW;
+       wb->use = 0;
        spin_unlock_irqrestore(&acm->write_lock, flags);
 }
 
 /*
  * Poke write.
  */
-static int acm_write_start(struct acm *acm)
+static int acm_write_start(struct acm *acm, int wbn)
 {
        unsigned long flags;
-       int wbn;
        struct acm_wb *wb;
        int rc;
 
@@ -190,24 +182,24 @@ static int acm_write_start(struct acm *acm)
                return 0;       /* A white lie */
        }
 
-       wbn = acm->write_current;
        if (!acm_wb_is_used(acm, wbn)) {
                spin_unlock_irqrestore(&acm->write_lock, flags);
                return 0;
        }
        wb = &acm->wb[wbn];
 
-       acm->write_ready = 0;
+       if(acm_wb_is_avail(acm) <= 1)
+               acm->write_ready = 0;
        spin_unlock_irqrestore(&acm->write_lock, flags);
 
-       acm->writeurb->transfer_buffer = wb->buf;
-       acm->writeurb->transfer_dma = wb->dmah;
-       acm->writeurb->transfer_buffer_length = wb->len;
-       acm->writeurb->dev = acm->dev;
+       wb->urb->transfer_buffer = wb->buf;
+       wb->urb->transfer_dma = wb->dmah;
+       wb->urb->transfer_buffer_length = wb->len;
+       wb->urb->dev = acm->dev;
 
-       if ((rc = usb_submit_urb(acm->writeurb, GFP_ATOMIC)) < 0) {
+       if ((rc = usb_submit_urb(wb->urb, GFP_ATOMIC)) < 0) {
                dbg("usb_submit_urb(write bulk) failed: %d", rc);
-               acm_write_done(acm);
+               acm_write_done(acm, wb);
        }
        return rc;
 }
@@ -268,10 +260,10 @@ static void acm_ctrl_irq(struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, status);
+               dbg("%s - urb shutting down with status: %d", __func__, status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, status);
+               dbg("%s - nonzero urb status received: %d", __func__, status);
                goto exit;
        }
 
@@ -315,7 +307,7 @@ exit:
        retval = usb_submit_urb (urb, GFP_ATOMIC);
        if (retval)
                err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, retval);
+                    __func__, retval);
 }
 
 /* data interface returns incoming bytes, or we got unthrottled */
@@ -450,12 +442,13 @@ urbs:
 /* data interface wrote those outgoing bytes */
 static void acm_write_bulk(struct urb *urb)
 {
-       struct acm *acm = (struct acm *)urb->context;
+       struct acm *acm;
+       struct acm_wb *wb = urb->context;
 
        dbg("Entering acm_write_bulk with status %d", urb->status);
 
-       acm_write_done(acm);
-       acm_write_start(acm);
+       acm = wb->instance;
+       acm_write_done(acm, wb);
        if (ACM_READY(acm))
                schedule_work(&acm->work);
 }
@@ -489,6 +482,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
        else
                rv = 0;
 
+       set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);
        tty->driver_data = acm;
        acm->tty = tty;
 
@@ -556,7 +550,8 @@ static void acm_tty_unregister(struct acm *acm)
        usb_put_intf(acm->control);
        acm_table[acm->minor] = NULL;
        usb_free_urb(acm->ctrlurb);
-       usb_free_urb(acm->writeurb);
+       for (i = 0; i < ACM_NW; i++)
+               usb_free_urb(acm->wb[i].urb);
        for (i = 0; i < nr; i++)
                usb_free_urb(acm->ru[i].urb);
        kfree(acm->country_codes);
@@ -577,7 +572,8 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
                if (acm->dev) {
                        acm_set_control(acm, acm->ctrlout = 0);
                        usb_kill_urb(acm->ctrlurb);
-                       usb_kill_urb(acm->writeurb);
+                       for (i = 0; i < ACM_NW; i++)
+                               usb_kill_urb(acm->wb[i].urb);
                        for (i = 0; i < nr; i++)
                                usb_kill_urb(acm->ru[i].urb);
                        usb_autopm_put_interface(acm->control);
@@ -605,7 +601,6 @@ static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int c
        spin_lock_irqsave(&acm->write_lock, flags);
        if ((wbn = acm_wb_alloc(acm)) < 0) {
                spin_unlock_irqrestore(&acm->write_lock, flags);
-               acm_write_start(acm);
                return 0;
        }
        wb = &acm->wb[wbn];
@@ -616,7 +611,7 @@ static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int c
        wb->len = count;
        spin_unlock_irqrestore(&acm->write_lock, flags);
 
-       if ((stat = acm_write_start(acm)) < 0)
+       if ((stat = acm_write_start(acm, wbn)) < 0)
                return stat;
        return count;
 }
@@ -809,7 +804,7 @@ static int acm_probe (struct usb_interface *intf,
 {
        struct usb_cdc_union_desc *union_header = NULL;
        struct usb_cdc_country_functional_desc *cfd = NULL;
-       char *buffer = intf->altsetting->extra;
+       unsigned char *buffer = intf->altsetting->extra;
        int buflen = intf->altsetting->extralen;
        struct usb_interface *control_interface;
        struct usb_interface *data_interface;
@@ -886,9 +881,13 @@ static int acm_probe (struct usb_interface *intf,
                                if ((call_management_function & 3) != 3)
                                        err("This device cannot do calls on its own. It is no modem.");
                                break;
-                               
                        default:
-                               err("Ignoring extra header, type %d, length %d", buffer[2], buffer[0]);
+                               /* there are LOTS more CDC descriptors that
+                                * could legitimately be found here.
+                                */
+                               dev_dbg(&intf->dev, "Ignoring descriptor: "
+                                               "type %02x, length %d\n",
+                                               buffer[2], buffer[0]);
                                break;
                        }
 next_desc:
@@ -976,7 +975,7 @@ skip_normal_probe:
 
        ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
        readsize = le16_to_cpu(epread->wMaxPacketSize)* ( quirks == SINGLE_RX_URB ? 1 : 2);
-       acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize);
+       acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize) * 20;
        acm->control = control_interface;
        acm->data = data_interface;
        acm->minor = minor;
@@ -1031,10 +1030,19 @@ skip_normal_probe:
                        goto alloc_fail7;
                }
        }
-       acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!acm->writeurb) {
-               dev_dbg(&intf->dev, "out of memory (writeurb kmalloc)\n");
-               goto alloc_fail7;
+       for(i = 0; i < ACM_NW; i++)
+       {
+               struct acm_wb *snd = &(acm->wb[i]);
+
+               if (!(snd->urb = usb_alloc_urb(0, GFP_KERNEL))) {
+                       dev_dbg(&intf->dev, "out of memory (write urbs usb_alloc_urb)");
+                       goto alloc_fail7;
+               }
+
+               usb_fill_bulk_urb(snd->urb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
+                               NULL, acm->writesize, acm_write_bulk, snd);
+               snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+               snd->instance = acm;
        }
 
        usb_set_intfdata (intf, acm);
@@ -1070,10 +1078,6 @@ skip_countries:
        acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
        acm->ctrlurb->transfer_dma = acm->ctrl_dma;
 
-       usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
-                         NULL, acm->writesize, acm_write_bulk, acm);
-       acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
-
        dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
 
        acm_set_control(acm, acm->ctrlout);
@@ -1091,7 +1095,8 @@ skip_countries:
 
        return 0;
 alloc_fail8:
-       usb_free_urb(acm->writeurb);
+       for (i = 0; i < ACM_NW; i++)
+               usb_free_urb(acm->wb[i].urb);
 alloc_fail7:
        for (i = 0; i < num_rx_buf; i++)
                usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
@@ -1115,7 +1120,8 @@ static void stop_data_traffic(struct acm *acm)
        tasklet_disable(&acm->urb_task);
 
        usb_kill_urb(acm->ctrlurb);
-       usb_kill_urb(acm->writeurb);
+       for(i = 0; i < ACM_NW; i++)
+               usb_kill_urb(acm->wb[i].urb);
        for (i = 0; i < acm->rx_buflimit; i++)
                usb_kill_urb(acm->ru[i].urb);
 
index 8df6a57dcf9e4ca188b368f62ca2f0b4b86df4c6..046e064b033af6675bb48208b277f9967130c243 100644 (file)
@@ -59,7 +59,7 @@
  * when processing onlcr, so we only need 2 buffers. These values must be
  * powers of 2.
  */
-#define ACM_NW  2
+#define ACM_NW  16
 #define ACM_NR  16
 
 struct acm_wb {
@@ -67,6 +67,8 @@ struct acm_wb {
        dma_addr_t dmah;
        int len;
        int use;
+       struct urb              *urb;
+       struct acm              *instance;
 };
 
 struct acm_rb {
@@ -88,7 +90,7 @@ struct acm {
        struct usb_interface *control;                  /* control interface */
        struct usb_interface *data;                     /* data interface */
        struct tty_struct *tty;                         /* the corresponding tty */
-       struct urb *ctrlurb, *writeurb;                 /* urbs */
+       struct urb *ctrlurb;                    /* urbs */
        u8 *ctrl_buffer;                                /* buffers of urbs */
        dma_addr_t ctrl_dma;                            /* dma handles of buffers */
        u8 *country_codes;                              /* country codes from device */
@@ -103,7 +105,6 @@ struct acm {
        struct list_head spare_read_urbs;
        struct list_head spare_read_bufs;
        struct list_head filled_read_bufs;
-       int write_current;                              /* current write buffer */
        int write_used;                                 /* number of non-empty write buffers */
        int write_ready;                                /* write urb is not running */
        spinlock_t write_lock;
index a2b0aa48b8eaba4d5be56c5d2bcbe3a4ed9fc2cd..cc9f397e8398043b250a424bc582fcc9d008e102 100644 (file)
@@ -76,8 +76,8 @@ config USB_DEVICE_CLASS
            NAME="bus/usb/$env{BUSNUM}/$env{DEVNUM}", MODE="0644"
 
 config USB_DYNAMIC_MINORS
-       bool "Dynamic USB minor allocation (EXPERIMENTAL)"
-       depends on USB && EXPERIMENTAL
+       bool "Dynamic USB minor allocation"
+       depends on USB
        help
          If you say Y here, the USB subsystem will use dynamic minor
          allocation for any device that uses the USB major number.
@@ -102,31 +102,6 @@ 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
@@ -136,14 +111,16 @@ config USB_OTG
 
 config USB_OTG_WHITELIST
        bool "Rely on OTG Targeted Peripherals List"
-       depends on USB_OTG
-       default y
+       depends on USB_OTG || EMBEDDED
+       default y if USB_OTG
+       default n if EMBEDDED
        help
          If you say Y here, the "otg_whitelist.h" file will be used as a
          product whitelist, so USB peripherals not listed there will be
          rejected during enumeration.  This behavior is required by the
          USB OTG specification for all devices not on your product's
-         "Targeted Peripherals List".
+         "Targeted Peripherals List".  "Embedded Hosts" are likewise
+         allowed to support only a limited number of peripherals.
 
          Otherwise, peripherals not listed there will only generate a
          warning and enumeration will continue.  That's more like what
@@ -152,9 +129,10 @@ config USB_OTG_WHITELIST
 
 config USB_OTG_BLACKLIST_HUB
        bool "Disable external hubs"
-       depends on USB_OTG
+       depends on USB_OTG || EMBEDDED
        help
          If you say Y here, then Linux will refuse to enumerate
          external hubs.  OTG hosts are allowed to reduce hardware
-         and software costs by not supporting external hubs.
+         and software costs by not supporting external hubs.  So
+         are "Emedded Hosts" that don't offer OTG support.
 
index a92122a216bcc8dbb4f7ea092fa3108cdaaba36a..568244c99bdc0f5d7b0e03d2177d1153e9d49d49 100644 (file)
@@ -145,6 +145,23 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
                        endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
        }
 
+       /*
+        * Some buggy high speed devices have bulk endpoints using
+        * maxpacket sizes other than 512.  High speed HCDs may not
+        * be able to handle that particular bug, so let's warn...
+        */
+       if (to_usb_device(ddev)->speed == USB_SPEED_HIGH
+                       && usb_endpoint_xfer_bulk(d)) {
+               unsigned maxp;
+
+               maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize) & 0x07ff;
+               if (maxp != 512)
+                       dev_warn(ddev, "config %d interface %d altsetting %d "
+                               "bulk endpoint 0x%X has invalid maxpacket %d\n",
+                               cfgno, inum, asnum, d->bEndpointAddress,
+                               maxp);
+       }
+
        /* Skip over any Class Specific or Vendor Specific descriptors;
         * find the next endpoint or interface descriptor */
        endpoint->extra = buffer;
index ae94176c64e41245efa23335d6a4787741ef9e7f..de17738f3acbab5c69066a81a31b041d25c5bf38 100644 (file)
@@ -647,6 +647,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)
        struct usbdevfs_ctrltransfer ctrl;
        unsigned int tmo;
        unsigned char *tbuf;
+       unsigned wLength;
        int i, j, ret;
 
        if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
@@ -654,7 +655,8 @@ static int proc_control(struct dev_state *ps, void __user *arg)
        ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex);
        if (ret)
                return ret;
-       if (ctrl.wLength > PAGE_SIZE)
+       wLength = ctrl.wLength;         /* To suppress 64k PAGE_SIZE warning */
+       if (wLength > PAGE_SIZE)
                return -EINVAL;
        tbuf = (unsigned char *)__get_free_page(GFP_KERNEL);
        if (!tbuf)
@@ -946,8 +948,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
        int ret, ifnum = -1;
        int is_in;
 
-       if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
-                          URB_NO_FSBR|URB_ZERO_PACKET))
+       if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP |
+                               USBDEVFS_URB_SHORT_NOT_OK |
+                               USBDEVFS_URB_NO_FSBR |
+                               USBDEVFS_URB_ZERO_PACKET |
+                               USBDEVFS_URB_NO_INTERRUPT))
                return -EINVAL;
        if (!uurb->buffer)
                return -EINVAL;
@@ -1102,8 +1107,24 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
        as->urb->pipe = (uurb->type << 30) |
                        __create_pipe(ps->dev, uurb->endpoint & 0xf) |
                        (uurb->endpoint & USB_DIR_IN);
-       as->urb->transfer_flags = uurb->flags |
-                       (is_in ? URB_DIR_IN : URB_DIR_OUT);
+
+       /* This tedious sequence is necessary because the URB_* flags
+        * are internal to the kernel and subject to change, whereas
+        * the USBDEVFS_URB_* flags are a user API and must not be changed.
+        */
+       u = (is_in ? URB_DIR_IN : URB_DIR_OUT);
+       if (uurb->flags & USBDEVFS_URB_ISO_ASAP)
+               u |= URB_ISO_ASAP;
+       if (uurb->flags & USBDEVFS_URB_SHORT_NOT_OK)
+               u |= URB_SHORT_NOT_OK;
+       if (uurb->flags & USBDEVFS_URB_NO_FSBR)
+               u |= URB_NO_FSBR;
+       if (uurb->flags & USBDEVFS_URB_ZERO_PACKET)
+               u |= URB_ZERO_PACKET;
+       if (uurb->flags & USBDEVFS_URB_NO_INTERRUPT)
+               u |= URB_NO_INTERRUPT;
+       as->urb->transfer_flags = u;
+
        as->urb->transfer_buffer_length = uurb->buffer_length;
        as->urb->setup_packet = (unsigned char *)dr;
        as->urb->start_frame = uurb->start_frame;
@@ -1509,60 +1530,60 @@ static int usbdev_ioctl(struct inode *inode, struct file *file,
 
        switch (cmd) {
        case USBDEVFS_CONTROL:
-               snoop(&dev->dev, "%s: CONTROL\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: CONTROL\n", __func__);
                ret = proc_control(ps, p);
                if (ret >= 0)
                        inode->i_mtime = CURRENT_TIME;
                break;
 
        case USBDEVFS_BULK:
-               snoop(&dev->dev, "%s: BULK\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: BULK\n", __func__);
                ret = proc_bulk(ps, p);
                if (ret >= 0)
                        inode->i_mtime = CURRENT_TIME;
                break;
 
        case USBDEVFS_RESETEP:
-               snoop(&dev->dev, "%s: RESETEP\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: RESETEP\n", __func__);
                ret = proc_resetep(ps, p);
                if (ret >= 0)
                        inode->i_mtime = CURRENT_TIME;
                break;
 
        case USBDEVFS_RESET:
-               snoop(&dev->dev, "%s: RESET\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: RESET\n", __func__);
                ret = proc_resetdevice(ps);
                break;
 
        case USBDEVFS_CLEAR_HALT:
-               snoop(&dev->dev, "%s: CLEAR_HALT\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: CLEAR_HALT\n", __func__);
                ret = proc_clearhalt(ps, p);
                if (ret >= 0)
                        inode->i_mtime = CURRENT_TIME;
                break;
 
        case USBDEVFS_GETDRIVER:
-               snoop(&dev->dev, "%s: GETDRIVER\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: GETDRIVER\n", __func__);
                ret = proc_getdriver(ps, p);
                break;
 
        case USBDEVFS_CONNECTINFO:
-               snoop(&dev->dev, "%s: CONNECTINFO\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: CONNECTINFO\n", __func__);
                ret = proc_connectinfo(ps, p);
                break;
 
        case USBDEVFS_SETINTERFACE:
-               snoop(&dev->dev, "%s: SETINTERFACE\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: SETINTERFACE\n", __func__);
                ret = proc_setintf(ps, p);
                break;
 
        case USBDEVFS_SETCONFIGURATION:
-               snoop(&dev->dev, "%s: SETCONFIGURATION\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: SETCONFIGURATION\n", __func__);
                ret = proc_setconfig(ps, p);
                break;
 
        case USBDEVFS_SUBMITURB:
-               snoop(&dev->dev, "%s: SUBMITURB\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: SUBMITURB\n", __func__);
                ret = proc_submiturb(ps, p);
                if (ret >= 0)
                        inode->i_mtime = CURRENT_TIME;
@@ -1571,60 +1592,60 @@ static int usbdev_ioctl(struct inode *inode, struct file *file,
 #ifdef CONFIG_COMPAT
 
        case USBDEVFS_SUBMITURB32:
-               snoop(&dev->dev, "%s: SUBMITURB32\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: SUBMITURB32\n", __func__);
                ret = proc_submiturb_compat(ps, p);
                if (ret >= 0)
                        inode->i_mtime = CURRENT_TIME;
                break;
 
        case USBDEVFS_REAPURB32:
-               snoop(&dev->dev, "%s: REAPURB32\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: REAPURB32\n", __func__);
                ret = proc_reapurb_compat(ps, p);
                break;
 
        case USBDEVFS_REAPURBNDELAY32:
-               snoop(&dev->dev, "%s: REAPURBDELAY32\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: REAPURBDELAY32\n", __func__);
                ret = proc_reapurbnonblock_compat(ps, p);
                break;
 
        case USBDEVFS_IOCTL32:
-               snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: IOCTL\n", __func__);
                ret = proc_ioctl_compat(ps, ptr_to_compat(p));
                break;
 #endif
 
        case USBDEVFS_DISCARDURB:
-               snoop(&dev->dev, "%s: DISCARDURB\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: DISCARDURB\n", __func__);
                ret = proc_unlinkurb(ps, p);
                break;
 
        case USBDEVFS_REAPURB:
-               snoop(&dev->dev, "%s: REAPURB\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: REAPURB\n", __func__);
                ret = proc_reapurb(ps, p);
                break;
 
        case USBDEVFS_REAPURBNDELAY:
-               snoop(&dev->dev, "%s: REAPURBDELAY\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: REAPURBDELAY\n", __func__);
                ret = proc_reapurbnonblock(ps, p);
                break;
 
        case USBDEVFS_DISCSIGNAL:
-               snoop(&dev->dev, "%s: DISCSIGNAL\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: DISCSIGNAL\n", __func__);
                ret = proc_disconnectsignal(ps, p);
                break;
 
        case USBDEVFS_CLAIMINTERFACE:
-               snoop(&dev->dev, "%s: CLAIMINTERFACE\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: CLAIMINTERFACE\n", __func__);
                ret = proc_claiminterface(ps, p);
                break;
 
        case USBDEVFS_RELEASEINTERFACE:
-               snoop(&dev->dev, "%s: RELEASEINTERFACE\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: RELEASEINTERFACE\n", __func__);
                ret = proc_releaseinterface(ps, p);
                break;
 
        case USBDEVFS_IOCTL:
-               snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
+               snoop(&dev->dev, "%s: IOCTL\n", __func__);
                ret = proc_ioctl_default(ps, p);
                break;
        }
index 801b6f142fa7f874650a99c4d28c268c887a3114..1e56f1cfa6dc9447c22df3de61a840a3ac401330 100644 (file)
@@ -157,7 +157,7 @@ static int usb_probe_device(struct device *dev)
        struct usb_device *udev;
        int error = -ENODEV;
 
-       dev_dbg(dev, "%s\n", __FUNCTION__);
+       dev_dbg(dev, "%s\n", __func__);
 
        if (!is_usb_device(dev))        /* Sanity check */
                return error;
@@ -194,7 +194,7 @@ static int usb_probe_interface(struct device *dev)
        const struct usb_device_id *id;
        int error = -ENODEV;
 
-       dev_dbg(dev, "%s\n", __FUNCTION__);
+       dev_dbg(dev, "%s\n", __func__);
 
        if (is_usb_device(dev))         /* Sanity check */
                return error;
@@ -211,7 +211,7 @@ static int usb_probe_interface(struct device *dev)
        if (!id)
                id = usb_match_dynamic_id(intf, driver);
        if (id) {
-               dev_dbg(dev, "%s - got id\n", __FUNCTION__);
+               dev_dbg(dev, "%s - got id\n", __func__);
 
                error = usb_autoresume_device(udev);
                if (error)
@@ -793,9 +793,7 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
        status = udriver->suspend(udev, msg);
 
  done:
-       dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
-       if (status == 0)
-               udev->dev.power.power_state.event = msg.event;
+       dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
        return status;
 }
 
@@ -823,11 +821,9 @@ static int usb_resume_device(struct usb_device *udev)
        status = udriver->resume(udev);
 
  done:
-       dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
-       if (status == 0) {
+       dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
+       if (status == 0)
                udev->autoresume_disabled = 0;
-               udev->dev.power.power_state.event = PM_EVENT_ON;
-       }
        return status;
 }
 
@@ -864,7 +860,7 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
        }
 
  done:
-       dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+       dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status);
        return status;
 }
 
@@ -914,7 +910,7 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
        }
 
 done:
-       dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+       dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status);
        if (status == 0)
                mark_active(intf);
 
@@ -936,7 +932,6 @@ static int autosuspend_check(struct usb_device *udev, int reschedule)
         * is disabled.  Also fail if any interfaces require remote wakeup
         * but it isn't available.
         */
-       udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
        if (udev->pm_usage_cnt > 0)
                return -EBUSY;
        if (udev->autosuspend_delay < 0 || udev->autosuspend_disabled)
@@ -1098,7 +1093,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
        }
 
  done:
-       dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+       dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
        return status;
 }
 
@@ -1180,8 +1175,7 @@ static int usb_resume_both(struct usb_device *udev)
                }
        } else {
 
-               /* Needed for setting udev->dev.power.power_state.event,
-                * for possible debugging message, and for reset_resume. */
+               /* Needed for reset-resume */
                status = usb_resume_device(udev);
        }
 
@@ -1193,8 +1187,9 @@ static int usb_resume_both(struct usb_device *udev)
        }
 
  done:
-       dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
-       udev->reset_resume = 0;
+       dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
+       if (!status)
+               udev->reset_resume = 0;
        return status;
 }
 
@@ -1262,7 +1257,7 @@ void usb_autosuspend_device(struct usb_device *udev)
 
        status = usb_autopm_do_device(udev, -1);
        dev_vdbg(&udev->dev, "%s: cnt %d\n",
-                       __FUNCTION__, udev->pm_usage_cnt);
+                       __func__, udev->pm_usage_cnt);
 }
 
 /**
@@ -1282,7 +1277,7 @@ void usb_try_autosuspend_device(struct usb_device *udev)
 {
        usb_autopm_do_device(udev, 0);
        dev_vdbg(&udev->dev, "%s: cnt %d\n",
-                       __FUNCTION__, udev->pm_usage_cnt);
+                       __func__, udev->pm_usage_cnt);
 }
 
 /**
@@ -1310,7 +1305,7 @@ int usb_autoresume_device(struct usb_device *udev)
 
        status = usb_autopm_do_device(udev, 1);
        dev_vdbg(&udev->dev, "%s: status %d cnt %d\n",
-                       __FUNCTION__, status, udev->pm_usage_cnt);
+                       __func__, status, udev->pm_usage_cnt);
        return status;
 }
 
@@ -1382,7 +1377,7 @@ void usb_autopm_put_interface(struct usb_interface *intf)
 
        status = usb_autopm_do_interface(intf, -1);
        dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
-                       __FUNCTION__, status, intf->pm_usage_cnt);
+                       __func__, status, intf->pm_usage_cnt);
 }
 EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
 
@@ -1426,7 +1421,7 @@ int usb_autopm_get_interface(struct usb_interface *intf)
 
        status = usb_autopm_do_interface(intf, 1);
        dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
-                       __FUNCTION__, status, intf->pm_usage_cnt);
+                       __func__, status, intf->pm_usage_cnt);
        return status;
 }
 EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
@@ -1448,7 +1443,7 @@ int usb_autopm_set_interface(struct usb_interface *intf)
 
        status = usb_autopm_do_interface(intf, 0);
        dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
-                       __FUNCTION__, status, intf->pm_usage_cnt);
+                       __func__, status, intf->pm_usage_cnt);
        return status;
 }
 EXPORT_SYMBOL_GPL(usb_autopm_set_interface);
@@ -1523,9 +1518,14 @@ static int usb_suspend(struct device *dev, pm_message_t message)
        udev = to_usb_device(dev);
 
        /* If udev is already suspended, we can skip this suspend and
-        * we should also skip the upcoming system resume. */
+        * we should also skip the upcoming system resume.  High-speed
+        * root hubs are an exception; they need to resume whenever the
+        * system wakes up in order for USB-PERSIST port handover to work
+        * properly.
+        */
        if (udev->state == USB_STATE_SUSPENDED) {
-               udev->skip_sys_resume = 1;
+               if (udev->parent || udev->speed != USB_SPEED_HIGH)
+                       udev->skip_sys_resume = 1;
                return 0;
        }
 
index 84760ddbc3325cba6cfdc8b219c3d70f32e0a5ab..5b87ae7f0a6acc2d2ab7ecf3f7d4a3af2da1915c 100644 (file)
@@ -73,7 +73,6 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
        if (pci_enable_device(dev) < 0)
                return -ENODEV;
        dev->current_state = PCI_D0;
-       dev->dev.power.power_state = PMSG_ON;
 
        if (!dev->irq) {
                dev_err(&dev->dev,
@@ -216,9 +215,9 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
                        hcd->state == HC_STATE_HALT))
                return -EBUSY;
 
-       if (hcd->driver->suspend) {
-               retval = hcd->driver->suspend(hcd, message);
-               suspend_report_result(hcd->driver->suspend, retval);
+       if (hcd->driver->pci_suspend) {
+               retval = hcd->driver->pci_suspend(hcd, message);
+               suspend_report_result(hcd->driver->pci_suspend, retval);
                if (retval)
                        goto done;
        }
@@ -302,8 +301,6 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
 
 done:
        if (retval == 0) {
-               dev->dev.power.power_state = PMSG_SUSPEND;
-
 #ifdef CONFIG_PPC_PMAC
                /* Disable ASIC clocks for USB */
                if (machine_is(powermac)) {
@@ -406,12 +403,10 @@ int usb_hcd_pci_resume(struct pci_dev *dev)
        pci_set_master(dev);
        pci_restore_state(dev);
 
-       dev->dev.power.power_state = PMSG_ON;
-
        clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
 
-       if (hcd->driver->resume) {
-               retval = hcd->driver->resume(hcd);
+       if (hcd->driver->pci_resume) {
+               retval = hcd->driver->pci_resume(hcd);
                if (retval) {
                        dev_err(hcd->self.controller,
                                "PCI post-resume error %d!\n", retval);
index e52ed1663b3c566ae5d0aa53799faa46f2f00324..bf10e9c4195e04eb473e15f65d17903b7afde935 100644 (file)
@@ -129,7 +129,7 @@ static const u8 usb2_rh_dev_descriptor [18] = {
 
        0x09,       /*  __u8  bDeviceClass; HUB_CLASSCODE */
        0x00,       /*  __u8  bDeviceSubClass; */
-       0x01,       /*  __u8  bDeviceProtocol; [ usb 2.0 single TT ]*/
+       0x00,       /*  __u8  bDeviceProtocol; [ usb 2.0 no TT ] */
        0x40,       /*  __u8  bMaxPacketSize0; 64 Bytes */
 
        0x6b, 0x1d, /*  __le16 idVendor; Linux Foundation */
@@ -291,7 +291,6 @@ static int ascii2utf (char *s, u8 *utf, int utfmax)
  * rh_string - provides manufacturer, product and serial strings for root hub
  * @id: the string ID number (1: serial number, 2: product, 3: vendor)
  * @hcd: the host controller for this root hub
- * @type: string describing our driver 
  * @data: return packet in UTF-16 LE
  * @len: length of the return packet
  *
@@ -355,9 +354,10 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
                __attribute__((aligned(4)));
        const u8        *bufp = tbuf;
        int             len = 0;
-       int             patch_wakeup = 0;
        int             status;
        int             n;
+       u8              patch_wakeup = 0;
+       u8              patch_protocol = 0;
 
        might_sleep();
 
@@ -434,6 +434,8 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
                        else
                                goto error;
                        len = 18;
+                       if (hcd->has_tt)
+                               patch_protocol = 1;
                        break;
                case USB_DT_CONFIG << 8:
                        if (hcd->driver->flags & HCD_USB2) {
@@ -528,6 +530,13 @@ error:
                                                bmAttributes))
                        ((struct usb_config_descriptor *)ubuf)->bmAttributes
                                |= USB_CONFIG_ATT_WAKEUP;
+
+               /* report whether RH hardware has an integrated TT */
+               if (patch_protocol &&
+                               len > offsetof(struct usb_device_descriptor,
+                                               bDeviceProtocol))
+                       ((struct usb_device_descriptor *) ubuf)->
+                                       bDeviceProtocol = 1;
        }
 
        /* any errors get returned through the urb completion */
@@ -915,15 +924,6 @@ static int register_root_hub(struct usb_hcd *hcd)
        return retval;
 }
 
-void usb_enable_root_hub_irq (struct usb_bus *bus)
-{
-       struct usb_hcd *hcd;
-
-       hcd = container_of (bus, struct usb_hcd, self);
-       if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT)
-               hcd->driver->hub_irq_enable (hcd);
-}
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -1677,7 +1677,6 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);
  * usb_hcd_irq - hook IRQs to HCD framework (bus glue)
  * @irq: the IRQ being raised
  * @__hcd: pointer to the HCD whose IRQ is being signaled
- * @r: saved hardware registers
  *
  * If the controller isn't HALTed, calls the driver's irq handler.
  * Checks whether the controller is now dead.
index 2d1c3d5e47b8b3e791bbbed28f857247da6ad2e9..1e4b81e9eb5034a06c1b85406f0dbaf3da7f77a9 100644 (file)
@@ -28,7 +28,7 @@
 /*
  * USB Packet IDs (PIDs)
  */
-#define USB_PID_UNDEF_0                        0xf0
+#define USB_PID_EXT                    0xf0    /* USB 2.0 LPM ECN */
 #define USB_PID_OUT                    0xe1
 #define USB_PID_ACK                    0xd2
 #define USB_PID_DATA0                  0xc3
@@ -99,6 +99,7 @@ struct usb_hcd {
        unsigned                poll_pending:1; /* status has changed? */
        unsigned                wireless:1;     /* Wireless USB HCD */
        unsigned                authorized_default:1;
+       unsigned                has_tt:1;       /* Integrated TT in root hub */
 
        int                     irq;            /* irq allocated */
        void __iomem            *regs;          /* device memory/io */
@@ -177,10 +178,10 @@ struct hc_driver {
         * a whole, not just the root hub; they're for PCI bus glue.
         */
        /* called after suspending the hub, before entering D3 etc */
-       int     (*suspend) (struct usb_hcd *hcd, pm_message_t message);
+       int     (*pci_suspend) (struct usb_hcd *hcd, pm_message_t message);
 
        /* called after entering D0 (etc), before resuming the hub */
-       int     (*resume) (struct usb_hcd *hcd);
+       int     (*pci_resume) (struct usb_hcd *hcd);
 
        /* cleanly make HCD stop writing memory and doing I/O */
        void    (*stop) (struct usb_hcd *hcd);
@@ -209,8 +210,6 @@ struct hc_driver {
        int     (*bus_suspend)(struct usb_hcd *);
        int     (*bus_resume)(struct usb_hcd *);
        int     (*start_port_reset)(struct usb_hcd *, unsigned port_num);
-       void    (*hub_irq_enable)(struct usb_hcd *);
-               /* Needed only if port-change IRQs are level-triggered */
 
                /* force handover of high-speed port to full-speed companion */
        void    (*relinquish_port)(struct usb_hcd *, int);
index 57aeca160f3837a6cc39b580a8192d086cc15e9b..eb57fcc701d7d995e271c39773f0ac3738214222 100644 (file)
 #include "hcd.h"
 #include "hub.h"
 
-#ifdef CONFIG_USB_PERSIST
-#define        USB_PERSIST     1
-#else
-#define        USB_PERSIST     0
-#endif
-
 /* if we are in debug mode, always announce new devices */
 #ifdef DEBUG
 #ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES
@@ -333,6 +327,27 @@ static int get_port_status(struct usb_device *hdev, int port1,
        return status;
 }
 
+static int hub_port_status(struct usb_hub *hub, int port1,
+               u16 *status, u16 *change)
+{
+       int ret;
+
+       mutex_lock(&hub->status_mutex);
+       ret = get_port_status(hub->hdev, port1, &hub->status->port);
+       if (ret < 4) {
+               dev_err(hub->intfdev,
+                       "%s failed (err = %d)\n", __func__, ret);
+               if (ret >= 0)
+                       ret = -EIO;
+       } else {
+               *status = le16_to_cpu(hub->status->port.wPortStatus);
+               *change = le16_to_cpu(hub->status->port.wPortChange);
+               ret = 0;
+       }
+       mutex_unlock(&hub->status_mutex);
+       return ret;
+}
+
 static void kick_khubd(struct usb_hub *hub)
 {
        unsigned long   flags;
@@ -560,7 +575,7 @@ static int hub_hub_status(struct usb_hub *hub,
        ret = get_hub_status(hub->hdev, &hub->status->hub);
        if (ret < 0)
                dev_err (hub->intfdev,
-                       "%s failed (err = %d)\n", __FUNCTION__, ret);
+                       "%s failed (err = %d)\n", __func__, ret);
        else {
                *status = le16_to_cpu(hub->status->hub.wHubStatus);
                *change = le16_to_cpu(hub->status->hub.wHubChange); 
@@ -610,9 +625,8 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
 }
 
 /* caller has locked the hub device */
-static int hub_pre_reset(struct usb_interface *intf)
+static void hub_stop(struct usb_hub *hub)
 {
-       struct usb_hub *hub = usb_get_intfdata(intf);
        struct usb_device *hdev = hub->hdev;
        int i;
 
@@ -622,6 +636,89 @@ static int hub_pre_reset(struct usb_interface *intf)
                        usb_disconnect(&hdev->children[i]);
        }
        hub_quiesce(hub);
+}
+
+#define HUB_RESET              1
+#define HUB_RESUME             2
+#define HUB_RESET_RESUME       3
+
+#ifdef CONFIG_PM
+
+static void hub_restart(struct usb_hub *hub, int type)
+{
+       struct usb_device *hdev = hub->hdev;
+       int port1;
+
+       /* Check each of the children to see if they require
+        * USB-PERSIST handling or disconnection.  Also check
+        * each unoccupied port to make sure it is still disabled.
+        */
+       for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+               struct usb_device *udev = hdev->children[port1-1];
+               int status = 0;
+               u16 portstatus, portchange;
+
+               if (!udev || udev->state == USB_STATE_NOTATTACHED) {
+                       if (type != HUB_RESET) {
+                               status = hub_port_status(hub, port1,
+                                               &portstatus, &portchange);
+                               if (status == 0 && (portstatus &
+                                               USB_PORT_STAT_ENABLE))
+                                       clear_port_feature(hdev, port1,
+                                                       USB_PORT_FEAT_ENABLE);
+                       }
+                       continue;
+               }
+
+               /* Was the power session lost while we were suspended? */
+               switch (type) {
+               case HUB_RESET_RESUME:
+                       portstatus = 0;
+                       portchange = USB_PORT_STAT_C_CONNECTION;
+                       break;
+
+               case HUB_RESET:
+               case HUB_RESUME:
+                       status = hub_port_status(hub, port1,
+                                       &portstatus, &portchange);
+                       break;
+               }
+
+               /* For "USB_PERSIST"-enabled children we must
+                * mark the child device for reset-resume and
+                * turn off the various status changes to prevent
+                * khubd from disconnecting it later.
+                */
+               if (udev->persist_enabled && status == 0 &&
+                               !(portstatus & USB_PORT_STAT_ENABLE)) {
+                       if (portchange & USB_PORT_STAT_C_ENABLE)
+                               clear_port_feature(hub->hdev, port1,
+                                               USB_PORT_FEAT_C_ENABLE);
+                       if (portchange & USB_PORT_STAT_C_CONNECTION)
+                               clear_port_feature(hub->hdev, port1,
+                                               USB_PORT_FEAT_C_CONNECTION);
+                       udev->reset_resume = 1;
+               }
+
+               /* Otherwise for a reset_resume we must disconnect the child,
+                * but as we may not lock the child device here
+                * we have to do a "logical" disconnect.
+                */
+               else if (type == HUB_RESET_RESUME)
+                       hub_port_logical_disconnect(hub, port1);
+       }
+
+       hub_activate(hub);
+}
+
+#endif /* CONFIG_PM */
+
+/* caller has locked the hub device */
+static int hub_pre_reset(struct usb_interface *intf)
+{
+       struct usb_hub *hub = usb_get_intfdata(intf);
+
+       hub_stop(hub);
        return 0;
 }
 
@@ -910,7 +1007,7 @@ static void hub_disconnect(struct usb_interface *intf)
 
        /* Disconnect all children and quiesce the hub */
        hub->error = 0;
-       hub_pre_reset(intf);
+       hub_stop(hub);
 
        usb_set_intfdata (intf, NULL);
 
@@ -1098,21 +1195,42 @@ void usb_set_device_state(struct usb_device *udev,
        spin_unlock_irqrestore(&device_state_lock, flags);
 }
 
+/*
+ * WUSB devices are simple: they have no hubs behind, so the mapping
+ * device <-> virtual port number becomes 1:1. Why? to simplify the
+ * life of the device connection logic in
+ * drivers/usb/wusbcore/devconnect.c. When we do the initial secret
+ * handshake we need to assign a temporary address in the unauthorized
+ * space. For simplicity we use the first virtual port number found to
+ * be free [drivers/usb/wusbcore/devconnect.c:wusbhc_devconnect_ack()]
+ * and that becomes it's address [X < 128] or its unauthorized address
+ * [X | 0x80].
+ *
+ * We add 1 as an offset to the one-based USB-stack port number
+ * (zero-based wusb virtual port index) for two reasons: (a) dev addr
+ * 0 is reserved by USB for default address; (b) Linux's USB stack
+ * uses always #1 for the root hub of the controller. So USB stack's
+ * port #1, which is wusb virtual-port #0 has address #2.
+ */
 static void choose_address(struct usb_device *udev)
 {
        int             devnum;
        struct usb_bus  *bus = udev->bus;
 
        /* If khubd ever becomes multithreaded, this will need a lock */
-
-       /* Try to allocate the next devnum beginning at bus->devnum_next. */
-       devnum = find_next_zero_bit(bus->devmap.devicemap, 128,
-                       bus->devnum_next);
-       if (devnum >= 128)
-               devnum = find_next_zero_bit(bus->devmap.devicemap, 128, 1);
-
-       bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);
-
+       if (udev->wusb) {
+               devnum = udev->portnum + 1;
+               BUG_ON(test_bit(devnum, bus->devmap.devicemap));
+       } else {
+               /* Try to allocate the next devnum beginning at
+                * bus->devnum_next. */
+               devnum = find_next_zero_bit(bus->devmap.devicemap, 128,
+                                           bus->devnum_next);
+               if (devnum >= 128)
+                       devnum = find_next_zero_bit(bus->devmap.devicemap,
+                                                   128, 1);
+               bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);
+       }
        if (devnum < 128) {
                set_bit(devnum, bus->devmap.devicemap);
                udev->devnum = devnum;
@@ -1127,6 +1245,13 @@ static void release_address(struct usb_device *udev)
        }
 }
 
+static void update_address(struct usb_device *udev, int devnum)
+{
+       /* The address for a WUSB device is managed by wusbcore. */
+       if (!udev->wusb)
+               udev->devnum = devnum;
+}
+
 #ifdef CONFIG_USB_SUSPEND
 
 static void usb_stop_pm(struct usb_device *udev)
@@ -1173,7 +1298,7 @@ void usb_disconnect(struct usb_device **pdev)
        int                     i;
 
        if (!udev) {
-               pr_debug ("%s nodev\n", __FUNCTION__);
+               pr_debug ("%s nodev\n", __func__);
                return;
        }
 
@@ -1510,28 +1635,6 @@ out_authorized:
 }
 
 
-static int hub_port_status(struct usb_hub *hub, int port1,
-                              u16 *status, u16 *change)
-{
-       int ret;
-
-       mutex_lock(&hub->status_mutex);
-       ret = get_port_status(hub->hdev, port1, &hub->status->port);
-       if (ret < 4) {
-               dev_err (hub->intfdev,
-                       "%s failed (err = %d)\n", __FUNCTION__, ret);
-               if (ret >= 0)
-                       ret = -EIO;
-       } else {
-               *status = le16_to_cpu(hub->status->port.wPortStatus);
-               *change = le16_to_cpu(hub->status->port.wPortChange); 
-               ret = 0;
-       }
-       mutex_unlock(&hub->status_mutex);
-       return ret;
-}
-
-
 /* Returns 1 if @hub is a WUSB root hub, 0 otherwise */
 static unsigned hub_is_wusb(struct usb_hub *hub)
 {
@@ -1637,7 +1740,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
                case 0:
                        /* TRSTRCY = 10 ms; plus some extra */
                        msleep(10 + 40);
-                       udev->devnum = 0;       /* Device now at address 0 */
+                       update_address(udev, 0);
                        /* FALL THROUGH */
                case -ENOTCONN:
                case -ENODEV:
@@ -1842,9 +1945,8 @@ static int finish_port_resume(struct usb_device *udev)
  * 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
+ * If @udev->reset_resume is set then this routine won't check that the
+ * port is still enabled.  Furthermore, 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.
  *
@@ -1856,8 +1958,8 @@ static int finish_port_resume(struct usb_device *udev)
  * 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
+ * This facility can be 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
@@ -1902,7 +2004,7 @@ int usb_port_resume(struct usb_device *udev)
                status = hub_port_status(hub, port1, &portstatus, &portchange);
 
  SuspendCleared:
-               if (USB_PERSIST && udev->reset_resume)
+               if (udev->reset_resume)
                        want_flags = USB_PORT_STAT_POWER
                                        | USB_PORT_STAT_CONNECTION;
                else
@@ -1927,8 +2029,6 @@ int usb_port_resume(struct usb_device *udev)
        }
 
        clear_bit(port1, hub->busy_bits);
-       if (!hub->hdev->parent && !hub->busy_bits[0])
-               usb_enable_root_hub_irq(hub->hdev->bus);
 
        if (status == 0)
                status = finish_port_resume(udev);
@@ -2000,7 +2100,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
                }
        }
 
-       dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
+       dev_dbg(&intf->dev, "%s\n", __func__);
 
        /* stop khubd and related activity */
        hub_quiesce(hub);
@@ -2009,49 +2109,20 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
 
 static int hub_resume(struct usb_interface *intf)
 {
-       struct usb_hub          *hub = usb_get_intfdata (intf);
-
-       dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
+       struct usb_hub *hub = usb_get_intfdata(intf);
 
-       /* tell khubd to look for changes on this hub */
-       hub_activate(hub);
+       dev_dbg(&intf->dev, "%s\n", __func__);
+       hub_restart(hub, HUB_RESUME);
        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;
 
+       dev_dbg(&intf->dev, "%s\n", __func__);
        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);
-                       }
-               }
-       }
-
-       hub_activate(hub);
+       hub_restart(hub, HUB_RESET_RESUME);
        return 0;
 }
 
@@ -2061,10 +2132,10 @@ static int hub_reset_resume(struct usb_interface *intf)
  *
  * 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.
+ * has been reset.  The routine marks @rhdev as having lost power.
+ * When the hub driver is resumed it will take notice and carry out
+ * power-session recovery for all the "USB-PERSIST"-enabled child devices;
+ * the others will be disconnected.
  */
 void usb_root_hub_lost_power(struct usb_device *rhdev)
 {
@@ -2147,12 +2218,13 @@ static int hub_port_debounce(struct usb_hub *hub, int port1)
        return portstatus;
 }
 
-static void ep0_reinit(struct usb_device *udev)
+void usb_ep0_reinit(struct usb_device *udev)
 {
        usb_disable_endpoint(udev, 0 + USB_DIR_IN);
        usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
        usb_enable_endpoint(udev, &udev->ep0);
 }
+EXPORT_SYMBOL_GPL(usb_ep0_reinit);
 
 #define usb_sndaddr0pipe()     (PIPE_CONTROL << 30)
 #define usb_rcvaddr0pipe()     ((PIPE_CONTROL << 30) | USB_DIR_IN)
@@ -2171,9 +2243,10 @@ static int hub_set_address(struct usb_device *udev, int devnum)
                USB_REQ_SET_ADDRESS, 0, devnum, 0,
                NULL, 0, USB_CTRL_SET_TIMEOUT);
        if (retval == 0) {
-               udev->devnum = devnum;  /* Device now using proper address */
+               /* Device now using proper address. */
+               update_address(udev, devnum);
                usb_set_device_state(udev, USB_STATE_ADDRESS);
-               ep0_reinit(udev);
+               usb_ep0_reinit(udev);
        }
        return retval;
 }
@@ -2355,26 +2428,33 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
 #undef GET_DESCRIPTOR_BUFSIZE
                }
 
-               for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
-                       retval = hub_set_address(udev, devnum);
-                       if (retval >= 0)
+               /*
+                * If device is WUSB, we already assigned an
+                * unauthorized address in the Connect Ack sequence;
+                * authorization will assign the final address.
+                */
+               if (udev->wusb == 0) {
+                       for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
+                               retval = hub_set_address(udev, devnum);
+                               if (retval >= 0)
+                                       break;
+                               msleep(200);
+                       }
+                       if (retval < 0) {
+                               dev_err(&udev->dev,
+                                       "device not accepting address %d, error %d\n",
+                                       devnum, retval);
+                               goto fail;
+                       }
+
+                       /* cope with hardware quirkiness:
+                        *  - let SET_ADDRESS settle, some device hardware wants it
+                        *  - read ep0 maxpacket even for high and low speed,
+                        */
+                       msleep(10);
+                       if (USE_NEW_SCHEME(retry_counter))
                                break;
-                       msleep(200);
-               }
-               if (retval < 0) {
-                       dev_err(&udev->dev,
-                               "device not accepting address %d, error %d\n",
-                               devnum, retval);
-                       goto fail;
-               }
-               /* cope with hardware quirkiness:
-                *  - let SET_ADDRESS settle, some device hardware wants it
-                *  - read ep0 maxpacket even for high and low speed,
-                */
-               msleep(10);
-               if (USE_NEW_SCHEME(retry_counter))
-                       break;
+               }
 
                retval = usb_get_device_descriptor(udev, 8);
                if (retval < 8) {
@@ -2391,7 +2471,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
        if (retval)
                goto fail;
 
-       i = udev->descriptor.bMaxPacketSize0 == 0xff?
+       i = udev->descriptor.bMaxPacketSize0 == 0xff?   /* wusb device? */
            512 : udev->descriptor.bMaxPacketSize0;
        if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {
                if (udev->speed != USB_SPEED_FULL ||
@@ -2402,7 +2482,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
                }
                dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
                udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
-               ep0_reinit(udev);
+               usb_ep0_reinit(udev);
        }
   
        retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
@@ -2419,7 +2499,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
 fail:
        if (retval) {
                hub_port_disable(hub, port1, 0);
-               udev->devnum = devnum;  /* for disconnect processing */
+               update_address(udev, devnum);   /* for disconnect processing */
        }
        mutex_unlock(&usb_address0_mutex);
        return retval;
@@ -2568,6 +2648,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
                udev->speed = USB_SPEED_UNKNOWN;
                udev->bus_mA = hub->mA_per_port;
                udev->level = hdev->level + 1;
+               udev->wusb = hub_is_wusb(hub);
 
                /* set the address */
                choose_address(udev);
@@ -2657,12 +2738,13 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 loop_disable:
                hub_port_disable(hub, port1, 1);
 loop:
-               ep0_reinit(udev);
+               usb_ep0_reinit(udev);
                release_address(udev);
                usb_put_dev(udev);
                if ((status == -ENOTCONN) || (status == -ENOTSUPP))
                        break;
        }
+       dev_err(hub_dev, "unable to enumerate USB device on port %d\n", port1);
  
 done:
        hub_port_disable(hub, port1, 1);
@@ -2726,7 +2808,7 @@ static void hub_events(void)
                /* If the hub has died, clean up after it */
                if (hdev->state == USB_STATE_NOTATTACHED) {
                        hub->error = -ENODEV;
-                       hub_pre_reset(intf);
+                       hub_stop(hub);
                        goto loop;
                }
 
@@ -2872,11 +2954,6 @@ static void hub_events(void)
 
                hub->activating = 0;
 
-               /* If this is a root hub, tell the HCD it's okay to
-                * re-enable port-change interrupts now. */
-               if (!hdev->parent && !hub->busy_bits[0])
-                       usb_enable_root_hub_irq(hdev->bus);
-
 loop_autopm:
                /* Allow autosuspend if we're not going to run again */
                if (list_empty(&hub->event_list))
@@ -2890,7 +2967,13 @@ loop:
 
 static int hub_thread(void *__unused)
 {
+       /* khubd needs to be freezable to avoid intefering with USB-PERSIST
+        * port handover.  Otherwise it might see that a full-speed device
+        * was gone before the EHCI controller had handed its port over to
+        * the companion full-speed controller.
+        */
        set_freezable();
+
        do {
                hub_events();
                wait_event_freezable(khubd_wait,
@@ -2959,16 +3042,36 @@ void usb_hub_cleanup(void)
        usb_deregister(&hub_driver);
 } /* usb_hub_cleanup() */
 
-static int config_descriptors_changed(struct usb_device *udev)
+static int descriptors_changed(struct usb_device *udev,
+               struct usb_device_descriptor *old_device_descriptor)
 {
-       unsigned                        index;
-       unsigned                        len = 0;
-       struct usb_config_descriptor    *buf;
+       int             changed = 0;
+       unsigned        index;
+       unsigned        serial_len = 0;
+       unsigned        len;
+       unsigned        old_length;
+       int             length;
+       char            *buf;
+
+       if (memcmp(&udev->descriptor, old_device_descriptor,
+                       sizeof(*old_device_descriptor)) != 0)
+               return 1;
 
+       /* Since the idVendor, idProduct, and bcdDevice values in the
+        * device descriptor haven't changed, we will assume the
+        * Manufacturer and Product strings haven't changed either.
+        * But the SerialNumber string could be different (e.g., a
+        * different flash card of the same brand).
+        */
+       if (udev->serial)
+               serial_len = strlen(udev->serial) + 1;
+
+       len = serial_len;
        for (index = 0; index < udev->descriptor.bNumConfigurations; index++) {
-               if (len < le16_to_cpu(udev->config[index].desc.wTotalLength))
-                       len = le16_to_cpu(udev->config[index].desc.wTotalLength);
+               old_length = le16_to_cpu(udev->config[index].desc.wTotalLength);
+               len = max(len, old_length);
        }
+
        buf = kmalloc(len, GFP_NOIO);
        if (buf == NULL) {
                dev_err(&udev->dev, "no mem to re-read configs after reset\n");
@@ -2976,25 +3079,41 @@ static int config_descriptors_changed(struct usb_device *udev)
                return 1;
        }
        for (index = 0; index < udev->descriptor.bNumConfigurations; index++) {
-               int length;
-               int old_length = le16_to_cpu(udev->config[index].desc.wTotalLength);
-
+               old_length = le16_to_cpu(udev->config[index].desc.wTotalLength);
                length = usb_get_descriptor(udev, USB_DT_CONFIG, index, buf,
                                old_length);
-               if (length < old_length) {
+               if (length != old_length) {
                        dev_dbg(&udev->dev, "config index %d, error %d\n",
                                        index, length);
+                       changed = 1;
                        break;
                }
                if (memcmp (buf, udev->rawdescriptors[index], old_length)
                                != 0) {
                        dev_dbg(&udev->dev, "config index %d changed (#%d)\n",
-                               index, buf->bConfigurationValue);
+                               index,
+                               ((struct usb_config_descriptor *) buf)->
+                                       bConfigurationValue);
+                       changed = 1;
                        break;
                }
        }
+
+       if (!changed && serial_len) {
+               length = usb_string(udev, udev->descriptor.iSerialNumber,
+                               buf, serial_len);
+               if (length + 1 != serial_len) {
+                       dev_dbg(&udev->dev, "serial string error %d\n",
+                                       length);
+                       changed = 1;
+               } else if (memcmp(buf, udev->serial, length) != 0) {
+                       dev_dbg(&udev->dev, "serial string changed\n");
+                       changed = 1;
+               }
+       }
+
        kfree(buf);
-       return index != udev->descriptor.bNumConfigurations;
+       return changed;
 }
 
 /**
@@ -3044,7 +3163,7 @@ int usb_reset_device(struct usb_device *udev)
 
        if (!parent_hdev) {
                /* this requires hcd-specific logic; see OHCI hc_restart() */
-               dev_dbg(&udev->dev, "%s for root hub!\n", __FUNCTION__);
+               dev_dbg(&udev->dev, "%s for root hub!\n", __func__);
                return -EISDIR;
        }
        parent_hub = hdev_to_hub(parent_hdev);
@@ -3054,21 +3173,18 @@ int usb_reset_device(struct usb_device *udev)
 
                /* ep0 maxpacket size may change; let the HCD know about it.
                 * Other endpoints will be handled by re-enumeration. */
-               ep0_reinit(udev);
+               usb_ep0_reinit(udev);
                ret = hub_port_init(parent_hub, udev, port1, i);
                if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV)
                        break;
        }
        clear_bit(port1, parent_hub->busy_bits);
-       if (!parent_hdev->parent && !parent_hub->busy_bits[0])
-               usb_enable_root_hub_irq(parent_hdev->bus);
 
        if (ret < 0)
                goto re_enumerate;
  
        /* Device might have changed firmware (DFU or similar) */
-       if (memcmp(&udev->descriptor, &descriptor, sizeof descriptor)
-                       || config_descriptors_changed (udev)) {
+       if (descriptors_changed(udev, &descriptor)) {
                dev_info(&udev->dev, "device firmware changed\n");
                udev->descriptor = descriptor;  /* for disconnect() calls */
                goto re_enumerate;
index 1551aed65e05c7dcc585e07883cd216dd8ed7718..2a116ce53c9b8e441f942b5b1b386a06a90cf738 100644 (file)
  */
 #define USB_PORT_FEAT_CONNECTION       0
 #define USB_PORT_FEAT_ENABLE           1
-#define USB_PORT_FEAT_SUSPEND          2
+#define USB_PORT_FEAT_SUSPEND          2       /* L2 suspend */
 #define USB_PORT_FEAT_OVER_CURRENT     3
 #define USB_PORT_FEAT_RESET            4
+#define USB_PORT_FEAT_L1               5       /* L1 suspend */
 #define USB_PORT_FEAT_POWER            8
 #define USB_PORT_FEAT_LOWSPEED         9
 #define USB_PORT_FEAT_HIGHSPEED                10
@@ -54,6 +55,7 @@
 #define USB_PORT_FEAT_C_RESET          20
 #define USB_PORT_FEAT_TEST              21
 #define USB_PORT_FEAT_INDICATOR         22
+#define USB_PORT_FEAT_C_PORT_L1         23
 
 /*
  * Hub Status and Hub Change results
@@ -73,7 +75,8 @@ struct usb_port_status {
 #define USB_PORT_STAT_SUSPEND          0x0004
 #define USB_PORT_STAT_OVERCURRENT      0x0008
 #define USB_PORT_STAT_RESET            0x0010
-/* bits 5 to 7 are reserved */
+#define USB_PORT_STAT_L1               0x0020
+/* bits 6 to 7 are reserved */
 #define USB_PORT_STAT_POWER            0x0100
 #define USB_PORT_STAT_LOW_SPEED                0x0200
 #define USB_PORT_STAT_HIGH_SPEED        0x0400
@@ -91,6 +94,7 @@ struct usb_port_status {
 #define USB_PORT_STAT_C_SUSPEND                0x0004
 #define USB_PORT_STAT_C_OVERCURRENT    0x0008
 #define USB_PORT_STAT_C_RESET          0x0010
+#define USB_PORT_STAT_C_L1             0x0020
 
 /*
  * wHubCharacteristics (masks)
@@ -191,5 +195,6 @@ struct usb_tt_clear {
 };
 
 extern void usb_hub_tt_clear_buffer(struct usb_device *dev, int pipe);
+extern void usb_ep0_reinit(struct usb_device *);
 
 #endif /* __LINUX_HUB_H */
index 83a373e9cc3624c66f09bac2c5383221e0eef8d2..8607846e3c3f7bf1f2998953b61517756a3a4c14 100644 (file)
@@ -463,13 +463,13 @@ static int usbfs_fill_super(struct super_block *sb, void *data, int silent)
        inode = usbfs_get_inode(sb, S_IFDIR | 0755, 0);
 
        if (!inode) {
-               dbg("%s: could not get inode!",__FUNCTION__);
+               dbg("%s: could not get inode!",__func__);
                return -ENOMEM;
        }
 
        root = d_alloc_root(inode);
        if (!root) {
-               dbg("%s: could not get root dentry!",__FUNCTION__);
+               dbg("%s: could not get root dentry!",__func__);
                iput(inode);
                return -ENOMEM;
        }
index c311f67b7f0824dba591b50d4b21f943827349b0..e819e5359d5765e1d2e1540432a6aa4981fa5d0a 100644 (file)
@@ -312,7 +312,7 @@ static void sg_complete(struct urb *urb)
                                    retval != -EBUSY)
                                        dev_err(&io->dev->dev,
                                                "%s, unlink --> %d\n",
-                                               __FUNCTION__, retval);
+                                               __func__, retval);
                        } else if (urb == io->urbs [i])
                                found = 1;
                }
@@ -550,7 +550,7 @@ void usb_sg_wait(struct usb_sg_request *io)
                        io->urbs[i]->dev = NULL;
                        io->urbs[i]->status = retval;
                        dev_dbg(&io->dev->dev, "%s, submit --> %d\n",
-                               __FUNCTION__, retval);
+                               __func__, retval);
                        usb_sg_cancel(io);
                }
                spin_lock_irq(&io->lock);
@@ -600,7 +600,7 @@ void usb_sg_cancel(struct usb_sg_request *io)
                        retval = usb_unlink_urb(io->urbs [i]);
                        if (retval != -EINPROGRESS && retval != -EBUSY)
                                dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
-                                       __FUNCTION__, retval);
+                                       __func__, retval);
                }
                spin_lock(&io->lock);
        }
@@ -784,7 +784,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
        if (size <= 0 || !buf || !index)
                return -EINVAL;
        buf[0] = 0;
-       tbuf = kmalloc(256, GFP_KERNEL);
+       tbuf = kmalloc(256, GFP_NOIO);
        if (!tbuf)
                return -ENOMEM;
 
@@ -1068,7 +1068,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
 {
        int i;
 
-       dev_dbg(&dev->dev, "%s nuking %s URBs\n", __FUNCTION__,
+       dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
                skip_ep0 ? "non-ep0" : "all");
        for (i = skip_ep0; i < 16; ++i) {
                usb_disable_endpoint(dev, i);
@@ -1089,8 +1089,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
                                continue;
                        dev_dbg(&dev->dev, "unregistering interface %s\n",
                                interface->dev.bus_id);
-                       usb_remove_sysfs_intf_files(interface);
                        device_del(&interface->dev);
+                       usb_remove_sysfs_intf_files(interface);
                }
 
                /* Now that the interfaces are unbound, nobody should
@@ -1231,7 +1231,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
         */
 
        /* prevent submissions using previous endpoint settings */
-       if (iface->cur_altsetting != alt && device_is_registered(&iface->dev))
+       if (iface->cur_altsetting != alt)
                usb_remove_sysfs_intf_files(iface);
        usb_disable_interface(dev, iface);
 
@@ -1330,8 +1330,7 @@ int usb_reset_configuration(struct usb_device *dev)
                struct usb_interface *intf = config->interface[i];
                struct usb_host_interface *alt;
 
-               if (device_is_registered(&intf->dev))
-                       usb_remove_sysfs_intf_files(intf);
+               usb_remove_sysfs_intf_files(intf);
                alt = usb_altnum_to_altsetting(intf, 0);
 
                /* No altsetting 0?  We'll assume the first altsetting.
index dfc5418ea10c0a11654cb59d392bb535be0aad0b..2e201939029061e01dabc91b64f73ee30f6afb90 100644 (file)
@@ -97,4 +97,18 @@ void usb_detect_quirks(struct usb_device *udev)
        if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
                udev->autosuspend_disabled = 1;
 #endif
+
+       /* For the present, all devices default to USB-PERSIST enabled */
+#if 0          /* was: #ifdef CONFIG_PM */
+       /* Hubs are automatically enabled for USB-PERSIST */
+       if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
+               udev->persist_enabled = 1;
+
+#else
+       /* In the absence of PM, we can safely enable USB-PERSIST
+        * for all devices.  It will affect things like hub resets
+        * and EMF-related port disables.
+        */
+       udev->persist_enabled = 1;
+#endif /* CONFIG_PM */
 }
index a37ccbd1e007c478022ff02b22beeef3fd81976f..5b20a60de8ba9900bde0c51e7a7e8cb49590e84b 100644 (file)
@@ -180,11 +180,9 @@ show_urbnum(struct device *dev, struct device_attribute *attr, char *buf)
 static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL);
 
 
-#if defined(CONFIG_USB_PERSIST) || defined(CONFIG_USB_SUSPEND)
-static const char power_group[] = "power";
-#endif
+#ifdef CONFIG_PM
 
-#ifdef CONFIG_USB_PERSIST
+static const char power_group[] = "power";
 
 static ssize_t
 show_persist(struct device *dev, struct device_attribute *attr, char *buf)
@@ -222,12 +220,13 @@ static int add_persist_attributes(struct device *dev)
        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);
+               /* Hubs are automatically enabled for USB_PERSIST,
+                * no point in creating the attribute file.
+                */
+               if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
+                       rc = sysfs_add_file_to_group(&dev->kobj,
+                                       &dev_attr_persist.attr,
+                                       power_group);
        }
        return rc;
 }
@@ -238,13 +237,12 @@ static void remove_persist_attributes(struct device *dev)
                        &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 */
+#endif /* CONFIG_PM */
 
 #ifdef CONFIG_USB_SUSPEND
 
index 9d7e63292c01175647503b65e821cdd3b94dc381..c0b1ae25ae2a8923cf463bd670f3873acaf87102 100644 (file)
@@ -334,7 +334,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
                dev_dbg(&dev->dev,
                        "bogus endpoint ep%d%s in %s (bad maxpacket %d)\n",
                        usb_endpoint_num(&ep->desc), is_out ? "out" : "in",
-                       __FUNCTION__, max);
+                       __func__, max);
                return -EMSGSIZE;
        }
 
@@ -589,6 +589,30 @@ void usb_kill_anchored_urbs(struct usb_anchor *anchor)
 }
 EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs);
 
+/**
+ * usb_unlink_anchored_urbs - asynchronously cancel transfer requests en masse
+ * @anchor: anchor the requests are bound to
+ *
+ * this allows all outstanding URBs to be unlinked starting
+ * from the back of the queue. This function is asynchronous.
+ * The unlinking is just tiggered. It may happen after this
+ * function has returned.
+ */
+void usb_unlink_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);
+               /* this will unanchor the URB */
+               usb_unlink_urb(victim);
+       }
+       spin_unlock_irq(&anchor->lock);
+}
+EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs);
+
 /**
  * usb_wait_anchor_empty_timeout - wait for an anchor to be unused
  * @anchor: the anchor you want to become unused
index 2375194a9d43a7d9a6440f097e951d2f8b27f56d..1bf8ccb9c58dab72f243ff82168fda9cc427f6cc 100644 (file)
@@ -114,13 +114,11 @@ 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 d681bb27fa5815a10cd49cfda60812e7f1cd2bd8..f7b54651dd42eb77ccab5a29bae693c4570c6a7d 100644 (file)
@@ -44,8 +44,8 @@ menuconfig USB_GADGET
 if USB_GADGET
 
 config USB_GADGET_DEBUG
-       boolean "Debugging messages"
-       depends on USB_GADGET && DEBUG_KERNEL && EXPERIMENTAL
+       boolean "Debugging messages (DEVELOPMENT)"
+       depends on USB_GADGET && DEBUG_KERNEL
        help
           Many controller and gadget drivers will print some debugging
           messages if you use this option to ask for those messages.
@@ -58,7 +58,7 @@ config USB_GADGET_DEBUG
           production build.
 
 config USB_GADGET_DEBUG_FILES
-       boolean "Debugging information files"
+       boolean "Debugging information files (DEVELOPMENT)"
        depends on USB_GADGET && PROC_FS
        help
           Some of the drivers in the "gadget" framework can expose
@@ -69,7 +69,7 @@ config USB_GADGET_DEBUG_FILES
           here.  If in doubt, or to conserve kernel memory, say "N".
 
 config USB_GADGET_DEBUG_FS
-       boolean "Debugging information files in debugfs"
+       boolean "Debugging information files in debugfs (DEVELOPMENT)"
        depends on USB_GADGET && DEBUG_FS
        help
           Some of the drivers in the "gadget" framework can expose
@@ -337,7 +337,7 @@ config USB_AT91
 
 config USB_GADGET_DUMMY_HCD
        boolean "Dummy HCD (DEVELOPMENT)"
-       depends on (USB=y || (USB=m && USB_GADGET=m)) && EXPERIMENTAL
+       depends on USB=y || (USB=m && USB_GADGET=m)
        select USB_GADGET_DUALSPEED
        help
          This host controller driver emulates USB, looping all data transfer
@@ -404,7 +404,6 @@ choice
 
 config USB_ZERO
        tristate "Gadget Zero (DEVELOPMENT)"
-       depends on EXPERIMENTAL
        help
          Gadget Zero is a two-configuration device.  It either sinks and
          sources bulk data; or it loops back a configurable number of
@@ -468,8 +467,8 @@ config USB_ETH
          dynamically linked module called "g_ether".
 
 config USB_ETH_RNDIS
-       bool "RNDIS support (EXPERIMENTAL)"
-       depends on USB_ETH && EXPERIMENTAL
+       bool "RNDIS support"
+       depends on USB_ETH
        default y
        help
           Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
@@ -495,6 +494,9 @@ config USB_GADGETFS
          All endpoints, transfer speeds, and transfer types supported by
          the hardware are available, through read() and write() calls.
 
+         Currently, this option is still labelled as EXPERIMENTAL because
+         of existing race conditions in the underlying in-kernel AIO core.
+
          Say "y" to link the driver statically, or "m" to build a
          dynamically linked module called "gadgetfs".
 
index b663f23f2642ab5a157039e98c1f92b678927ee1..fc6f3483be4473c25e21620a8be1a84bb5e9ea79 100644 (file)
@@ -3248,6 +3248,8 @@ static int udc_pci_probe(
 
        /* pci setup */
        if (pci_enable_device(pdev) < 0) {
+               kfree(dev);
+               dev = 0;
                retval = -ENODEV;
                goto finished;
        }
@@ -3259,6 +3261,8 @@ static int udc_pci_probe(
 
        if (!request_mem_region(resource, len, name)) {
                dev_dbg(&pdev->dev, "pci device used already\n");
+               kfree(dev);
+               dev = 0;
                retval = -EBUSY;
                goto finished;
        }
@@ -3267,18 +3271,24 @@ static int udc_pci_probe(
        dev->virt_addr = ioremap_nocache(resource, len);
        if (dev->virt_addr == NULL) {
                dev_dbg(&pdev->dev, "start address cannot be mapped\n");
+               kfree(dev);
+               dev = 0;
                retval = -EFAULT;
                goto finished;
        }
 
        if (!pdev->irq) {
                dev_err(&dev->pdev->dev, "irq not set\n");
+               kfree(dev);
+               dev = 0;
                retval = -ENODEV;
                goto finished;
        }
 
        if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
                dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq);
+               kfree(dev);
+               dev = 0;
                retval = -EBUSY;
                goto finished;
        }
index fd15ced899d8a3f9214590541a6a967327131690..9b913afb2e6dab7beb727a7400516247b4863a59 100644 (file)
@@ -389,6 +389,7 @@ static int write_fifo(struct at91_ep *ep, struct at91_request *req)
        u32             csr = __raw_readl(creg);
        u8 __iomem      *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0));
        unsigned        total, count, is_last;
+       u8              *buf;
 
        /*
         * TODO: allow for writing two packets to the fifo ... that'll
@@ -413,6 +414,8 @@ static int write_fifo(struct at91_ep *ep, struct at91_request *req)
                        return 0;
        }
 
+       buf = req->req.buf + req->req.actual;
+       prefetch(buf);
        total = req->req.length - req->req.actual;
        if (ep->ep.maxpacket < total) {
                count = ep->ep.maxpacket;
@@ -435,7 +438,7 @@ static int write_fifo(struct at91_ep *ep, struct at91_request *req)
         * recover when the actual bytecount matters (e.g. for USB Test
         * and Measurement Class devices).
         */
-       __raw_writesb(dreg, req->req.buf + req->req.actual, count);
+       __raw_writesb(dreg, buf, count);
        csr &= ~SET_FX;
        csr |= CLR_FX | AT91_UDP_TXPKTRDY;
        __raw_writel(csr, creg);
@@ -457,7 +460,7 @@ static void nuke(struct at91_ep *ep, int status)
        if (list_empty(&ep->queue))
                return;
 
-       VDBG("%s %s\n", __FUNCTION__, ep->ep.name);
+       VDBG("%s %s\n", __func__, ep->ep.name);
        while (!list_empty(&ep->queue)) {
                req = list_entry(ep->queue.next, struct at91_request, queue);
                done(ep, req, status);
@@ -792,7 +795,7 @@ static int at91_wakeup(struct usb_gadget *gadget)
        int             status = -EINVAL;
        unsigned long   flags;
 
-       DBG("%s\n", __FUNCTION__ );
+       DBG("%s\n", __func__ );
        local_irq_save(flags);
 
        if (!udc->clocked || !udc->suspended)
index cbe44535c0f0a4520af8b004ff84bad0264e1008..66293105d136646d3e739ef330cde96ff112cec3 100644 (file)
@@ -365,16 +365,14 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
                case USB_SPEED_HIGH:
                        if (max == 512)
                                break;
-                       /* conserve return statements */
-               default:
-                       switch (max) {
-                       case 8: case 16: case 32: case 64:
+                       goto done;
+               case USB_SPEED_FULL:
+                       if (max == 8 || max == 16 || max == 32 || max == 64)
                                /* we'll fake any legal size */
                                break;
-                       default:
-               case USB_SPEED_LOW:
-                               goto done;
-                       }
+                       /* save a return statement */
+               default:
+                       goto done;
                }
                break;
        case USB_ENDPOINT_XFER_INT:
@@ -894,13 +892,12 @@ static int dummy_udc_suspend (struct platform_device *pdev, pm_message_t state)
 {
        struct dummy    *dum = platform_get_drvdata(pdev);
 
-       dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
+       dev_dbg (&pdev->dev, "%s\n", __func__);
        spin_lock_irq (&dum->lock);
        dum->udc_suspended = 1;
        set_link_state (dum);
        spin_unlock_irq (&dum->lock);
 
-       pdev->dev.power.power_state = state;
        usb_hcd_poll_rh_status (dummy_to_hcd (dum));
        return 0;
 }
@@ -909,13 +906,12 @@ static int dummy_udc_resume (struct platform_device *pdev)
 {
        struct dummy    *dum = platform_get_drvdata(pdev);
 
-       dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
+       dev_dbg (&pdev->dev, "%s\n", __func__);
        spin_lock_irq (&dum->lock);
        dum->udc_suspended = 0;
        set_link_state (dum);
        spin_unlock_irq (&dum->lock);
 
-       pdev->dev.power.power_state = PMSG_ON;
        usb_hcd_poll_rh_status (dummy_to_hcd (dum));
        return 0;
 }
@@ -1711,7 +1707,7 @@ static int dummy_bus_suspend (struct usb_hcd *hcd)
 {
        struct dummy *dum = hcd_to_dummy (hcd);
 
-       dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
+       dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
 
        spin_lock_irq (&dum->lock);
        dum->rh_state = DUMMY_RH_SUSPENDED;
@@ -1726,7 +1722,7 @@ static int dummy_bus_resume (struct usb_hcd *hcd)
        struct dummy *dum = hcd_to_dummy (hcd);
        int rc = 0;
 
-       dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
+       dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
 
        spin_lock_irq (&dum->lock);
        if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
@@ -1900,7 +1896,7 @@ static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state)
        struct dummy            *dum;
        int                     rc = 0;
 
-       dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
+       dev_dbg (&pdev->dev, "%s\n", __func__);
 
        hcd = platform_get_drvdata (pdev);
        dum = hcd_to_dummy (hcd);
@@ -1916,7 +1912,7 @@ static int dummy_hcd_resume (struct platform_device *pdev)
 {
        struct usb_hcd          *hcd;
 
-       dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
+       dev_dbg (&pdev->dev, "%s\n", __func__);
 
        hcd = platform_get_drvdata (pdev);
        set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
@@ -1937,69 +1933,57 @@ static struct platform_driver dummy_hcd_driver = {
 
 /*-------------------------------------------------------------------------*/
 
-/* These don't need to do anything because the pdev structures are
- * statically allocated. */
-static void
-dummy_udc_release (struct device *dev) {}
-
-static void
-dummy_hcd_release (struct device *dev) {}
-
-static struct platform_device          the_udc_pdev = {
-       .name           = (char *) gadget_name,
-       .id             = -1,
-       .dev            = {
-               .release        = dummy_udc_release,
-       },
-};
-
-static struct platform_device          the_hcd_pdev = {
-       .name           = (char *) driver_name,
-       .id             = -1,
-       .dev            = {
-               .release        = dummy_hcd_release,
-       },
-};
+static struct platform_device *the_udc_pdev;
+static struct platform_device *the_hcd_pdev;
 
 static int __init init (void)
 {
-       int     retval;
+       int     retval = -ENOMEM;
 
        if (usb_disabled ())
                return -ENODEV;
 
-       retval = platform_driver_register (&dummy_hcd_driver);
-       if (retval < 0)
+       the_hcd_pdev = platform_device_alloc(driver_name, -1);
+       if (!the_hcd_pdev)
                return retval;
+       the_udc_pdev = platform_device_alloc(gadget_name, -1);
+       if (!the_udc_pdev)
+               goto err_alloc_udc;
 
-       retval = platform_driver_register (&dummy_udc_driver);
+       retval = platform_driver_register(&dummy_hcd_driver);
+       if (retval < 0)
+               goto err_register_hcd_driver;
+       retval = platform_driver_register(&dummy_udc_driver);
        if (retval < 0)
                goto err_register_udc_driver;
 
-       retval = platform_device_register (&the_hcd_pdev);
+       retval = platform_device_add(the_hcd_pdev);
        if (retval < 0)
-               goto err_register_hcd;
-
-       retval = platform_device_register (&the_udc_pdev);
+               goto err_add_hcd;
+       retval = platform_device_add(the_udc_pdev);
        if (retval < 0)
-               goto err_register_udc;
+               goto err_add_udc;
        return retval;
 
-err_register_udc:
-       platform_device_unregister (&the_hcd_pdev);
-err_register_hcd:
-       platform_driver_unregister (&dummy_udc_driver);
+err_add_udc:
+       platform_device_del(the_hcd_pdev);
+err_add_hcd:
+       platform_driver_unregister(&dummy_udc_driver);
 err_register_udc_driver:
-       platform_driver_unregister (&dummy_hcd_driver);
+       platform_driver_unregister(&dummy_hcd_driver);
+err_register_hcd_driver:
+       platform_device_put(the_udc_pdev);
+err_alloc_udc:
+       platform_device_put(the_hcd_pdev);
        return retval;
 }
 module_init (init);
 
 static void __exit cleanup (void)
 {
-       platform_device_unregister (&the_udc_pdev);
-       platform_device_unregister (&the_hcd_pdev);
-       platform_driver_unregister (&dummy_udc_driver);
-       platform_driver_unregister (&dummy_hcd_driver);
+       platform_device_unregister(the_udc_pdev);
+       platform_device_unregister(the_hcd_pdev);
+       platform_driver_unregister(&dummy_udc_driver);
+       platform_driver_unregister(&dummy_hcd_driver);
 }
 module_exit (cleanup);
index f9d07108bc3048c721efbd11a0a46ff0dceb3b4f..8bdad221fa91adc094c45ee1dea65cb0677c84e2 100644 (file)
 
 
 /* we must assign addresses for configurable endpoints (like net2280) */
-static __devinitdata unsigned epnum;
+static __initdata unsigned epnum;
 
 // #define MANY_ENDPOINTS
 #ifdef MANY_ENDPOINTS
 /* more than 15 configurable endpoints */
-static __devinitdata unsigned in_epnum;
+static __initdata unsigned in_epnum;
 #endif
 
 
@@ -59,7 +59,7 @@ static __devinitdata unsigned in_epnum;
  * NOTE:  each endpoint is unidirectional, as specified by its USB
  * descriptor; and isn't specific to a configuration or altsetting.
  */
-static int __devinit
+static int __init
 ep_matches (
        struct usb_gadget               *gadget,
        struct usb_ep                   *ep,
@@ -186,7 +186,7 @@ ep_matches (
        return 1;
 }
 
-static struct usb_ep * __devinit
+static struct usb_ep * __init
 find_ep (struct usb_gadget *gadget, const char *name)
 {
        struct usb_ep   *ep;
@@ -228,7 +228,7 @@ find_ep (struct usb_gadget *gadget, const char *name)
  *
  * On failure, this returns a null endpoint descriptor.
  */
-struct usb_ep * __devinit usb_ep_autoconfig (
+struct usb_ep * __init usb_ep_autoconfig (
        struct usb_gadget               *gadget,
        struct usb_endpoint_descriptor  *desc
 )
@@ -295,7 +295,7 @@ struct usb_ep * __devinit usb_ep_autoconfig (
  * state such as ep->driver_data and the record of assigned endpoints
  * used by usb_ep_autoconfig().
  */
-void __devinit usb_ep_autoconfig_reset (struct usb_gadget *gadget)
+void __init usb_ep_autoconfig_reset (struct usb_gadget *gadget)
 {
        struct usb_ep   *ep;
 
index e99872308144d3f148f029ae7c9a5672eae9c827..bb93bdd7659315da5707b2ae11e73aecac979996 100644 (file)
@@ -1102,7 +1102,7 @@ static void eth_reset_config (struct eth_dev *dev)
        if (dev->config == 0)
                return;
 
-       DEBUG (dev, "%s\n", __FUNCTION__);
+       DEBUG (dev, "%s\n", __func__);
 
        netif_stop_queue (dev->net);
        netif_carrier_off (dev->net);
@@ -1263,7 +1263,7 @@ static void issue_start_status (struct eth_dev *dev)
        struct usb_cdc_notification     *event;
        int                             value;
 
-       DEBUG (dev, "%s, flush old status first\n", __FUNCTION__);
+       DEBUG (dev, "%s, flush old status first\n", __func__);
 
        /* flush old status
         *
@@ -1329,7 +1329,7 @@ static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req)
        spin_lock(&dev->lock);
        status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf);
        if (status < 0)
-               ERROR(dev, "%s: rndis parse error %d\n", __FUNCTION__, status);
+               ERROR(dev, "%s: rndis parse error %d\n", __func__, status);
        spin_unlock(&dev->lock);
 }
 
@@ -2113,7 +2113,7 @@ static int rndis_control_ack (struct net_device *net)
 
 static void eth_start (struct eth_dev *dev, gfp_t gfp_flags)
 {
-       DEBUG (dev, "%s\n", __FUNCTION__);
+       DEBUG (dev, "%s\n", __func__);
 
        /* fill the rx queue */
        rx_fill (dev, gfp_flags);
@@ -2133,7 +2133,7 @@ static int eth_open (struct net_device *net)
 {
        struct eth_dev          *dev = netdev_priv(net);
 
-       DEBUG (dev, "%s\n", __FUNCTION__);
+       DEBUG (dev, "%s\n", __func__);
        if (netif_carrier_ok (dev->net))
                eth_start (dev, GFP_KERNEL);
        return 0;
@@ -2143,7 +2143,7 @@ static int eth_stop (struct net_device *net)
 {
        struct eth_dev          *dev = netdev_priv(net);
 
-       VDEBUG (dev, "%s\n", __FUNCTION__);
+       VDEBUG (dev, "%s\n", __func__);
        netif_stop_queue (net);
 
        DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
@@ -2229,7 +2229,7 @@ eth_unbind (struct usb_gadget *gadget)
        set_gadget_data (gadget, NULL);
 }
 
-static u8 __devinit nibble (unsigned char c)
+static u8 __init nibble (unsigned char c)
 {
        if (likely (isdigit (c)))
                return c - '0';
@@ -2239,7 +2239,7 @@ static u8 __devinit nibble (unsigned char c)
        return 0;
 }
 
-static int __devinit get_ether_addr(const char *str, u8 *dev_addr)
+static int __init get_ether_addr(const char *str, u8 *dev_addr)
 {
        if (str) {
                unsigned        i;
@@ -2260,7 +2260,7 @@ static int __devinit get_ether_addr(const char *str, u8 *dev_addr)
        return 1;
 }
 
-static int __devinit
+static int __init
 eth_bind (struct usb_gadget *gadget)
 {
        struct eth_dev          *dev;
index 017a196d041fe58d9617aa2c52148c9f3b258e64..bf3f946fd45544e04cc1549ab68d71f2f2b8f0f2 100644 (file)
@@ -644,7 +644,7 @@ struct fsg_dev {
 
        unsigned long           atomic_bitflags;
 #define REGISTERED             0
-#define CLEAR_BULK_HALTS       1
+#define IGNORE_BULK_OUT                1
 #define SUSPENDED              2
 
        struct usb_ep           *bulk_in;
@@ -1104,7 +1104,7 @@ static void ep0_complete(struct usb_ep *ep, struct usb_request *req)
        if (req->actual > 0)
                dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);
        if (req->status || req->actual != req->length)
-               DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,
+               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
                                req->status, req->actual, req->length);
        if (req->status == -ECONNRESET)         // Request was cancelled
                usb_ep_fifo_flush(ep);
@@ -1125,7 +1125,7 @@ static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
        struct fsg_buffhd       *bh = req->context;
 
        if (req->status || req->actual != req->length)
-               DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,
+               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
                                req->status, req->actual, req->length);
        if (req->status == -ECONNRESET)         // Request was cancelled
                usb_ep_fifo_flush(ep);
@@ -1146,7 +1146,7 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
 
        dump_msg(fsg, "bulk-out", req->buf, req->actual);
        if (req->status || req->actual != bh->bulk_out_intended_length)
-               DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,
+               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
                                req->status, req->actual,
                                bh->bulk_out_intended_length);
        if (req->status == -ECONNRESET)         // Request was cancelled
@@ -1169,7 +1169,7 @@ static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
        struct fsg_buffhd       *bh = req->context;
 
        if (req->status || req->actual != req->length)
-               DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,
+               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
                                req->status, req->actual, req->length);
        if (req->status == -ECONNRESET)         // Request was cancelled
                usb_ep_fifo_flush(ep);
@@ -2936,8 +2936,8 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
        struct usb_request      *req = bh->outreq;
        struct bulk_cb_wrap     *cbw = req->buf;
 
-       /* Was this a real packet? */
-       if (req->status)
+       /* Was this a real packet?  Should it be ignored? */
+       if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
                return -EINVAL;
 
        /* Is the CBW valid? */
@@ -2948,13 +2948,17 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
                                req->actual,
                                le32_to_cpu(cbw->Signature));
 
-               /* The Bulk-only spec says we MUST stall the bulk pipes!
-                * If we want to avoid stalls, set a flag so that we will
-                * clear the endpoint halts at the next reset. */
-               if (!mod_data.can_stall)
-                       set_bit(CLEAR_BULK_HALTS, &fsg->atomic_bitflags);
-               fsg_set_halt(fsg, fsg->bulk_out);
+               /* The Bulk-only spec says we MUST stall the IN endpoint
+                * (6.6.1), so it's unavoidable.  It also says we must
+                * retain this state until the next reset, but there's
+                * no way to tell the controller driver it should ignore
+                * Clear-Feature(HALT) requests.
+                *
+                * We aren't required to halt the OUT endpoint; instead
+                * we can simply accept and discard any data received
+                * until the next reset. */
                halt_bulk_in_endpoint(fsg);
+               set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
                return -EINVAL;
        }
 
@@ -3140,6 +3144,7 @@ reset:
                goto reset;
        fsg->bulk_out_enabled = 1;
        fsg->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
+       clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
 
        if (transport_is_cbi()) {
                d = ep_desc(fsg->gadget, &fs_intr_in_desc, &hs_intr_in_desc);
@@ -3321,11 +3326,8 @@ static void handle_exception(struct fsg_dev *fsg)
                /* In case we were forced against our will to halt a
                 * bulk endpoint, clear the halt now.  (The SuperH UDC
                 * requires this.) */
-               if (test_and_clear_bit(CLEAR_BULK_HALTS,
-                               &fsg->atomic_bitflags)) {
+               if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
                        usb_ep_clear_halt(fsg->bulk_in);
-                       usb_ep_clear_halt(fsg->bulk_out);
-               }
 
                if (transport_is_bbb()) {
                        if (fsg->ep0_req_tag == exception_req_tag)
index 254012ad2b91b68b344340b773b7b413374f0469..651b82701394c89ff0dbbbcea532354fb5d4dc62 100644 (file)
@@ -773,11 +773,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
        /* catch various bogus parameters */
        if (!_req || !req->req.complete || !req->req.buf
                        || !list_empty(&req->queue)) {
-               VDBG("%s, bad params\n", __FUNCTION__);
+               VDBG("%s, bad params\n", __func__);
                return -EINVAL;
        }
        if (unlikely(!_ep || !ep->desc)) {
-               VDBG("%s, bad ep\n", __FUNCTION__);
+               VDBG("%s, bad ep\n", __func__);
                return -EINVAL;
        }
        if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
index 9fb0b1ec85266322054422db511f337e53459efd..98b1483ef6a511459e44b2b8f17ada3329570ec1 100644 (file)
@@ -512,7 +512,7 @@ struct fsl_udc {
 
 #ifdef DEBUG
 #define DBG(fmt, args...)      printk(KERN_DEBUG "[%s]  " fmt "\n", \
-                               __FUNCTION__, ## args)
+                               __func__, ## args)
 #else
 #define DBG(fmt, args...)      do{}while(0)
 #endif
index 5b42ccd0035fee4364d4d8021c0e72814015775a..ff3a8513e64dbbcdc8d15f5d944693317acdb459 100644 (file)
@@ -1149,7 +1149,7 @@ fail:
 /*
  * Creates an output endpoint, and initializes output ports.
  */
-static int __devinit gmidi_bind(struct usb_gadget *gadget)
+static int __init gmidi_bind(struct usb_gadget *gadget)
 {
        struct gmidi_device *dev;
        struct usb_ep *in_ep, *out_ep;
index d3e702576de6e23c7aca952bc40cc3288de1dd59..64a592cbbe7b7f4aa3b3236ebd165ce726cdb6cb 100644 (file)
@@ -692,7 +692,7 @@ static void abort_dma(struct goku_ep *ep, int status)
        req->req.actual = (curr - req->req.dma) + 1;
        req->req.status = status;
 
-       VDBG(ep->dev, "%s %s %s %d/%d\n", __FUNCTION__, ep->ep.name,
+       VDBG(ep->dev, "%s %s %s %d/%d\n", __func__, ep->ep.name,
                ep->is_in ? "IN" : "OUT",
                req->req.actual, req->req.length);
 
@@ -826,7 +826,7 @@ static int goku_dequeue(struct usb_ep *_ep, struct usb_request *_req)
        if (dev->ep0state == EP0_SUSPEND)
                return -EBUSY;
 
-       VDBG(dev, "%s %s %s %s %p\n", __FUNCTION__, _ep->name,
+       VDBG(dev, "%s %s %s %s %p\n", __func__, _ep->name,
                ep->is_in ? "IN" : "OUT",
                ep->dma ? "dma" : "pio",
                _req);
@@ -898,7 +898,7 @@ static int goku_set_halt(struct usb_ep *_ep, int value)
 
        /* don't change EPxSTATUS_EP_INVALID to READY */
        } else if (!ep->desc) {
-               DBG(ep->dev, "%s %s inactive?\n", __FUNCTION__, ep->ep.name);
+               DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name);
                return -EINVAL;
        }
 
@@ -940,7 +940,7 @@ static int goku_fifo_status(struct usb_ep *_ep)
        regs = ep->dev->regs;
        size = readl(&regs->EPxSizeLA[ep->num]) & DATASIZE;
        size += readl(&regs->EPxSizeLB[ep->num]) & DATASIZE;
-       VDBG(ep->dev, "%s %s %u\n", __FUNCTION__, ep->ep.name, size);
+       VDBG(ep->dev, "%s %s %u\n", __func__, ep->ep.name, size);
        return size;
 }
 
@@ -953,11 +953,11 @@ static void goku_fifo_flush(struct usb_ep *_ep)
        if (!_ep)
                return;
        ep = container_of(_ep, struct goku_ep, ep);
-       VDBG(ep->dev, "%s %s\n", __FUNCTION__, ep->ep.name);
+       VDBG(ep->dev, "%s %s\n", __func__, ep->ep.name);
 
        /* don't change EPxSTATUS_EP_INVALID to READY */
        if (!ep->desc && ep->num != 0) {
-               DBG(ep->dev, "%s %s inactive?\n", __FUNCTION__, ep->ep.name);
+               DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name);
                return;
        }
 
@@ -1286,7 +1286,7 @@ static void ep0_start(struct goku_udc *dev)
        struct goku_udc_regs __iomem    *regs = dev->regs;
        unsigned                        i;
 
-       VDBG(dev, "%s\n", __FUNCTION__);
+       VDBG(dev, "%s\n", __func__);
 
        udc_reset(dev);
        udc_reinit (dev);
@@ -1322,7 +1322,7 @@ static void udc_enable(struct goku_udc *dev)
        if (readl(&dev->regs->power_detect) & PW_DETECT)
                ep0_start(dev);
        else {
-               DBG(dev, "%s\n", __FUNCTION__);
+               DBG(dev, "%s\n", __func__);
                dev->int_enable = INT_PWRDETECT;
                writel(dev->int_enable, &dev->regs->int_enable);
        }
@@ -1387,7 +1387,7 @@ stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
 {
        unsigned        i;
 
-       DBG (dev, "%s\n", __FUNCTION__);
+       DBG (dev, "%s\n", __func__);
 
        if (dev->gadget.speed == USB_SPEED_UNKNOWN)
                driver = NULL;
@@ -1726,7 +1726,7 @@ static void goku_remove(struct pci_dev *pdev)
 {
        struct goku_udc         *dev = pci_get_drvdata(pdev);
 
-       DBG(dev, "%s\n", __FUNCTION__);
+       DBG(dev, "%s\n", __func__);
 
        BUG_ON(dev->driver);
 
index 0a6feafc8d2847ef39ab4ed3c74cac750e8b931c..69b0a2754f2ae3a0e7b0af72039094311b0cda1b 100644 (file)
@@ -1107,13 +1107,13 @@ scan:
 
        switch (state) {
        default:
-               DBG (dev, "fail %s, state %d\n", __FUNCTION__, state);
+               DBG (dev, "fail %s, state %d\n", __func__, state);
                retval = -ESRCH;
                break;
        case STATE_DEV_UNCONNECTED:
        case STATE_DEV_CONNECTED:
                spin_unlock_irq (&dev->lock);
-               DBG (dev, "%s wait\n", __FUNCTION__);
+               DBG (dev, "%s wait\n", __func__);
 
                /* wait for events */
                retval = wait_event_interruptible (dev->wait,
@@ -1222,7 +1222,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
                        DBG(dev, "bogus ep0out stall!\n");
                }
        } else
-               DBG (dev, "fail %s, state %d\n", __FUNCTION__, dev->state);
+               DBG (dev, "fail %s, state %d\n", __func__, dev->state);
 
        spin_unlock_irq (&dev->lock);
        return retval;
@@ -1233,7 +1233,7 @@ ep0_fasync (int f, struct file *fd, int on)
 {
        struct dev_data         *dev = fd->private_data;
        // caller must F_SETOWN before signal delivery happens
-       VDEBUG (dev, "%s %s\n", __FUNCTION__, on ? "on" : "off");
+       VDEBUG (dev, "%s %s\n", __func__, on ? "on" : "off");
        return fasync_helper (f, fd, on, &dev->fasync);
 }
 
@@ -1575,7 +1575,7 @@ static void destroy_ep_files (struct dev_data *dev)
 {
        struct list_head        *entry, *tmp;
 
-       DBG (dev, "%s %d\n", __FUNCTION__, dev->state);
+       DBG (dev, "%s %d\n", __func__, dev->state);
 
        /* dev->state must prevent interference */
 restart:
@@ -1662,7 +1662,7 @@ enomem1:
        put_dev (dev);
        kfree (data);
 enomem0:
-       DBG (dev, "%s enomem\n", __FUNCTION__);
+       DBG (dev, "%s enomem\n", __func__);
        destroy_ep_files (dev);
        return -ENOMEM;
 }
@@ -1672,7 +1672,7 @@ gadgetfs_unbind (struct usb_gadget *gadget)
 {
        struct dev_data         *dev = get_gadget_data (gadget);
 
-       DBG (dev, "%s\n", __FUNCTION__);
+       DBG (dev, "%s\n", __func__);
 
        spin_lock_irq (&dev->lock);
        dev->state = STATE_DEV_UNBOUND;
@@ -1685,7 +1685,7 @@ gadgetfs_unbind (struct usb_gadget *gadget)
        /* we've already been disconnected ... no i/o is active */
        if (dev->req)
                usb_ep_free_request (gadget->ep0, dev->req);
-       DBG (dev, "%s done\n", __FUNCTION__);
+       DBG (dev, "%s done\n", __func__);
        put_dev (dev);
 }
 
@@ -1933,7 +1933,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
 
 fail:
        spin_unlock_irq (&dev->lock);
-       pr_debug ("%s: %s fail %Zd, %p\n", shortname, __FUNCTION__, value, dev);
+       pr_debug ("%s: %s fail %Zd, %p\n", shortname, __func__, value, dev);
        kfree (dev->buf);
        dev->buf = NULL;
        return value;
index 078f72467671b81720178b84a2692a26ba86261e..825abd2621b397499a92e9d43b41b7e1d2862e98 100644 (file)
@@ -253,7 +253,7 @@ udc_proc_read(char *page, char **start, off_t off, int count,
  */
 static void udc_disable(struct lh7a40x_udc *dev)
 {
-       DEBUG("%s, %p\n", __FUNCTION__, dev);
+       DEBUG("%s, %p\n", __func__, dev);
 
        udc_set_address(dev, 0);
 
@@ -285,7 +285,7 @@ static void udc_reinit(struct lh7a40x_udc *dev)
 {
        u32 i;
 
-       DEBUG("%s, %p\n", __FUNCTION__, dev);
+       DEBUG("%s, %p\n", __func__, dev);
 
        /* device/ep0 records init */
        INIT_LIST_HEAD(&dev->gadget.ep_list);
@@ -318,7 +318,7 @@ static void udc_enable(struct lh7a40x_udc *dev)
 {
        int ep;
 
-       DEBUG("%s, %p\n", __FUNCTION__, dev);
+       DEBUG("%s, %p\n", __func__, dev);
 
        dev->gadget.speed = USB_SPEED_UNKNOWN;
 
@@ -412,7 +412,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
        struct lh7a40x_udc *dev = the_controller;
        int retval;
 
-       DEBUG("%s: %s\n", __FUNCTION__, driver->driver.name);
+       DEBUG("%s: %s\n", __func__, driver->driver.name);
 
        if (!driver
                        || driver->speed != USB_SPEED_FULL
@@ -521,7 +521,7 @@ static int write_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
                        is_short = unlikely(max < ep_maxpacket(ep));
                }
 
-               DEBUG("%s: wrote %s %d bytes%s%s %d left %p\n", __FUNCTION__,
+               DEBUG("%s: wrote %s %d bytes%s%s %d left %p\n", __func__,
                      ep->ep.name, count,
                      is_last ? "/L" : "", is_short ? "/S" : "",
                      req->req.length - req->req.actual, req);
@@ -555,7 +555,7 @@ static int read_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
        /* make sure there's a packet in the FIFO. */
        csr = usb_read(ep->csr1);
        if (!(csr & USB_OUT_CSR1_OUT_PKT_RDY)) {
-               DEBUG("%s: Packet NOT ready!\n", __FUNCTION__);
+               DEBUG("%s: Packet NOT ready!\n", __func__);
                return -EINVAL;
        }
 
@@ -614,7 +614,7 @@ static void done(struct lh7a40x_ep *ep, struct lh7a40x_request *req, int status)
        unsigned int stopped = ep->stopped;
        u32 index;
 
-       DEBUG("%s, %p\n", __FUNCTION__, ep);
+       DEBUG("%s, %p\n", __func__, ep);
        list_del_init(&req->queue);
 
        if (likely(req->req.status == -EINPROGRESS))
@@ -644,7 +644,7 @@ static void done(struct lh7a40x_ep *ep, struct lh7a40x_request *req, int status)
 /** Enable EP interrupt */
 static void pio_irq_enable(int ep)
 {
-       DEBUG("%s: %d\n", __FUNCTION__, ep);
+       DEBUG("%s: %d\n", __func__, ep);
 
        switch (ep) {
        case 1:
@@ -665,7 +665,7 @@ static void pio_irq_enable(int ep)
 /** Disable EP interrupt */
 static void pio_irq_disable(int ep)
 {
-       DEBUG("%s: %d\n", __FUNCTION__, ep);
+       DEBUG("%s: %d\n", __func__, ep);
 
        switch (ep) {
        case 1:
@@ -690,7 +690,7 @@ void nuke(struct lh7a40x_ep *ep, int status)
 {
        struct lh7a40x_request *req;
 
-       DEBUG("%s, %p\n", __FUNCTION__, ep);
+       DEBUG("%s, %p\n", __func__, ep);
 
        /* Flush FIFO */
        flush(ep);
@@ -734,7 +734,7 @@ static void flush_all(struct lh7a40x_udc *dev)
  */
 static void flush(struct lh7a40x_ep *ep)
 {
-       DEBUG("%s, %p\n", __FUNCTION__, ep);
+       DEBUG("%s, %p\n", __func__, ep);
 
        switch (ep->ep_type) {
        case ep_control:
@@ -766,7 +766,7 @@ static void lh7a40x_in_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
        usb_set_index(ep_idx);
 
        csr = usb_read(ep->csr1);
-       DEBUG("%s: %d, csr %x\n", __FUNCTION__, ep_idx, csr);
+       DEBUG("%s: %d, csr %x\n", __func__, ep_idx, csr);
 
        if (csr & USB_IN_CSR1_SENT_STALL) {
                DEBUG("USB_IN_CSR1_SENT_STALL\n");
@@ -776,7 +776,7 @@ static void lh7a40x_in_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
        }
 
        if (!ep->desc) {
-               DEBUG("%s: NO EP DESC\n", __FUNCTION__);
+               DEBUG("%s: NO EP DESC\n", __func__);
                return;
        }
 
@@ -802,7 +802,7 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
        struct lh7a40x_ep *ep = &dev->ep[ep_idx];
        struct lh7a40x_request *req;
 
-       DEBUG("%s: %d\n", __FUNCTION__, ep_idx);
+       DEBUG("%s: %d\n", __func__, ep_idx);
 
        usb_set_index(ep_idx);
 
@@ -814,11 +814,11 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
                        usb_read(ep->
                                 csr1)) & (USB_OUT_CSR1_OUT_PKT_RDY |
                                           USB_OUT_CSR1_SENT_STALL)) {
-                       DEBUG("%s: %x\n", __FUNCTION__, csr);
+                       DEBUG("%s: %x\n", __func__, csr);
 
                        if (csr & USB_OUT_CSR1_SENT_STALL) {
                                DEBUG("%s: stall sent, flush fifo\n",
-                                     __FUNCTION__);
+                                     __func__);
                                /* usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1); */
                                flush(ep);
                        } else if (csr & USB_OUT_CSR1_OUT_PKT_RDY) {
@@ -832,7 +832,7 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
 
                                if (!req) {
                                        printk("%s: NULL REQ %d\n",
-                                              __FUNCTION__, ep_idx);
+                                              __func__, ep_idx);
                                        flush(ep);
                                        break;
                                } else {
@@ -844,7 +844,7 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
 
        } else {
                /* Throw packet away.. */
-               printk("%s: No descriptor?!?\n", __FUNCTION__);
+               printk("%s: No descriptor?!?\n", __func__);
                flush(ep);
        }
 }
@@ -886,7 +886,7 @@ static void lh7a40x_reset_intr(struct lh7a40x_udc *dev)
 #if 0                          /* def CONFIG_ARCH_LH7A404 */
        /* Does not work always... */
 
-       DEBUG("%s: %d\n", __FUNCTION__, dev->usb_address);
+       DEBUG("%s: %d\n", __func__, dev->usb_address);
 
        if (!dev->usb_address) {
                /*usb_set(USB_RESET_IO, USB_RESET);
@@ -936,7 +936,7 @@ static irqreturn_t lh7a40x_udc_irq(int irq, void *_dev)
                if (!intr_out && !intr_in && !intr_int)
                        break;
 
-               DEBUG("%s (on state %s)\n", __FUNCTION__,
+               DEBUG("%s (on state %s)\n", __func__,
                      state_names[dev->ep0state]);
                DEBUG("intr_out = %x\n", intr_out);
                DEBUG("intr_in  = %x\n", intr_in);
@@ -1016,14 +1016,14 @@ static int lh7a40x_ep_enable(struct usb_ep *_ep,
        struct lh7a40x_udc *dev;
        unsigned long flags;
 
-       DEBUG("%s, %p\n", __FUNCTION__, _ep);
+       DEBUG("%s, %p\n", __func__, _ep);
 
        ep = container_of(_ep, struct lh7a40x_ep, ep);
        if (!_ep || !desc || ep->desc || _ep->name == ep0name
            || desc->bDescriptorType != USB_DT_ENDPOINT
            || ep->bEndpointAddress != desc->bEndpointAddress
            || ep_maxpacket(ep) < le16_to_cpu(desc->wMaxPacketSize)) {
-               DEBUG("%s, bad ep or descriptor\n", __FUNCTION__);
+               DEBUG("%s, bad ep or descriptor\n", __func__);
                return -EINVAL;
        }
 
@@ -1031,7 +1031,7 @@ static int lh7a40x_ep_enable(struct usb_ep *_ep,
        if (ep->bmAttributes != desc->bmAttributes
            && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
            && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
-               DEBUG("%s, %s type mismatch\n", __FUNCTION__, _ep->name);
+               DEBUG("%s, %s type mismatch\n", __func__, _ep->name);
                return -EINVAL;
        }
 
@@ -1039,13 +1039,13 @@ static int lh7a40x_ep_enable(struct usb_ep *_ep,
        if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
             && le16_to_cpu(desc->wMaxPacketSize) != ep_maxpacket(ep))
            || !desc->wMaxPacketSize) {
-               DEBUG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
+               DEBUG("%s, bad %s maxpacket\n", __func__, _ep->name);
                return -ERANGE;
        }
 
        dev = ep->dev;
        if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
-               DEBUG("%s, bogus device state\n", __FUNCTION__);
+               DEBUG("%s, bogus device state\n", __func__);
                return -ESHUTDOWN;
        }
 
@@ -1061,7 +1061,7 @@ static int lh7a40x_ep_enable(struct usb_ep *_ep,
        /* Reset halt state (does flush) */
        lh7a40x_set_halt(_ep, 0);
 
-       DEBUG("%s: enabled %s\n", __FUNCTION__, _ep->name);
+       DEBUG("%s: enabled %s\n", __func__, _ep->name);
        return 0;
 }
 
@@ -1073,11 +1073,11 @@ static int lh7a40x_ep_disable(struct usb_ep *_ep)
        struct lh7a40x_ep *ep;
        unsigned long flags;
 
-       DEBUG("%s, %p\n", __FUNCTION__, _ep);
+       DEBUG("%s, %p\n", __func__, _ep);
 
        ep = container_of(_ep, struct lh7a40x_ep, ep);
        if (!_ep || !ep->desc) {
-               DEBUG("%s, %s not enabled\n", __FUNCTION__,
+               DEBUG("%s, %s not enabled\n", __func__,
                      _ep ? ep->ep.name : NULL);
                return -EINVAL;
        }
@@ -1097,7 +1097,7 @@ static int lh7a40x_ep_disable(struct usb_ep *_ep)
 
        spin_unlock_irqrestore(&ep->dev->lock, flags);
 
-       DEBUG("%s: disabled %s\n", __FUNCTION__, _ep->name);
+       DEBUG("%s: disabled %s\n", __func__, _ep->name);
        return 0;
 }
 
@@ -1106,7 +1106,7 @@ static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep,
 {
        struct lh7a40x_request *req;
 
-       DEBUG("%s, %p\n", __FUNCTION__, ep);
+       DEBUG("%s, %p\n", __func__, ep);
 
        req = kzalloc(sizeof(*req), gfp_flags);
        if (!req)
@@ -1121,7 +1121,7 @@ static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *_req)
 {
        struct lh7a40x_request *req;
 
-       DEBUG("%s, %p\n", __FUNCTION__, ep);
+       DEBUG("%s, %p\n", __func__, ep);
 
        req = container_of(_req, struct lh7a40x_request, req);
        WARN_ON(!list_empty(&req->queue));
@@ -1140,25 +1140,25 @@ static int lh7a40x_queue(struct usb_ep *_ep, struct usb_request *_req,
        struct lh7a40x_udc *dev;
        unsigned long flags;
 
-       DEBUG("\n\n\n%s, %p\n", __FUNCTION__, _ep);
+       DEBUG("\n\n\n%s, %p\n", __func__, _ep);
 
        req = container_of(_req, struct lh7a40x_request, req);
        if (unlikely
            (!_req || !_req->complete || !_req->buf
             || !list_empty(&req->queue))) {
-               DEBUG("%s, bad params\n", __FUNCTION__);
+               DEBUG("%s, bad params\n", __func__);
                return -EINVAL;
        }
 
        ep = container_of(_ep, struct lh7a40x_ep, ep);
        if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
-               DEBUG("%s, bad ep\n", __FUNCTION__);
+               DEBUG("%s, bad ep\n", __func__);
                return -EINVAL;
        }
 
        dev = ep->dev;
        if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
-               DEBUG("%s, bogus device state %p\n", __FUNCTION__, dev->driver);
+               DEBUG("%s, bogus device state %p\n", __func__, dev->driver);
                return -ESHUTDOWN;
        }
 
@@ -1218,7 +1218,7 @@ static int lh7a40x_dequeue(struct usb_ep *_ep, struct usb_request *_req)
        struct lh7a40x_request *req;
        unsigned long flags;
 
-       DEBUG("%s, %p\n", __FUNCTION__, _ep);
+       DEBUG("%s, %p\n", __func__, _ep);
 
        ep = container_of(_ep, struct lh7a40x_ep, ep);
        if (!_ep || ep->ep.name == ep0name)
@@ -1253,13 +1253,13 @@ static int lh7a40x_set_halt(struct usb_ep *_ep, int value)
 
        ep = container_of(_ep, struct lh7a40x_ep, ep);
        if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
-               DEBUG("%s, bad ep\n", __FUNCTION__);
+               DEBUG("%s, bad ep\n", __func__);
                return -EINVAL;
        }
 
        usb_set_index(ep_index(ep));
 
-       DEBUG("%s, ep %d, val %d\n", __FUNCTION__, ep_index(ep), value);
+       DEBUG("%s, ep %d, val %d\n", __func__, ep_index(ep), value);
 
        spin_lock_irqsave(&ep->dev->lock, flags);
 
@@ -1325,11 +1325,11 @@ static int lh7a40x_fifo_status(struct usb_ep *_ep)
 
        ep = container_of(_ep, struct lh7a40x_ep, ep);
        if (!_ep) {
-               DEBUG("%s, bad ep\n", __FUNCTION__);
+               DEBUG("%s, bad ep\n", __func__);
                return -ENODEV;
        }
 
-       DEBUG("%s, %d\n", __FUNCTION__, ep_index(ep));
+       DEBUG("%s, %d\n", __func__, ep_index(ep));
 
        /* LPD can't report unclaimed bytes from IN fifos */
        if (ep_is_in(ep))
@@ -1355,7 +1355,7 @@ static void lh7a40x_fifo_flush(struct usb_ep *_ep)
 
        ep = container_of(_ep, struct lh7a40x_ep, ep);
        if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
-               DEBUG("%s, bad ep\n", __FUNCTION__);
+               DEBUG("%s, bad ep\n", __func__);
                return;
        }
 
@@ -1376,7 +1376,7 @@ static int write_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
 
        max = ep_maxpacket(ep);
 
-       DEBUG_EP0("%s\n", __FUNCTION__);
+       DEBUG_EP0("%s\n", __func__);
 
        count = write_packet(ep, req, max);
 
@@ -1390,7 +1390,7 @@ static int write_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
                        is_last = 1;
        }
 
-       DEBUG_EP0("%s: wrote %s %d bytes%s %d left %p\n", __FUNCTION__,
+       DEBUG_EP0("%s: wrote %s %d bytes%s %d left %p\n", __func__,
                  ep->ep.name, count,
                  is_last ? "/L" : "", req->req.length - req->req.actual, req);
 
@@ -1434,7 +1434,7 @@ static int read_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
        unsigned bufferspace, count, is_short;
        volatile u32 *fifo = (volatile u32 *)ep->fifo;
 
-       DEBUG_EP0("%s\n", __FUNCTION__);
+       DEBUG_EP0("%s\n", __func__);
 
        csr = usb_read(USB_EP0_CSR);
        if (!(csr & USB_OUT_CSR1_OUT_PKT_RDY))
@@ -1492,7 +1492,7 @@ static int read_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
  */
 static void udc_set_address(struct lh7a40x_udc *dev, unsigned char address)
 {
-       DEBUG_EP0("%s: %d\n", __FUNCTION__, address);
+       DEBUG_EP0("%s: %d\n", __func__, address);
        /* c.f. 15.1.2.2 Table 15-4 address will be used after DATA_END is set */
        dev->usb_address = address;
        usb_set((address & USB_FA_FUNCTION_ADDR), USB_FA);
@@ -1514,7 +1514,7 @@ static void lh7a40x_ep0_out(struct lh7a40x_udc *dev, u32 csr)
        struct lh7a40x_ep *ep = &dev->ep[0];
        int ret;
 
-       DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
+       DEBUG_EP0("%s: %x\n", __func__, csr);
 
        if (list_empty(&ep->queue))
                req = 0;
@@ -1533,13 +1533,13 @@ static void lh7a40x_ep0_out(struct lh7a40x_udc *dev, u32 csr)
                if (ret) {
                        /* Done! */
                        DEBUG_EP0("%s: finished, waiting for status\n",
-                                 __FUNCTION__);
+                                 __func__);
 
                        usb_set((EP0_CLR_OUT | EP0_DATA_END), USB_EP0_CSR);
                        dev->ep0state = WAIT_FOR_SETUP;
                } else {
                        /* Not done yet.. */
-                       DEBUG_EP0("%s: not finished\n", __FUNCTION__);
+                       DEBUG_EP0("%s: not finished\n", __func__);
                        usb_set(EP0_CLR_OUT, USB_EP0_CSR);
                }
        } else {
@@ -1556,7 +1556,7 @@ static int lh7a40x_ep0_in(struct lh7a40x_udc *dev, u32 csr)
        struct lh7a40x_ep *ep = &dev->ep[0];
        int ret, need_zlp = 0;
 
-       DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
+       DEBUG_EP0("%s: %x\n", __func__, csr);
 
        if (list_empty(&ep->queue))
                req = 0;
@@ -1564,7 +1564,7 @@ static int lh7a40x_ep0_in(struct lh7a40x_udc *dev, u32 csr)
                req = list_entry(ep->queue.next, struct lh7a40x_request, queue);
 
        if (!req) {
-               DEBUG_EP0("%s: NULL REQ\n", __FUNCTION__);
+               DEBUG_EP0("%s: NULL REQ\n", __func__);
                return 0;
        }
 
@@ -1585,17 +1585,17 @@ static int lh7a40x_ep0_in(struct lh7a40x_udc *dev, u32 csr)
 
        if (ret == 1 && !need_zlp) {
                /* Last packet */
-               DEBUG_EP0("%s: finished, waiting for status\n", __FUNCTION__);
+               DEBUG_EP0("%s: finished, waiting for status\n", __func__);
 
                usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
                dev->ep0state = WAIT_FOR_SETUP;
        } else {
-               DEBUG_EP0("%s: not finished\n", __FUNCTION__);
+               DEBUG_EP0("%s: not finished\n", __func__);
                usb_set(EP0_IN_PKT_RDY, USB_EP0_CSR);
        }
 
        if (need_zlp) {
-               DEBUG_EP0("%s: Need ZLP!\n", __FUNCTION__);
+               DEBUG_EP0("%s: Need ZLP!\n", __func__);
                usb_set(EP0_IN_PKT_RDY, USB_EP0_CSR);
                dev->ep0state = DATA_STATE_NEED_ZLP;
        }
@@ -1694,7 +1694,7 @@ static void lh7a40x_ep0_setup(struct lh7a40x_udc *dev, u32 csr)
        struct usb_ctrlrequest ctrl;
        int i, bytes, is_in;
 
-       DEBUG_SETUP("%s: %x\n", __FUNCTION__, csr);
+       DEBUG_SETUP("%s: %x\n", __func__, csr);
 
        /* Nuke all previous transfers */
        nuke(ep, -EPROTO);
@@ -1799,7 +1799,7 @@ static void lh7a40x_ep0_setup(struct lh7a40x_udc *dev, u32 csr)
  */
 static void lh7a40x_ep0_in_zlp(struct lh7a40x_udc *dev, u32 csr)
 {
-       DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
+       DEBUG_EP0("%s: %x\n", __func__, csr);
 
        /* c.f. Table 15-14 */
        usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
@@ -1818,7 +1818,7 @@ static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
        usb_set_index(0);
        csr = usb_read(USB_EP0_CSR);
 
-       DEBUG_EP0("%s: csr = %x\n", __FUNCTION__, csr);
+       DEBUG_EP0("%s: csr = %x\n", __func__, csr);
 
        /*
         * For overview of what we should be doing see c.f. Chapter 18.1.2.4
@@ -1832,7 +1832,7 @@ static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
         *      - clear the SENT_STALL bit
         */
        if (csr & EP0_SENT_STALL) {
-               DEBUG_EP0("%s: EP0_SENT_STALL is set: %x\n", __FUNCTION__, csr);
+               DEBUG_EP0("%s: EP0_SENT_STALL is set: %x\n", __func__, csr);
                usb_clear((EP0_SENT_STALL | EP0_SEND_STALL), USB_EP0_CSR);
                nuke(ep, -ECONNABORTED);
                dev->ep0state = WAIT_FOR_SETUP;
@@ -1849,7 +1849,7 @@ static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
         */
        if (!(csr & (EP0_IN_PKT_RDY | EP0_OUT_PKT_RDY))) {
                DEBUG_EP0("%s: IN_PKT_RDY and OUT_PKT_RDY are clear\n",
-                         __FUNCTION__);
+                         __func__);
 
                switch (dev->ep0state) {
                case DATA_STATE_XMIT:
@@ -1877,7 +1877,7 @@ static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
         *      - set SERVICED_SETUP_END_BIT
         */
        if (csr & EP0_SETUP_END) {
-               DEBUG_EP0("%s: EP0_SETUP_END is set: %x\n", __FUNCTION__, csr);
+               DEBUG_EP0("%s: EP0_SETUP_END is set: %x\n", __func__, csr);
 
                usb_set(EP0_CLR_SETUP_END, USB_EP0_CSR);
 
@@ -1896,7 +1896,7 @@ static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
         */
        if (csr & EP0_OUT_PKT_RDY) {
 
-               DEBUG_EP0("%s: EP0_OUT_PKT_RDY is set: %x\n", __FUNCTION__,
+               DEBUG_EP0("%s: EP0_OUT_PKT_RDY is set: %x\n", __func__,
                          csr);
 
                switch (dev->ep0state) {
@@ -1926,7 +1926,7 @@ static void lh7a40x_ep0_kick(struct lh7a40x_udc *dev, struct lh7a40x_ep *ep)
        usb_set_index(0);
        csr = usb_read(USB_EP0_CSR);
 
-       DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
+       DEBUG_EP0("%s: %x\n", __func__, csr);
 
        /* Clear "out packet ready" */
        usb_set(EP0_CLR_OUT, USB_EP0_CSR);
@@ -1949,7 +1949,7 @@ static int lh7a40x_udc_get_frame(struct usb_gadget *_gadget)
 {
        u32 frame1 = usb_read(USB_FRM_NUM1);    /* Least significant 8 bits */
        u32 frame2 = usb_read(USB_FRM_NUM2);    /* Most significant 3 bits */
-       DEBUG("%s, %p\n", __FUNCTION__, _gadget);
+       DEBUG("%s, %p\n", __func__, _gadget);
        return ((frame2 & 0x07) << 8) | (frame1 & 0xff);
 }
 
@@ -1970,7 +1970,7 @@ static const struct usb_gadget_ops lh7a40x_udc_ops = {
 
 static void nop_release(struct device *dev)
 {
-       DEBUG("%s %s\n", __FUNCTION__, dev->bus_id);
+       DEBUG("%s %s\n", __func__, dev->bus_id);
 }
 
 static struct lh7a40x_udc memory = {
@@ -2065,7 +2065,7 @@ static int lh7a40x_udc_probe(struct platform_device *pdev)
        struct lh7a40x_udc *dev = &memory;
        int retval;
 
-       DEBUG("%s: %p\n", __FUNCTION__, pdev);
+       DEBUG("%s: %p\n", __func__, pdev);
 
        spin_lock_init(&dev->lock);
        dev->dev = &pdev->dev;
@@ -2098,7 +2098,7 @@ static int lh7a40x_udc_remove(struct platform_device *pdev)
 {
        struct lh7a40x_udc *dev = platform_get_drvdata(pdev);
 
-       DEBUG("%s: %p\n", __FUNCTION__, pdev);
+       DEBUG("%s: %p\n", __func__, pdev);
 
        if (dev->driver)
                return -EBUSY;
@@ -2131,7 +2131,7 @@ static struct platform_driver udc_driver = {
 
 static int __init udc_init(void)
 {
-       DEBUG("%s: %s version %s\n", __FUNCTION__, driver_name, DRIVER_VERSION);
+       DEBUG("%s: %s version %s\n", __func__, driver_name, DRIVER_VERSION);
        return platform_driver_register(&udc_driver);
 }
 
index 17b792b7f6bfc43d3879fc316b188f0a12ae36f4..be0a4c1f80a2d66fa8c26ed66f9aacc81093e811 100644 (file)
@@ -486,10 +486,10 @@ struct m66592 {
 
        struct usb_request      *ep0_req;       /* for internal request */
        u16                     ep0_data;       /* for internal request */
+       u16                     old_vbus;
 
        struct timer_list       timer;
 
-       u16                     old_vbus;
        int                     scount;
 
        int                     old_dvsq;
index 44ca139983d8e4c302f5f50a3918071b416179f9..1f2af398a9a405df9e78192080474114c2ac95f6 100644 (file)
@@ -299,7 +299,7 @@ static inline void assert_out_naking (struct net2280_ep *ep, const char *where)
                        &ep->regs->ep_rsp);
        }
 }
-#define ASSERT_OUT_NAKING(ep) assert_out_naking(ep,__FUNCTION__)
+#define ASSERT_OUT_NAKING(ep) assert_out_naking(ep,__func__)
 #else
 #define ASSERT_OUT_NAKING(ep) do {} while (0)
 #endif
index ee1e9a314cd1b07fa08f8460d6bb13364b021984..95f7662376f16e41e463ec3feef0c243842517f9 100644 (file)
@@ -163,7 +163,7 @@ static int omap_ep_enable(struct usb_ep *_ep,
                        || ep->bEndpointAddress != desc->bEndpointAddress
                        || ep->maxpacket < le16_to_cpu
                                                (desc->wMaxPacketSize)) {
-               DBG("%s, bad ep or descriptor\n", __FUNCTION__);
+               DBG("%s, bad ep or descriptor\n", __func__);
                return -EINVAL;
        }
        maxp = le16_to_cpu (desc->wMaxPacketSize);
@@ -171,7 +171,7 @@ static int omap_ep_enable(struct usb_ep *_ep,
                                && maxp != ep->maxpacket)
                        || le16_to_cpu(desc->wMaxPacketSize) > ep->maxpacket
                        || !desc->wMaxPacketSize) {
-               DBG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
+               DBG("%s, bad %s maxpacket\n", __func__, _ep->name);
                return -ERANGE;
        }
 
@@ -194,13 +194,13 @@ static int omap_ep_enable(struct usb_ep *_ep,
        if (ep->bmAttributes != desc->bmAttributes
                        && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
                        && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
-               DBG("%s, %s type mismatch\n", __FUNCTION__, _ep->name);
+               DBG("%s, %s type mismatch\n", __func__, _ep->name);
                return -EINVAL;
        }
 
        udc = ep->udc;
        if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
-               DBG("%s, bogus device state\n", __FUNCTION__);
+               DBG("%s, bogus device state\n", __func__);
                return -ESHUTDOWN;
        }
 
@@ -249,7 +249,7 @@ static int omap_ep_disable(struct usb_ep *_ep)
        unsigned long   flags;
 
        if (!_ep || !ep->desc) {
-               DBG("%s, %s not enabled\n", __FUNCTION__,
+               DBG("%s, %s not enabled\n", __func__,
                        _ep ? ep->ep.name : NULL);
                return -EINVAL;
        }
@@ -936,11 +936,11 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
        /* catch various bogus parameters */
        if (!_req || !req->req.complete || !req->req.buf
                        || !list_empty(&req->queue)) {
-               DBG("%s, bad params\n", __FUNCTION__);
+               DBG("%s, bad params\n", __func__);
                return -EINVAL;
        }
        if (!_ep || (!ep->desc && ep->bEndpointAddress)) {
-               DBG("%s, bad ep\n", __FUNCTION__);
+               DBG("%s, bad ep\n", __func__);
                return -EINVAL;
        }
        if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
@@ -959,7 +959,7 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
                        && (ep->bEndpointAddress & USB_DIR_IN) == 0
                        && !cpu_class_is_omap2()
                        && (req->req.length % ep->ep.maxpacket) != 0) {
-               DBG("%s, no partial packet OUT reads\n", __FUNCTION__);
+               DBG("%s, no partial packet OUT reads\n", __func__);
                return -EMSGSIZE;
        }
 
@@ -1265,8 +1265,6 @@ static int can_pullup(struct omap_udc *udc)
 
 static void pullup_enable(struct omap_udc *udc)
 {
-       udc->gadget.dev.parent->power.power_state = PMSG_ON;
-       udc->gadget.dev.power.power_state = PMSG_ON;
        UDC_SYSCON1_REG |= UDC_PULLUP_EN;
        if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx())
                OTG_CTRL_REG |= OTG_BSESSVLD;
@@ -3061,8 +3059,6 @@ static int omap_udc_suspend(struct platform_device *dev, pm_message_t message)
                omap_pullup(&udc->gadget, 0);
        }
 
-       udc->gadget.dev.power.power_state = PMSG_SUSPEND;
-       udc->gadget.dev.parent->power.power_state = PMSG_SUSPEND;
        return 0;
 }
 
index 2c32bd08ee7db2c6051df00de37f709de9041a10..76be75e3ab8fe4a051240b8c37e7f15c8558edba 100644 (file)
@@ -390,9 +390,12 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
 
        /* normal completion */
        case 0:
-               list_add_tail(&req->list, &dev->rx_buffers);
-               wake_up_interruptible(&dev->rx_wait);
-               DBG(dev, "G_Printer : rx length %d\n", req->actual);
+               if (req->actual > 0) {
+                       list_add_tail(&req->list, &dev->rx_buffers);
+                       DBG(dev, "G_Printer : rx length %d\n", req->actual);
+               } else {
+                       list_add(&req->list, &dev->rx_reqs);
+               }
                break;
 
        /* software-driven interface shutdown */
@@ -417,6 +420,8 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
                list_add(&req->list, &dev->rx_reqs);
                break;
        }
+
+       wake_up_interruptible(&dev->rx_wait);
        spin_unlock_irqrestore(&dev->lock, flags);
 }
 
@@ -494,6 +499,39 @@ printer_close(struct inode *inode, struct file *fd)
        return 0;
 }
 
+/* This function must be called with interrupts turned off. */
+static void
+setup_rx_reqs(struct printer_dev *dev)
+{
+       struct usb_request              *req;
+
+       while (likely(!list_empty(&dev->rx_reqs))) {
+               int error;
+
+               req = container_of(dev->rx_reqs.next,
+                               struct usb_request, list);
+               list_del_init(&req->list);
+
+               /* The USB Host sends us whatever amount of data it wants to
+                * so we always set the length field to the full USB_BUFSIZE.
+                * If the amount of data is more than the read() caller asked
+                * for it will be stored in the request buffer until it is
+                * asked for by read().
+                */
+               req->length = USB_BUFSIZE;
+               req->complete = rx_complete;
+
+               error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
+               if (error) {
+                       DBG(dev, "rx submit --> %d\n", error);
+                       list_add(&req->list, &dev->rx_reqs);
+                       break;
+               } else {
+                       list_add(&req->list, &dev->rx_reqs_active);
+               }
+       }
+}
+
 static ssize_t
 printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
 {
@@ -522,31 +560,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
         */
        dev->reset_printer = 0;
 
-       while (likely(!list_empty(&dev->rx_reqs))) {
-               int error;
-
-               req = container_of(dev->rx_reqs.next,
-                               struct usb_request, list);
-               list_del_init(&req->list);
-
-               /* The USB Host sends us whatever amount of data it wants to
-                * so we always set the length field to the full USB_BUFSIZE.
-                * If the amount of data is more than the read() caller asked
-                * for it will be stored in the request buffer until it is
-                * asked for by read().
-                */
-               req->length = USB_BUFSIZE;
-               req->complete = rx_complete;
-
-               error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
-               if (error) {
-                       DBG(dev, "rx submit --> %d\n", error);
-                       list_add(&req->list, &dev->rx_reqs);
-                       break;
-               } else {
-                       list_add(&req->list, &dev->rx_reqs_active);
-               }
-       }
+       setup_rx_reqs(dev);
 
        bytes_copied = 0;
        current_rx_req = dev->current_rx_req;
@@ -615,9 +629,9 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
 
                spin_lock_irqsave(&dev->lock, flags);
 
-               /* We've disconnected or reset free the req and buffer */
+               /* We've disconnected or reset so return. */
                if (dev->reset_printer) {
-                       printer_req_free(dev->out_ep, current_rx_req);
+                       list_add(&current_rx_req->list, &dev->rx_reqs);
                        spin_unlock_irqrestore(&dev->lock, flags);
                        spin_unlock(&dev->lock_printer_io);
                        return -EAGAIN;
@@ -735,7 +749,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
 
                /* We've disconnected or reset so free the req and buffer */
                if (dev->reset_printer) {
-                       printer_req_free(dev->in_ep, req);
+                       list_add(&req->list, &dev->tx_reqs);
                        spin_unlock_irqrestore(&dev->lock, flags);
                        spin_unlock(&dev->lock_printer_io);
                        return -EAGAIN;
@@ -791,6 +805,12 @@ printer_poll(struct file *fd, poll_table *wait)
        unsigned long           flags;
        int                     status = 0;
 
+       spin_lock(&dev->lock_printer_io);
+       spin_lock_irqsave(&dev->lock, flags);
+       setup_rx_reqs(dev);
+       spin_unlock_irqrestore(&dev->lock, flags);
+       spin_unlock(&dev->lock_printer_io);
+
        poll_wait(fd, &dev->rx_wait, wait);
        poll_wait(fd, &dev->tx_wait, wait);
 
@@ -798,7 +818,8 @@ printer_poll(struct file *fd, poll_table *wait)
        if (likely(!list_empty(&dev->tx_reqs)))
                status |= POLLOUT | POLLWRNORM;
 
-       if (likely(!list_empty(&dev->rx_buffers)))
+       if (likely(dev->current_rx_bytes) ||
+                       likely(!list_empty(&dev->rx_buffers)))
                status |= POLLIN | POLLRDNORM;
 
        spin_unlock_irqrestore(&dev->lock, flags);
@@ -894,7 +915,7 @@ static void printer_reset_interface(struct printer_dev *dev)
        if (dev->interface < 0)
                return;
 
-       DBG(dev, "%s\n", __FUNCTION__);
+       DBG(dev, "%s\n", __func__);
 
        if (dev->in)
                usb_ep_disable(dev->in_ep);
@@ -1084,6 +1105,7 @@ static void printer_soft_reset(struct printer_dev *dev)
        if (usb_ep_enable(dev->out_ep, dev->out))
                DBG(dev, "Failed to enable USB out_ep\n");
 
+       wake_up_interruptible(&dev->rx_wait);
        wake_up_interruptible(&dev->tx_wait);
        wake_up_interruptible(&dev->tx_flush_wait);
 }
@@ -1262,7 +1284,7 @@ printer_disconnect(struct usb_gadget *gadget)
        struct printer_dev      *dev = get_gadget_data(gadget);
        unsigned long           flags;
 
-       DBG(dev, "%s\n", __FUNCTION__);
+       DBG(dev, "%s\n", __func__);
 
        spin_lock_irqsave(&dev->lock, flags);
 
@@ -1278,7 +1300,7 @@ printer_unbind(struct usb_gadget *gadget)
        struct usb_request      *req;
 
 
-       DBG(dev, "%s\n", __FUNCTION__);
+       DBG(dev, "%s\n", __func__);
 
        /* Remove sysfs files */
        device_destroy(usb_gadget_class, g_printer_devno);
index c00cd8b9d3d1bb359c78f7a2b2c934dc0d10648a..08f699b1fc5702d70589e8b26d3ccac473539793 100644 (file)
@@ -235,7 +235,7 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep,
                        || ep->bEndpointAddress != desc->bEndpointAddress
                        || ep->fifo_size < le16_to_cpu
                                                (desc->wMaxPacketSize)) {
-               DMSG("%s, bad ep or descriptor\n", __FUNCTION__);
+               DMSG("%s, bad ep or descriptor\n", __func__);
                return -EINVAL;
        }
 
@@ -243,7 +243,7 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep,
        if (ep->bmAttributes != desc->bmAttributes
                        && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
                        && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
-               DMSG("%s, %s type mismatch\n", __FUNCTION__, _ep->name);
+               DMSG("%s, %s type mismatch\n", __func__, _ep->name);
                return -EINVAL;
        }
 
@@ -252,13 +252,13 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep,
                                && le16_to_cpu (desc->wMaxPacketSize)
                                                != BULK_FIFO_SIZE)
                        || !desc->wMaxPacketSize) {
-               DMSG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
+               DMSG("%s, bad %s maxpacket\n", __func__, _ep->name);
                return -ERANGE;
        }
 
        dev = ep->dev;
        if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
-               DMSG("%s, bogus device state\n", __FUNCTION__);
+               DMSG("%s, bogus device state\n", __func__);
                return -ESHUTDOWN;
        }
 
@@ -283,7 +283,7 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep)
 
        ep = container_of (_ep, struct pxa2xx_ep, ep);
        if (!_ep || !ep->desc) {
-               DMSG("%s, %s not enabled\n", __FUNCTION__,
+               DMSG("%s, %s not enabled\n", __func__,
                        _ep ? ep->ep.name : NULL);
                return -EINVAL;
        }
@@ -461,7 +461,7 @@ void ep0start(struct pxa2xx_udc *dev, u32 flags, const char *tag)
        USIR0 = USIR0_IR0;
        dev->req_pending = 0;
        DBG(DBG_VERY_NOISY, "%s %s, %02x/%02x\n",
-               __FUNCTION__, tag, UDCCS0, flags);
+               __func__, tag, UDCCS0, flags);
 }
 
 static int
@@ -651,20 +651,20 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
        req = container_of(_req, struct pxa2xx_request, req);
        if (unlikely (!_req || !_req->complete || !_req->buf
                        || !list_empty(&req->queue))) {
-               DMSG("%s, bad params\n", __FUNCTION__);
+               DMSG("%s, bad params\n", __func__);
                return -EINVAL;
        }
 
        ep = container_of(_ep, struct pxa2xx_ep, ep);
        if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
-               DMSG("%s, bad ep\n", __FUNCTION__);
+               DMSG("%s, bad ep\n", __func__);
                return -EINVAL;
        }
 
        dev = ep->dev;
        if (unlikely (!dev->driver
                        || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
-               DMSG("%s, bogus device state\n", __FUNCTION__);
+               DMSG("%s, bogus device state\n", __func__);
                return -ESHUTDOWN;
        }
 
@@ -807,7 +807,7 @@ static int pxa2xx_ep_set_halt(struct usb_ep *_ep, int value)
        if (unlikely (!_ep
                        || (!ep->desc && ep->ep.name != ep0name))
                        || ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
-               DMSG("%s, bad ep\n", __FUNCTION__);
+               DMSG("%s, bad ep\n", __func__);
                return -EINVAL;
        }
        if (value == 0) {
@@ -859,7 +859,7 @@ static int pxa2xx_ep_fifo_status(struct usb_ep *_ep)
 
        ep = container_of(_ep, struct pxa2xx_ep, ep);
        if (!_ep) {
-               DMSG("%s, bad ep\n", __FUNCTION__);
+               DMSG("%s, bad ep\n", __func__);
                return -ENODEV;
        }
        /* pxa can't report unclaimed bytes from IN fifos */
@@ -878,7 +878,7 @@ static void pxa2xx_ep_fifo_flush(struct usb_ep *_ep)
 
        ep = container_of(_ep, struct pxa2xx_ep, ep);
        if (!_ep || ep->ep.name == ep0name || !list_empty(&ep->queue)) {
-               DMSG("%s, bad ep\n", __FUNCTION__);
+               DMSG("%s, bad ep\n", __func__);
                return;
        }
 
@@ -1813,7 +1813,7 @@ pxa2xx_udc_irq(int irq, void *_dev)
 
 static void nop_release (struct device *dev)
 {
-       DMSG("%s %s\n", __FUNCTION__, dev->bus_id);
+       DMSG("%s %s\n", __func__, dev->bus_id);
 }
 
 /* this uses load-time allocation and initialization (instead of
index 3d036647431fdbd8f409a30cf327d74acceb82c5..bd58dd504f6f4ec144048432b51a8d8737047751 100644 (file)
@@ -204,7 +204,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_SUPPORTED_LIST:
-               DBG("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
+               DBG("%s: OID_GEN_SUPPORTED_LIST\n", __func__);
                length = sizeof (oid_supported_list);
                count  = length / sizeof (u32);
                for (i = 0; i < count; i++)
@@ -214,7 +214,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_HARDWARE_STATUS:
-               DBG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);
+               DBG("%s: OID_GEN_HARDWARE_STATUS\n", __func__);
                /* Bogus question!
                 * Hardware must be ready to receive high level protocols.
                 * BTW:
@@ -227,14 +227,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_MEDIA_SUPPORTED:
-               DBG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__);
                *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
                retval = 0;
                break;
 
        /* mandatory */
        case OID_GEN_MEDIA_IN_USE:
-               DBG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MEDIA_IN_USE\n", __func__);
                /* one medium, one transport... (maybe you do it better) */
                *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
                retval = 0;
@@ -242,7 +242,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_MAXIMUM_FRAME_SIZE:
-               DBG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__);
                if (rndis_per_dev_params [configNr].dev) {
                        *outbuf = cpu_to_le32 (
                                rndis_per_dev_params [configNr].dev->mtu);
@@ -253,7 +253,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_LINK_SPEED:
                if (rndis_debug > 1)
-                       DBG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
+                       DBG("%s: OID_GEN_LINK_SPEED\n", __func__);
                if (rndis_per_dev_params [configNr].media_state
                                == NDIS_MEDIA_STATE_DISCONNECTED)
                        *outbuf = __constant_cpu_to_le32 (0);
@@ -265,7 +265,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_TRANSMIT_BLOCK_SIZE:
-               DBG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
+               DBG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__);
                if (rndis_per_dev_params [configNr].dev) {
                        *outbuf = cpu_to_le32 (
                                rndis_per_dev_params [configNr].dev->mtu);
@@ -275,7 +275,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_RECEIVE_BLOCK_SIZE:
-               DBG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
+               DBG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__);
                if (rndis_per_dev_params [configNr].dev) {
                        *outbuf = cpu_to_le32 (
                                rndis_per_dev_params [configNr].dev->mtu);
@@ -285,7 +285,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_VENDOR_ID:
-               DBG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
+               DBG("%s: OID_GEN_VENDOR_ID\n", __func__);
                *outbuf = cpu_to_le32 (
                        rndis_per_dev_params [configNr].vendorID);
                retval = 0;
@@ -293,7 +293,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_VENDOR_DESCRIPTION:
-               DBG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__);
+               DBG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
                length = strlen (rndis_per_dev_params [configNr].vendorDescr);
                memcpy (outbuf,
                        rndis_per_dev_params [configNr].vendorDescr, length);
@@ -301,7 +301,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_VENDOR_DRIVER_VERSION:
-               DBG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
+               DBG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __func__);
                /* Created as LE */
                *outbuf = rndis_driver_version;
                retval = 0;
@@ -309,14 +309,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_CURRENT_PACKET_FILTER:
-               DBG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
+               DBG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
                *outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter);
                retval = 0;
                break;
 
        /* mandatory */
        case OID_GEN_MAXIMUM_TOTAL_SIZE:
-               DBG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__);
                *outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
                retval = 0;
                break;
@@ -324,14 +324,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)
-                       DBG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
+                       DBG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
                *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                                .media_state);
                retval = 0;
                break;
 
        case OID_GEN_PHYSICAL_MEDIUM:
-               DBG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
+               DBG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__);
                *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
@@ -341,7 +341,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 */
-               DBG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MAC_OPTIONS\n", __func__);
                *outbuf = __constant_cpu_to_le32(
                          NDIS_MAC_OPTION_RECEIVE_SERIALIZED
                        | NDIS_MAC_OPTION_FULL_DUPLEX);
@@ -353,7 +353,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_XMIT_OK:
                if (rndis_debug > 1)
-                       DBG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
+                       DBG("%s: OID_GEN_XMIT_OK\n", __func__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (
                            rndis_per_dev_params [configNr].stats->tx_packets -
@@ -366,7 +366,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_RCV_OK:
                if (rndis_debug > 1)
-                       DBG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
+                       DBG("%s: OID_GEN_RCV_OK\n", __func__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (
                            rndis_per_dev_params [configNr].stats->rx_packets -
@@ -379,7 +379,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_XMIT_ERROR:
                if (rndis_debug > 1)
-                       DBG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
+                       DBG("%s: OID_GEN_XMIT_ERROR\n", __func__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->tx_errors);
@@ -390,7 +390,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_RCV_ERROR:
                if (rndis_debug > 1)
-                       DBG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
+                       DBG("%s: OID_GEN_RCV_ERROR\n", __func__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_errors);
@@ -400,7 +400,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_RCV_NO_BUFFER:
-               DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
+               DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __func__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_dropped);
@@ -410,7 +410,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 #ifdef RNDIS_OPTIONAL_STATS
        case OID_GEN_DIRECTED_BYTES_XMIT:
-               DBG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__);
+               DBG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __func__);
                /*
                 * Aunt Tilly's size of shoes
                 * minus antarctica count of penguins
@@ -430,7 +430,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_DIRECTED_FRAMES_XMIT:
-               DBG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);
+               DBG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __func__);
                /* dito */
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (
@@ -446,7 +446,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_MULTICAST_BYTES_XMIT:
-               DBG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __func__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->multicast*1234);
@@ -455,7 +455,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_MULTICAST_FRAMES_XMIT:
-               DBG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __func__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->multicast);
@@ -464,7 +464,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_BROADCAST_BYTES_XMIT:
-               DBG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
+               DBG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __func__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->tx_packets/42*255);
@@ -473,7 +473,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_BROADCAST_FRAMES_XMIT:
-               DBG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
+               DBG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __func__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->tx_packets/42);
@@ -482,19 +482,19 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_DIRECTED_BYTES_RCV:
-               DBG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
+               DBG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __func__);
                *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
 
        case OID_GEN_DIRECTED_FRAMES_RCV:
-               DBG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
+               DBG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __func__);
                *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
 
        case OID_GEN_MULTICAST_BYTES_RCV:
-               DBG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __func__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->multicast * 1111);
@@ -503,7 +503,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_MULTICAST_FRAMES_RCV:
-               DBG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
+               DBG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __func__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->multicast);
@@ -512,7 +512,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_BROADCAST_BYTES_RCV:
-               DBG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
+               DBG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __func__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_packets/42*255);
@@ -521,7 +521,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_BROADCAST_FRAMES_RCV:
-               DBG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
+               DBG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __func__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_packets/42);
@@ -530,7 +530,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_RCV_CRC_ERROR:
-               DBG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
+               DBG("%s: OID_GEN_RCV_CRC_ERROR\n", __func__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_crc_errors);
@@ -539,7 +539,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_TRANSMIT_QUEUE_LENGTH:
-               DBG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
+               DBG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __func__);
                *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
@@ -549,7 +549,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_802_3_PERMANENT_ADDRESS:
-               DBG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);
+               DBG("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__);
                if (rndis_per_dev_params [configNr].dev) {
                        length = ETH_ALEN;
                        memcpy (outbuf,
@@ -561,7 +561,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_802_3_CURRENT_ADDRESS:
-               DBG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);
+               DBG("%s: OID_802_3_CURRENT_ADDRESS\n", __func__);
                if (rndis_per_dev_params [configNr].dev) {
                        length = ETH_ALEN;
                        memcpy (outbuf,
@@ -573,7 +573,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_802_3_MULTICAST_LIST:
-               DBG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
+               DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__);
                /* Multicast base address only */
                *outbuf = __constant_cpu_to_le32 (0xE0000000);
                retval = 0;
@@ -581,21 +581,21 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_802_3_MAXIMUM_LIST_SIZE:
-               DBG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
+               DBG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
                /* Multicast base address only */
                *outbuf = __constant_cpu_to_le32 (1);
                retval = 0;
                break;
 
        case OID_802_3_MAC_OPTIONS:
-               DBG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);
+               DBG("%s: OID_802_3_MAC_OPTIONS\n", __func__);
                break;
 
        /* ieee802.3 statistics OIDs (table 4-4) */
 
        /* mandatory */
        case OID_802_3_RCV_ERROR_ALIGNMENT:
-               DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);
+               DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
                if (rndis_per_dev_params [configNr].stats) {
                        *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_frame_errors);
@@ -605,51 +605,51 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_802_3_XMIT_ONE_COLLISION:
-               DBG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
+               DBG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__);
                *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
 
        /* mandatory */
        case OID_802_3_XMIT_MORE_COLLISIONS:
-               DBG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
+               DBG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
                *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
 
 #ifdef RNDIS_OPTIONAL_STATS
        case OID_802_3_XMIT_DEFERRED:
-               DBG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);
+               DBG("%s: OID_802_3_XMIT_DEFERRED\n", __func__);
                /* TODO */
                break;
 
        case OID_802_3_XMIT_MAX_COLLISIONS:
-               DBG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__);
+               DBG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __func__);
                /* TODO */
                break;
 
        case OID_802_3_RCV_OVERRUN:
-               DBG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__);
+               DBG("%s: OID_802_3_RCV_OVERRUN\n", __func__);
                /* TODO */
                break;
 
        case OID_802_3_XMIT_UNDERRUN:
-               DBG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__);
+               DBG("%s: OID_802_3_XMIT_UNDERRUN\n", __func__);
                /* TODO */
                break;
 
        case OID_802_3_XMIT_HEARTBEAT_FAILURE:
-               DBG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__);
+               DBG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __func__);
                /* TODO */
                break;
 
        case OID_802_3_XMIT_TIMES_CRS_LOST:
-               DBG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__);
+               DBG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __func__);
                /* TODO */
                break;
 
        case OID_802_3_XMIT_LATE_COLLISIONS:
-               DBG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);
+               DBG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __func__);
                /* TODO */
                break;
 #endif /* RNDIS_OPTIONAL_STATS */
@@ -657,7 +657,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:
-               DBG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__);
+               DBG("%s: OID_PNP_CAPABILITIES\n", __func__);
 
                /* for now, no wakeup capabilities */
                length = sizeof (struct NDIS_PNP_CAPABILITIES);
@@ -665,7 +665,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                retval = 0;
                break;
        case OID_PNP_QUERY_POWER:
-               DBG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,
+               DBG("%s: OID_PNP_QUERY_POWER D%d\n", __func__,
                                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...
@@ -677,7 +677,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        default:
                pr_warning("%s: query unknown OID 0x%08X\n",
-                        __FUNCTION__, OID);
+                        __func__, OID);
        }
        if (retval < 0)
                length = 0;
@@ -729,7 +729,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));
                DBG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
-                       __FUNCTION__, *params->filter);
+                       __func__, *params->filter);
 
                /* this call has a significant side effect:  it's
                 * what makes the packet flow start and stop, like
@@ -753,7 +753,7 @@ update_linkstate:
 
        case OID_802_3_MULTICAST_LIST:
                /* I think we can ignore this */
-               DBG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
+               DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__);
                retval = 0;
                break;
 #if 0
@@ -762,7 +762,7 @@ update_linkstate:
                struct rndis_config_parameter   *param;
                param = (struct rndis_config_parameter *) buf;
                DBG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
-                       __FUNCTION__,
+                       __func__,
                        min(cpu_to_le32(param->ParameterNameLength),80),
                        buf + param->ParameterNameOffset);
                retval = 0;
@@ -778,7 +778,7 @@ update_linkstate:
                 * FIXME ... then things go batty; Windows wedges itself.
                 */
                i = le32_to_cpu(get_unaligned((__le32 *)buf));
-               DBG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1);
+               DBG("%s: OID_PNP_SET_POWER D%d\n", __func__, i - 1);
                switch (i) {
                case NdisDeviceStateD0:
                        *params->filter = params->saved_filter;
@@ -802,7 +802,7 @@ update_linkstate:
 
        default:
                pr_warning("%s: set unknown OID 0x%08X, size %d\n",
-                        __FUNCTION__, OID, buf_len);
+                        __func__, OID, buf_len);
        }
 
        return retval;
@@ -855,7 +855,7 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
        rndis_query_cmplt_type *resp;
        rndis_resp_t            *r;
 
-       // DBG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID));
+       // DBG("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID));
        if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
 
        /*
@@ -908,9 +908,9 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
        BufOffset = le32_to_cpu (buf->InformationBufferOffset);
 
 #ifdef VERBOSE
-       DBG("%s: Length: %d\n", __FUNCTION__, BufLength);
-       DBG("%s: Offset: %d\n", __FUNCTION__, BufOffset);
-       DBG("%s: InfoBuffer: ", __FUNCTION__);
+       DBG("%s: Length: %d\n", __func__, BufLength);
+       DBG("%s: Offset: %d\n", __func__, BufOffset);
+       DBG("%s: InfoBuffer: ", __func__);
 
        for (i = 0; i < BufLength; i++) {
                DBG("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
@@ -1080,14 +1080,14 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
        switch (MsgType) {
        case REMOTE_NDIS_INITIALIZE_MSG:
                DBG("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
-                       __FUNCTION__ );
+                       __func__ );
                params->state = RNDIS_INITIALIZED;
                return  rndis_init_response (configNr,
                                        (rndis_init_msg_type *) buf);
 
        case REMOTE_NDIS_HALT_MSG:
                DBG("%s: REMOTE_NDIS_HALT_MSG\n",
-                       __FUNCTION__ );
+                       __func__ );
                params->state = RNDIS_UNINITIALIZED;
                if (params->dev) {
                        netif_carrier_off (params->dev);
@@ -1105,7 +1105,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
 
        case REMOTE_NDIS_RESET_MSG:
                DBG("%s: REMOTE_NDIS_RESET_MSG\n",
-                       __FUNCTION__ );
+                       __func__ );
                return rndis_reset_response (configNr,
                                        (rndis_reset_msg_type *) buf);
 
@@ -1113,7 +1113,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
                /* For USB: host does this every 5 seconds */
                if (rndis_debug > 1)
                        DBG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
-                               __FUNCTION__ );
+                               __func__ );
                return rndis_keepalive_response (configNr,
                                                 (rndis_keepalive_msg_type *)
                                                 buf);
@@ -1124,7 +1124,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
                 * suspending itself.
                 */
                pr_warning("%s: unknown RNDIS message 0x%08X len %d\n",
-                       __FUNCTION__ , MsgType, MsgLength);
+                       __func__ , MsgType, MsgLength);
                {
                        unsigned i;
                        for (i = 0; i < MsgLength; i += 16) {
@@ -1159,7 +1159,7 @@ 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;
-                       DBG("%s: configNr = %d\n", __FUNCTION__, i);
+                       DBG("%s: configNr = %d\n", __func__, i);
                        return i;
                }
        }
@@ -1170,7 +1170,7 @@ int rndis_register (int (* rndis_control_ack) (struct net_device *))
 
 void rndis_deregister (int configNr)
 {
-       DBG("%s: \n", __FUNCTION__ );
+       DBG("%s: \n", __func__ );
 
        if (configNr >= RNDIS_MAX_CONFIGS) return;
        rndis_per_dev_params [configNr].used = 0;
@@ -1182,7 +1182,7 @@ int rndis_set_param_dev (u8 configNr, struct net_device *dev,
                         struct net_device_stats *stats,
                         u16 *cdc_filter)
 {
-       DBG("%s:\n", __FUNCTION__ );
+       DBG("%s:\n", __func__ );
        if (!dev || !stats) return -1;
        if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
@@ -1195,7 +1195,7 @@ int rndis_set_param_dev (u8 configNr, struct net_device *dev,
 
 int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
 {
-       DBG("%s:\n", __FUNCTION__ );
+       DBG("%s:\n", __func__ );
        if (!vendorDescr) return -1;
        if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
@@ -1207,7 +1207,7 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
 
 int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
 {
-       DBG("%s: %u %u\n", __FUNCTION__, medium, speed);
+       DBG("%s: %u %u\n", __func__, medium, speed);
        if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
        rndis_per_dev_params [configNr].medium = medium;
@@ -1403,7 +1403,7 @@ static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
 #endif /* CONFIG_USB_GADGET_DEBUG_FILES */
 
 
-int __devinit rndis_init (void)
+int __init rndis_init (void)
 {
        u8 i;
 
@@ -1415,7 +1415,7 @@ int __devinit rndis_init (void)
                if (!(rndis_connect_state [i]
                                = create_proc_entry (name, 0660, NULL)))
                {
-                       DBG("%s :remove entries", __FUNCTION__);
+                       DBG("%s :remove entries", __func__);
                        while (i) {
                                sprintf (name, NAME_TEMPLATE, --i);
                                remove_proc_entry (name, NULL);
index f5c3896b1d959a5cbf66e705ba21038ef51553e5..433b3f44f42e2dc36e38e2b7dc85be3e48b3785a 100644 (file)
@@ -2163,8 +2163,7 @@ static void gs_free_ports(struct gs_dev *dev)
                                port->port_dev = NULL;
                                wake_up_interruptible(&port->port_write_wait);
                                if (port->port_tty) {
-                                       wake_up_interruptible(&port->port_tty->read_wait);
-                                       wake_up_interruptible(&port->port_tty->write_wait);
+                                       tty_hangup(port->port_tty);
                                }
                                spin_unlock_irqrestore(&port->port_lock, flags);
                        } else {
index bf8be2a41a4a79de02ac9507d3621f8d4b3a9c8b..0b87480dd713af0671575ce9cd055b00350ad384 100644 (file)
@@ -30,8 +30,8 @@ config USB_EHCI_HCD
          module will be called ehci-hcd.
 
 config USB_EHCI_ROOT_HUB_TT
-       bool "Root Hub Transaction Translators (EXPERIMENTAL)"
-       depends on USB_EHCI_HCD && EXPERIMENTAL
+       bool "Root Hub Transaction Translators"
+       depends on USB_EHCI_HCD
        ---help---
          Some EHCI chips have vendor-specific extensions to integrate
          transaction translators, so that no OHCI or UHCI companion
@@ -260,3 +260,9 @@ config USB_R8A66597_HCD
          To compile this driver as a module, choose M here: the
          module will be called r8a66597-hcd.
 
+config SUPERH_ON_CHIP_R8A66597
+       boolean "Enable SuperH on-chip USB like the R8A66597"
+       depends on USB_R8A66597_HCD && CPU_SUBTYPE_SH7366
+       help
+          Renesas SuperH processor has USB like the R8A66597.
+          This driver supported processor is SH7366.
index da7532d38bf1622044ed654147d25116a46a9b26..8b5f991e949c09371c541f18f445eb2024355b0d 100644 (file)
@@ -237,6 +237,7 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
        if (usb_disabled())
                return -ENODEV;
 
+       /* FIXME we only want one one probe() not two */
        ret = usb_ehci_au1xxx_probe(&ehci_au1xxx_hc_driver, &hcd, pdev);
        return ret;
 }
@@ -245,6 +246,7 @@ static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
 {
        struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
+       /* FIXME we only want one one remove() not two */
        usb_ehci_au1xxx_remove(hcd, pdev);
        return 0;
 }
@@ -265,7 +267,7 @@ static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
        return 0;
 }
 */
-MODULE_ALIAS("au1xxx-ehci");
+MODULE_ALIAS("platform:au1xxx-ehci");
 static struct platform_driver ehci_hcd_au1xxx_driver = {
        .probe = ehci_hcd_au1xxx_drv_probe,
        .remove = ehci_hcd_au1xxx_drv_remove,
@@ -274,6 +276,5 @@ static struct platform_driver ehci_hcd_au1xxx_driver = {
        /*.resume       = ehci_hcd_au1xxx_drv_resume, */
        .driver = {
                .name = "au1xxx-ehci",
-               .bus = &platform_bus_type
        }
 };
index 64ebfc5548a31c04735bcb428aa040a68e4a2598..4af90df8e7dec7e2aa3ea96a88b8de05de1a9f12 100644 (file)
@@ -27,7 +27,7 @@
 #define ehci_warn(ehci, fmt, args...) \
        dev_warn (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
 
-#ifdef EHCI_VERBOSE_DEBUG
+#ifdef VERBOSE_DEBUG
 #      define vdbg dbg
 #      define ehci_vdbg ehci_dbg
 #else
@@ -670,7 +670,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
 
        spin_lock_irqsave (&ehci->lock, flags);
 
-       if (buf->bus->controller->power.power_state.event) {
+       if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
                size = scnprintf (next, size,
                        "bus %s, device %s (driver " DRIVER_VERSION ")\n"
                        "%s\n"
index adb0defa1631f0de75baaf6d1777119c1ba0d434..6d9bed6c1f48f23e07729c37e2139f4d701c4d00 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * (C) Copyright David Brownell 2000-2002
  * Copyright (c) 2005 MontaVista Software
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -28,7 +27,6 @@
 /* FIXME: Power Management is un-ported so temporarily disable it */
 #undef CONFIG_PM
 
-/* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
 
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
@@ -331,6 +329,7 @@ static int ehci_fsl_drv_probe(struct platform_device *pdev)
        if (usb_disabled())
                return -ENODEV;
 
+       /* FIXME we only want one one probe() not two */
        return usb_hcd_fsl_probe(&ehci_fsl_hc_driver, pdev);
 }
 
@@ -338,12 +337,12 @@ static int ehci_fsl_drv_remove(struct platform_device *pdev)
 {
        struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
+       /* FIXME we only want one one remove() not two */
        usb_hcd_fsl_remove(hcd, pdev);
-
        return 0;
 }
 
-MODULE_ALIAS("fsl-ehci");
+MODULE_ALIAS("platform:fsl-ehci");
 
 static struct platform_driver ehci_fsl_driver = {
        .probe = ehci_fsl_drv_probe,
@@ -351,5 +350,5 @@ static struct platform_driver ehci_fsl_driver = {
        .shutdown = usb_hcd_platform_shutdown,
        .driver = {
                   .name = "fsl-ehci",
-                  },
+       },
 };
index 85074cb36f38001ac5d4faa8543c8e8bf7eda175..369a8a5ea7bb374da2776dd3a02587b0f58b06fb 100644 (file)
  * Special thanks to Intel and VIA for providing host controllers to
  * test this driver on, and Cypress (including In-System Design) for
  * providing early devices for those host controllers to talk to!
- *
- * HISTORY:
- *
- * 2004-05-10 Root hub and PCI suspend/resume support; remote wakeup. (db)
- * 2004-02-24 Replace pci_* with generic dma_* API calls (dsaxena@plexity.net)
- * 2003-12-29 Rewritten high speed iso transfer support (by Michal Sojka,
- *     <sojkam@centrum.cz>, updates by DB).
- *
- * 2002-11-29  Correct handling for hw async_next register.
- * 2002-08-06  Handling for bulk and interrupt transfers is mostly shared;
- *     only scheduling is different, no arbitrary limitations.
- * 2002-07-25  Sanity check PCI reads, mostly for better cardbus support,
- *     clean up HC run state handshaking.
- * 2002-05-24  Preliminary FS/LS interrupts, using scheduling shortcuts
- * 2002-05-11  Clear TT errors for FS/LS ctrl/bulk.  Fill in some other
- *     missing pieces:  enabling 64bit dma, handoff from BIOS/SMM.
- * 2002-05-07  Some error path cleanups to report better errors; wmb();
- *     use non-CVS version id; better iso bandwidth claim.
- * 2002-04-19  Control/bulk/interrupt submit no longer uses giveback() on
- *     errors in submit path.  Bugfixes to interrupt scheduling/processing.
- * 2002-03-05  Initial high-speed ISO support; reduce ITD memory; shift
- *     more checking to generic hcd framework (db).  Make it work with
- *     Philips EHCI; reduce PCI traffic; shorten IRQ path (Rory Bolt).
- * 2002-01-14  Minor cleanup; version synch.
- * 2002-01-08  Fix roothub handoff of FS/LS to companion controllers.
- * 2002-01-04  Control/Bulk queuing behaves.
- *
- * 2001-12-12  Initial patch version for Linux 2.5.1 kernel.
- * 2001-June   Works with usb-storage and NEC EHCI on 2.4
  */
 
 #define DRIVER_VERSION "10 Dec 2004"
@@ -95,7 +66,7 @@
 static const char      hcd_name [] = "ehci_hcd";
 
 
-#undef EHCI_VERBOSE_DEBUG
+#undef VERBOSE_DEBUG
 #undef EHCI_URB_TRACE
 
 #ifdef DEBUG
@@ -174,6 +145,16 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
        return -ETIMEDOUT;
 }
 
+static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr,
+                                      u32 mask, u32 done, int usec)
+{
+       int error = handshake(ehci, ptr, mask, done, usec);
+       if (error)
+               ehci_to_hcd(ehci)->state = HC_STATE_HALT;
+
+       return error;
+}
+
 /* force HC to halt state from unknown (EHCI spec section 2.3) */
 static int ehci_halt (struct ehci_hcd *ehci)
 {
@@ -246,11 +227,9 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
        /* wait for any schedule enables/disables to take effect */
        temp = ehci_readl(ehci, &ehci->regs->command) << 10;
        temp &= STS_ASS | STS_PSS;
-       if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS,
-                               temp, 16 * 125) != 0) {
-               ehci_to_hcd(ehci)->state = HC_STATE_HALT;
+       if (handshake_on_error_set_halt(ehci, &ehci->regs->status,
+                                       STS_ASS | STS_PSS, temp, 16 * 125))
                return;
-       }
 
        /* then disable anything that's still active */
        temp = ehci_readl(ehci, &ehci->regs->command);
@@ -258,11 +237,8 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
        ehci_writel(ehci, temp, &ehci->regs->command);
 
        /* hardware can take 16 microframes to turn off ... */
-       if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS,
-                               0, 16 * 125) != 0) {
-               ehci_to_hcd(ehci)->state = HC_STATE_HALT;
-               return;
-       }
+       handshake_on_error_set_halt(ehci, &ehci->regs->status,
+                                   STS_ASS | STS_PSS, 0, 16 * 125);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -355,17 +331,13 @@ static void ehci_turn_off_all_ports(struct ehci_hcd *ehci)
                                &ehci->regs->port_status[port]);
 }
 
-/* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
- * This forcibly disables dma and IRQs, helping kexec and other cases
- * where the next system software may expect clean state.
+/*
+ * Halt HC, turn off all ports, and let the BIOS use the companion controllers.
+ * Should be called with ehci->lock held.
  */
-static void
-ehci_shutdown (struct usb_hcd *hcd)
+static void ehci_silence_controller(struct ehci_hcd *ehci)
 {
-       struct ehci_hcd *ehci;
-
-       ehci = hcd_to_ehci (hcd);
-       (void) ehci_halt (ehci);
+       ehci_halt(ehci);
        ehci_turn_off_all_ports(ehci);
 
        /* make BIOS/etc use companion controller during reboot */
@@ -375,6 +347,22 @@ ehci_shutdown (struct usb_hcd *hcd)
        ehci_readl(ehci, &ehci->regs->configured_flag);
 }
 
+/* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
+ * This forcibly disables dma and IRQs, helping kexec and other cases
+ * where the next system software may expect clean state.
+ */
+static void ehci_shutdown(struct usb_hcd *hcd)
+{
+       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+       del_timer_sync(&ehci->watchdog);
+       del_timer_sync(&ehci->iaa_watchdog);
+
+       spin_lock_irq(&ehci->lock);
+       ehci_silence_controller(ehci);
+       spin_unlock_irq(&ehci->lock);
+}
+
 static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
 {
        unsigned port;
@@ -425,15 +413,15 @@ static void ehci_work (struct ehci_hcd *ehci)
                timer_action (ehci, TIMER_IO_WATCHDOG);
 }
 
+/*
+ * Called when the ehci_hcd module is removed.
+ */
 static void ehci_stop (struct usb_hcd *hcd)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
 
        ehci_dbg (ehci, "stop\n");
 
-       /* Turn off port power on all root hub ports. */
-       ehci_port_power (ehci, 0);
-
        /* no more interrupts ... */
        del_timer_sync (&ehci->watchdog);
        del_timer_sync(&ehci->iaa_watchdog);
@@ -442,13 +430,10 @@ static void ehci_stop (struct usb_hcd *hcd)
        if (HC_IS_RUNNING (hcd->state))
                ehci_quiesce (ehci);
 
+       ehci_silence_controller(ehci);
        ehci_reset (ehci);
-       ehci_writel(ehci, 0, &ehci->regs->intr_enable);
        spin_unlock_irq(&ehci->lock);
 
-       /* let companion controllers work when we aren't */
-       ehci_writel(ehci, 0, &ehci->regs->configured_flag);
-
        remove_companion_file(ehci);
        remove_debug_files (ehci);
 
@@ -676,7 +661,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
        cmd = ehci_readl(ehci, &ehci->regs->command);
        bh = 0;
 
-#ifdef EHCI_VERBOSE_DEBUG
+#ifdef VERBOSE_DEBUG
        /* unrequested/ignored: Frame List Rollover */
        dbg_status (ehci, "irq", status);
 #endif
@@ -710,6 +695,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
        /* remote wakeup [4.3.1] */
        if (status & STS_PCD) {
                unsigned        i = HCS_N_PORTS (ehci->hcs_params);
+
+               /* kick root hub later */
                pcd_status = status;
 
                /* resume root hub? */
@@ -738,8 +725,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
 
        /* PCI errors [4.15.2.4] */
        if (unlikely ((status & STS_FATAL) != 0)) {
-               /* bogus "fatal" IRQs appear on some chips... why?  */
-               status = ehci_readl(ehci, &ehci->regs->status);
                dbg_cmd (ehci, "fatal", ehci_readl(ehci,
                                                   &ehci->regs->command));
                dbg_status (ehci, "fatal", status);
@@ -758,7 +743,7 @@ dead:
        if (bh)
                ehci_work (ehci);
        spin_unlock (&ehci->lock);
-       if (pcd_status & STS_PCD)
+       if (pcd_status)
                usb_hcd_poll_rh_status(hcd);
        return IRQ_HANDLED;
 }
@@ -788,8 +773,14 @@ static int ehci_urb_enqueue (
        INIT_LIST_HEAD (&qtd_list);
 
        switch (usb_pipetype (urb->pipe)) {
-       // case PIPE_CONTROL:
-       // case PIPE_BULK:
+       case PIPE_CONTROL:
+               /* qh_completions() code doesn't handle all the fault cases
+                * in multi-TD control transfers.  Even 1KB is rare anyway.
+                */
+               if (urb->transfer_buffer_length > (16 * 1024))
+                       return -EMSGSIZE;
+               /* FALLTHROUGH */
+       /* case PIPE_BULK: */
        default:
                if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
                        return -ENOMEM;
index 4e065e556e4b802c8c83a507973fb31a56931460..efffef64f59daf68ecc80d571921cbb10f8a566e 100644 (file)
@@ -28,7 +28,9 @@
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef CONFIG_USB_PERSIST
+#define        PORT_WAKE_BITS  (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
+
+#ifdef CONFIG_PM
 
 static int ehci_hub_control(
        struct usb_hcd  *hcd,
@@ -104,15 +106,6 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
        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)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
@@ -158,10 +151,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
                }
 
                /* enable remote wakeup on all ports */
-               if (device_may_wakeup(&hcd->self.root_hub->dev))
-                       t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
+               if (hcd->self.root_hub->do_remote_wakeup)
+                       t2 |= PORT_WAKE_BITS;
                else
-                       t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
+                       t2 &= ~PORT_WAKE_BITS;
 
                if (t1 != t2) {
                        ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
@@ -183,7 +176,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
 
        /* allow remote wakeup */
        mask = INTR_MASK;
-       if (!device_may_wakeup(&hcd->self.root_hub->dev))
+       if (!hcd->self.root_hub->do_remote_wakeup)
                mask &= ~STS_PCD;
        ehci_writel(ehci, mask, &ehci->regs->intr_enable);
        ehci_readl(ehci, &ehci->regs->intr_enable);
@@ -241,8 +234,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
        i = HCS_N_PORTS (ehci->hcs_params);
        while (i--) {
                temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
-               temp &= ~(PORT_RWC_BITS
-                       | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
+               temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
                if (test_bit(i, &ehci->bus_suspended) &&
                                (temp & PORT_SUSPEND)) {
                        ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
@@ -281,9 +273,7 @@ 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);
+       ehci_handover_companion_ports(ehci);
        return 0;
 }
 
@@ -545,8 +535,6 @@ ehci_hub_descriptor (
 
 /*-------------------------------------------------------------------------*/
 
-#define        PORT_WAKE_BITS  (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
-
 static int ehci_hub_control (
        struct usb_hcd  *hcd,
        u16             typeReq,
@@ -778,7 +766,7 @@ static int ehci_hub_control (
                if (temp & PORT_POWER)
                        status |= 1 << USB_PORT_FEAT_POWER;
 
-#ifndef        EHCI_VERBOSE_DEBUG
+#ifndef        VERBOSE_DEBUG
        if (status & ~0xffff)   /* only if wPortChange is interesting */
 #endif
                dbg_port (ehci, "GetStatus", wIndex + 1, temp);
@@ -812,8 +800,6 @@ static int ehci_hub_control (
                        if ((temp & PORT_PE) == 0
                                        || (temp & PORT_RESET) != 0)
                                goto error;
-                       if (device_may_wakeup(&hcd->self.root_hub->dev))
-                               temp |= PORT_WAKE_BITS;
                        ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
                        break;
                case USB_PORT_FEAT_POWER:
index 3041d8f055f46990d29ee7c2c662631c2719ce6e..601c8795a8541362fe05edfca2923a98df64ac81 100644 (file)
@@ -140,13 +140,12 @@ static int ixp4xx_ehci_remove(struct platform_device *pdev)
        return 0;
 }
 
-MODULE_ALIAS("ixp4xx-ehci");
+MODULE_ALIAS("platform:ixp4xx-ehci");
 
 static struct platform_driver ixp4xx_ehci_driver = {
        .probe = ixp4xx_ehci_probe,
        .remove = ixp4xx_ehci_remove,
        .driver = {
                .name = "ixp4xx-ehci",
-               .bus = &platform_bus_type
        },
 };
index 72ccd56e36dd46665712ea26d5944312f8a10635..5bb7f6bb13f340a80f5fbd746e515f792fabe370 100644 (file)
@@ -130,6 +130,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
        case PCI_VENDOR_ID_TDI:
                if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
                        ehci->is_tdi_rh_tt = 1;
+                       hcd->has_tt = 1;
                        tdi_reset(ehci);
                }
                break;
@@ -221,6 +222,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                ehci_warn(ehci, "selective suspend/wakeup unavailable\n");
 #endif
 
+       ehci_port_power(ehci, 1);
        retval = ehci_pci_reinit(ehci, pdev);
 done:
        return retval;
@@ -299,7 +301,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
        if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
                int     mask = INTR_MASK;
 
-               if (!device_may_wakeup(&hcd->self.root_hub->dev))
+               if (!hcd->self.root_hub->do_remote_wakeup)
                        mask &= ~STS_PCD;
                ehci_writel(ehci, mask, &ehci->regs->intr_enable);
                ehci_readl(ehci, &ehci->regs->intr_enable);
@@ -329,7 +331,6 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
 
        /* 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;
@@ -353,8 +354,8 @@ static const struct hc_driver ehci_pci_hc_driver = {
        .reset =                ehci_pci_setup,
        .start =                ehci_run,
 #ifdef CONFIG_PM
-       .suspend =              ehci_pci_suspend,
-       .resume =               ehci_pci_resume,
+       .pci_suspend =          ehci_pci_suspend,
+       .pci_resume =           ehci_pci_resume,
 #endif
        .stop =                 ehci_stop,
        .shutdown =             ehci_shutdown,
index a3249078c8085af2d7aa28be8fb739c2e8fcb788..6c76036783a175804673728aef8054d189ea8236 100644 (file)
@@ -175,6 +175,7 @@ static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
        if (usb_disabled())
                return -ENODEV;
 
+       /* FIXME we only want one one probe() not two */
        ret = usb_ehci_ppc_soc_probe(&ehci_ppc_soc_hc_driver, &hcd, pdev);
        return ret;
 }
@@ -183,17 +184,17 @@ static int ehci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
 {
        struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
+       /* FIXME we only want one one remove() not two */
        usb_ehci_ppc_soc_remove(hcd, pdev);
        return 0;
 }
 
-MODULE_ALIAS("ppc-soc-ehci");
+MODULE_ALIAS("platform: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 bbda58eb881304052be475a0604c682cd87d6041..69782221bcf358edd99607dbcbf843cb5c371ea6 100644 (file)
@@ -125,7 +125,6 @@ static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
                goto fail_irq;
        }
 
-       dev->core.power.power_state = PMSG_ON;
        dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */
 
        hcd = usb_create_hcd(&ps3_ehci_hc_driver, &dev->core, dev->core.bus_id);
index 2e49de820b1494b054dfc5c4cd92ad75c5aad2ef..5ae689139dd08f8a92bd21e65439a9943cc540f6 100644 (file)
@@ -242,7 +242,8 @@ __acquires(ehci->lock)
        if (unlikely(urb->unlinked)) {
                COUNT(ehci->stats.unlink);
        } else {
-               if (likely(status == -EINPROGRESS))
+               /* report non-error and short read status as zero */
+               if (status == -EINPROGRESS || status == -EREMOTEIO)
                        status = 0;
                COUNT(ehci->stats.complete);
        }
@@ -250,7 +251,7 @@ __acquires(ehci->lock)
 #ifdef EHCI_URB_TRACE
        ehci_dbg (ehci,
                "%s %s urb %p ep%d%s status %d len %d/%d\n",
-               __FUNCTION__, urb->dev->devpath, urb,
+               __func__, urb->dev->devpath, urb,
                usb_pipeendpoint (urb->pipe),
                usb_pipein (urb->pipe) ? "in" : "out",
                status,
@@ -283,7 +284,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
        int                     last_status = -EINPROGRESS;
        int                     stopped;
        unsigned                count = 0;
-       int                     do_status = 0;
        u8                      state;
        u32                     halt = HALT_BIT(ehci);
 
@@ -309,7 +309,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
                struct ehci_qtd *qtd;
                struct urb      *urb;
                u32             token = 0;
-               int             qtd_status;
 
                qtd = list_entry (entry, struct ehci_qtd, qtd_list);
                urb = qtd->urb;
@@ -336,11 +335,20 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
                /* always clean up qtds the hc de-activated */
                if ((token & QTD_STS_ACTIVE) == 0) {
 
+                       /* on STALL, error, and short reads this urb must
+                        * complete and all its qtds must be recycled.
+                        */
                        if ((token & QTD_STS_HALT) != 0) {
                                stopped = 1;
 
                        /* magic dummy for some short reads; qh won't advance.
                         * that silicon quirk can kick in with this dummy too.
+                        *
+                        * other short reads won't stop the queue, including
+                        * control transfers (status stage handles that) or
+                        * most other single-qtd reads ... the queue stops if
+                        * URB_SHORT_NOT_OK was set so the driver submitting
+                        * the urbs could clean it up.
                         */
                        } else if (IS_SHORT_READ (token)
                                        && !(qtd->hw_alt_next
@@ -354,28 +362,21 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
                                && HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) {
                        break;
 
+               /* scan the whole queue for unlinks whenever it stops */
                } else {
                        stopped = 1;
 
-                       if (unlikely (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)))
+                       /* cancel everything if we halt, suspend, etc */
+                       if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))
                                last_status = -ESHUTDOWN;
 
-                       /* ignore active urbs unless some previous qtd
-                        * for the urb faulted (including short read) or
-                        * its urb was canceled.  we may patch qh or qtds.
+                       /* this qtd is active; skip it unless a previous qtd
+                        * for its urb faulted, or its urb was canceled.
                         */
-                       if (likely(last_status == -EINPROGRESS &&
-                                       !urb->unlinked))
-                               continue;
-
-                       /* issue status after short control reads */
-                       if (unlikely (do_status != 0)
-                                       && QTD_PID (token) == 0 /* OUT */) {
-                               do_status = 0;
+                       else if (last_status == -EINPROGRESS && !urb->unlinked)
                                continue;
-                       }
 
-                       /* token in overlay may be most current */
+                       /* qh unlinked; token in overlay may be most current */
                        if (state == QH_STATE_IDLE
                                        && cpu_to_hc32(ehci, qtd->qtd_dma)
                                                == qh->hw_current)
@@ -392,21 +393,32 @@ halt:
                        }
                }
 
-               /* remove it from the queue */
-               qtd_status = qtd_copy_status(ehci, urb, qtd->length, token);
-               if (unlikely(qtd_status == -EREMOTEIO)) {
-                       do_status = (!urb->unlinked &&
-                                       usb_pipecontrol(urb->pipe));
-                       qtd_status = 0;
+               /* unless we already know the urb's status, collect qtd status
+                * and update count of bytes transferred.  in common short read
+                * cases with only one data qtd (including control transfers),
+                * queue processing won't halt.  but with two or more qtds (for
+                * example, with a 32 KB transfer), when the first qtd gets a
+                * short read the second must be removed by hand.
+                */
+               if (last_status == -EINPROGRESS) {
+                       last_status = qtd_copy_status(ehci, urb,
+                                       qtd->length, token);
+                       if (last_status == -EREMOTEIO
+                                       && (qtd->hw_alt_next
+                                               & EHCI_LIST_END(ehci)))
+                               last_status = -EINPROGRESS;
                }
-               if (likely(last_status == -EINPROGRESS))
-                       last_status = qtd_status;
 
+               /* if we're removing something not at the queue head,
+                * patch the hardware queue pointer.
+                */
                if (stopped && qtd->qtd_list.prev != &qh->qtd_list) {
                        last = list_entry (qtd->qtd_list.prev,
                                        struct ehci_qtd, qtd_list);
                        last->hw_next = qtd->hw_next;
                }
+
+               /* remove qtd; it's recycled after possible urb completion */
                list_del (&qtd->qtd_list);
                last = qtd;
        }
@@ -431,7 +443,15 @@ halt:
                        qh_refresh(ehci, qh);
                        break;
                case QH_STATE_LINKED:
-                       /* should be rare for periodic transfers,
+                       /* We won't refresh a QH that's linked (after the HC
+                        * stopped the queue).  That avoids a race:
+                        *  - HC reads first part of QH;
+                        *  - CPU updates that first part and the token;
+                        *  - HC reads rest of that QH, including token
+                        * Result:  HC gets an inconsistent image, and then
+                        * DMAs to/from the wrong memory (corrupting it).
+                        *
+                        * That should be rare for interrupt transfers,
                         * except maybe high bandwidth ...
                         */
                        if ((cpu_to_hc32(ehci, QH_SMASK)
@@ -549,6 +569,12 @@ qh_urb_transaction (
                this_qtd_len = qtd_fill(ehci, qtd, buf, len, token, maxpacket);
                len -= this_qtd_len;
                buf += this_qtd_len;
+
+               /*
+                * short reads advance to a "magic" dummy instead of the next
+                * qtd ... that forces the queue to stop, for manual cleanup.
+                * (this will usually be overridden later.)
+                */
                if (is_input)
                        qtd->hw_alt_next = ehci->async->hw_alt_next;
 
@@ -568,8 +594,10 @@ qh_urb_transaction (
                list_add_tail (&qtd->qtd_list, head);
        }
 
-       /* unless the bulk/interrupt caller wants a chance to clean
-        * up after short reads, hc should advance qh past this urb
+       /*
+        * unless the caller requires manual cleanup after short reads,
+        * have the alt_next mechanism keep the queue running after the
+        * last data qtd (the only one, for control and most other cases).
         */
        if (likely ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0
                                || usb_pipecontrol (urb->pipe)))
@@ -657,6 +685,14 @@ qh_make (
        type = usb_pipetype (urb->pipe);
        maxp = usb_maxpacket (urb->dev, urb->pipe, !is_input);
 
+       /* 1024 byte maxpacket is a hardware ceiling.  High bandwidth
+        * acts like up to 3KB, but is built from smaller packets.
+        */
+       if (max_packet(maxp) > 1024) {
+               ehci_dbg(ehci, "bogus qh maxpacket %d\n", max_packet(maxp));
+               goto done;
+       }
+
        /* Compute interrupt scheduling parameters just once, and save.
         * - allowing for high bandwidth, how many nsec/uframe are used?
         * - split transactions need a second CSPLIT uframe; same question
@@ -757,7 +793,13 @@ qh_make (
                        info2 |= (EHCI_TUNE_MULT_HS << 30);
                } else if (type == PIPE_BULK) {
                        info1 |= (EHCI_TUNE_RL_HS << 28);
-                       info1 |= 512 << 16;     /* usb2 fixed maxpacket */
+                       /* The USB spec says that high speed bulk endpoints
+                        * always use 512 byte maxpacket.  But some device
+                        * vendors decided to ignore that, and MSFT is happy
+                        * to help them do so.  So now people expect to use
+                        * such nonconformant devices with Linux too; sigh.
+                        */
+                       info1 |= max_packet(maxp) << 16;
                        info2 |= (EHCI_TUNE_MULT_HS << 30);
                } else {                /* PIPE_INTERRUPT */
                        info1 |= max_packet (maxp) << 16;
@@ -932,7 +974,7 @@ submit_async (
 #ifdef EHCI_URB_TRACE
        ehci_dbg (ehci,
                "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
-               __FUNCTION__, urb->dev->devpath, urb,
+               __func__, urb->dev->devpath, urb,
                epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
                urb->transfer_buffer_length,
                qtd, urb->ep->hcpriv);
index 8a8e08a51ba33cd55b57c127d550d7c54e40a5ca..be575e46eac3132a661479a9138fcf64ea3a73ae 100644 (file)
@@ -440,11 +440,10 @@ static int enable_periodic (struct ehci_hcd *ehci)
        /* did clearing PSE did take effect yet?
         * takes effect only at frame boundaries...
         */
-       status = handshake(ehci, &ehci->regs->status, STS_PSS, 0, 9 * 125);
-       if (status != 0) {
-               ehci_to_hcd(ehci)->state = HC_STATE_HALT;
+       status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
+                                            STS_PSS, 0, 9 * 125);
+       if (status)
                return status;
-       }
 
        cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE;
        ehci_writel(ehci, cmd, &ehci->regs->command);
@@ -465,11 +464,10 @@ static int disable_periodic (struct ehci_hcd *ehci)
        /* did setting PSE not take effect yet?
         * takes effect only at frame boundaries...
         */
-       status = handshake(ehci, &ehci->regs->status, STS_PSS, STS_PSS, 9 * 125);
-       if (status != 0) {
-               ehci_to_hcd(ehci)->state = HC_STATE_HALT;
+       status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
+                                            STS_PSS, STS_PSS, 9 * 125);
+       if (status)
                return status;
-       }
 
        cmd = ehci_readl(ehci, &ehci->regs->command) & ~CMD_PSE;
        ehci_writel(ehci, cmd, &ehci->regs->command);
@@ -1183,21 +1181,18 @@ itd_urb_transaction (
                                        struct ehci_itd, itd_list);
                        list_del (&itd->itd_list);
                        itd_dma = itd->itd_dma;
-               } else
-                       itd = NULL;
-
-               if (!itd) {
+               } else {
                        spin_unlock_irqrestore (&ehci->lock, flags);
                        itd = dma_pool_alloc (ehci->itd_pool, mem_flags,
                                        &itd_dma);
                        spin_lock_irqsave (&ehci->lock, flags);
+                       if (!itd) {
+                               iso_sched_free(stream, sched);
+                               spin_unlock_irqrestore(&ehci->lock, flags);
+                               return -ENOMEM;
+                       }
                }
 
-               if (unlikely (NULL == itd)) {
-                       iso_sched_free (stream, sched);
-                       spin_unlock_irqrestore (&ehci->lock, flags);
-                       return -ENOMEM;
-               }
                memset (itd, 0, sizeof *itd);
                itd->itd_dma = itd_dma;
                list_add (&itd->itd_list, &sched->td_list);
@@ -1682,7 +1677,7 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
 #ifdef EHCI_URB_TRACE
        ehci_dbg (ehci,
                "%s %s urb %p ep%d%s len %d, %d pkts %d uframes [%p]\n",
-               __FUNCTION__, urb->dev->devpath, urb,
+               __func__, urb->dev->devpath, urb,
                usb_pipeendpoint (urb->pipe),
                usb_pipein (urb->pipe) ? "in" : "out",
                urb->transfer_buffer_length,
@@ -1816,21 +1811,18 @@ sitd_urb_transaction (
                                         struct ehci_sitd, sitd_list);
                        list_del (&sitd->sitd_list);
                        sitd_dma = sitd->sitd_dma;
-               } else
-                       sitd = NULL;
-
-               if (!sitd) {
+               } else {
                        spin_unlock_irqrestore (&ehci->lock, flags);
                        sitd = dma_pool_alloc (ehci->sitd_pool, mem_flags,
                                        &sitd_dma);
                        spin_lock_irqsave (&ehci->lock, flags);
+                       if (!sitd) {
+                               iso_sched_free(stream, iso_sched);
+                               spin_unlock_irqrestore(&ehci->lock, flags);
+                               return -ENOMEM;
+                       }
                }
 
-               if (!sitd) {
-                       iso_sched_free (stream, iso_sched);
-                       spin_unlock_irqrestore (&ehci->lock, flags);
-                       return -ENOMEM;
-               }
                memset (sitd, 0, sizeof *sitd);
                sitd->sitd_dma = sitd_dma;
                list_add (&sitd->sitd_list, &iso_sched->td_list);
index 203a3359a648db28cea4ee6984115b242e9817cc..20b9a0d07420d986f7dfc1e2edb9329a175083cc 100644 (file)
@@ -1400,7 +1400,7 @@ static int isp116x_bus_suspend(struct usb_hcd *hcd)
                spin_unlock_irqrestore(&isp116x->lock, flags);
                val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
                val |= HCCONTROL_USB_SUSPEND;
-               if (device_may_wakeup(&hcd->self.root_hub->dev))
+               if (hcd->self.root_hub->do_remote_wakeup)
                        val |= HCCONTROL_RWE;
                /* Wait for usb transfers to finish */
                msleep(2);
@@ -1442,11 +1442,6 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
                break;
        case HCCONTROL_USB_OPER:
                spin_unlock_irq(&isp116x->lock);
-               /* Without setting power_state here the
-                  SUSPENDED state won't be removed from
-                  sysfs/usbN/power.state as a response to remote
-                  wakeup. Maybe in the future. */
-               hcd->self.root_hub->dev.power.power_state = PMSG_ON;
                return 0;
        default:
                /* HCCONTROL_USB_RESET: this may happen, when during
@@ -1460,7 +1455,6 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
                if ((isp116x->rhdesca & RH_A_NDP) == 2)
                        isp116x_hub_control(hcd, SetPortFeature,
                                            USB_PORT_FEAT_POWER, 2, NULL, 0);
-               hcd->self.root_hub->dev.power.power_state = PMSG_ON;
                return 0;
        }
 
@@ -1486,8 +1480,6 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
        isp116x_write_reg32(isp116x, HCCONTROL,
                            (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
        spin_unlock_irq(&isp116x->lock);
-       /* see analogous comment above */
-       hcd->self.root_hub->dev.power.power_state = PMSG_ON;
        hcd->state = HC_STATE_RUNNING;
 
        return 0;
@@ -1663,7 +1655,6 @@ static int __devinit isp116x_probe(struct platform_device *pdev)
 static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
 {
        VDBG("%s: state %x\n", __func__, state.event);
-       dev->dev.power.power_state = state;
        return 0;
 }
 
@@ -1672,8 +1663,7 @@ static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
 */
 static int isp116x_resume(struct platform_device *dev)
 {
-       VDBG("%s:  state %x\n", __func__, dev->power.power_state.event);
-       dev->dev.power.power_state = PMSG_ON;
+       VDBG("%s\n", __func__);
        return 0;
 }
 
index d72dc07dda017de12a51eaedc68b9c0626d26cb3..c96db1153dcf6d595d2e42fc3bc3c18899f7b187 100644 (file)
@@ -261,7 +261,6 @@ static const struct hc_driver ohci_at91_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -348,6 +347,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
        if (!clocked)
                at91_start_clock();
 
+       ohci_finish_controller_resume(hcd);
        return 0;
 }
 #else
index f90fe0c7373f046d7677d48350e177731daef514..1b9abdba920b9d18a8a53723a8eabc58342eaf0d 100644 (file)
@@ -288,7 +288,6 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index a22c30aa745d69f1a15b3fa85d844a2d768f99ce..e06bfaebec5416d52e1510d472ebc62a219f52ed 100644 (file)
@@ -655,7 +655,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
                hcd->product_desc,
                hcd_name);
 
-       if (bus->controller->power.power_state.event) {
+       if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
                size -= scnprintf (next, size,
                        "SUSPENDED (no register access)\n");
                goto done;
index 156e93a9d0df3f3ee2ee96c7fc29241e9885a05c..06aadfb0ec29a4683830a1d47191174e3f99b500 100644 (file)
@@ -135,7 +135,6 @@ static struct hc_driver ohci_ep93xx_hc_driver = {
        .get_frame_number       = ohci_get_frame,
        .hub_status_data        = ohci_hub_status_data,
        .hub_control            = ohci_hub_control,
-       .hub_irq_enable         = ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend            = ohci_bus_suspend,
        .bus_resume             = ohci_bus_resume,
@@ -177,7 +176,6 @@ static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_
 
        ep93xx_stop_hc(&pdev->dev);
        hcd->state = HC_STATE_SUSPENDED;
-       pdev->dev.power.power_state = PMSG_SUSPEND;
 
        return 0;
 }
@@ -193,9 +191,8 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
        ohci->next_statechange = jiffies;
 
        ep93xx_start_hc(&pdev->dev);
-       pdev->dev.power.power_state = PMSG_ON;
-       usb_hcd_resume_root_hub(hcd);
 
+       ohci_finish_controller_resume(hcd);
        return 0;
 }
 #endif
index 48e4b11f4d3ea53a2d837636e5ae72de4a0724af..5be3bb3e6a9d791aa6262af9e429f724f20066f3 100644 (file)
 
 /*-------------------------------------------------------------------------*/
 
-/* hcd->hub_irq_enable() */
-static void ohci_rhsc_enable (struct usb_hcd *hcd)
-{
-       struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
-
-       spin_lock_irq(&ohci->lock);
-       if (!ohci->autostop)
-               del_timer(&hcd->rh_timer);      /* Prevent next poll */
-       ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
-       spin_unlock_irq(&ohci->lock);
-}
-
 #define OHCI_SCHED_ENABLES \
        (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
 
@@ -103,11 +91,11 @@ __acquires(ohci->lock)
        finish_unlinks (ohci, ohci_frame_no(ohci));
 
        /* maybe resume can wake root hub */
-       if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev) ||
-                       autostop)
+       if (ohci_to_hcd(ohci)->self.root_hub->do_remote_wakeup || autostop) {
                ohci->hc_control |= OHCI_CTRL_RWE;
-       else {
-               ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
+       } else {
+               ohci_writel(ohci, OHCI_INTR_RHSC | OHCI_INTR_RD,
+                               &ohci->regs->intrdisable);
                ohci->hc_control &= ~OHCI_CTRL_RWE;
        }
 
@@ -326,23 +314,76 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
        return rc;
 }
 
+/* Carry out the final steps of resuming the controller device */
+static void ohci_finish_controller_resume(struct usb_hcd *hcd)
+{
+       struct ohci_hcd         *ohci = hcd_to_ohci(hcd);
+       int                     port;
+       bool                    need_reinit = false;
+
+       /* See if the controller is already running or has been reset */
+       ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
+       if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
+               need_reinit = true;
+       } else {
+               switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+               case OHCI_USB_OPER:
+               case OHCI_USB_RESET:
+                       need_reinit = true;
+               }
+       }
+
+       /* If needed, reinitialize and suspend the root hub */
+       if (need_reinit) {
+               spin_lock_irq(&ohci->lock);
+               hcd->state = HC_STATE_RESUMING;
+               ohci_rh_resume(ohci);
+               hcd->state = HC_STATE_QUIESCING;
+               ohci_rh_suspend(ohci, 0);
+               hcd->state = HC_STATE_SUSPENDED;
+               spin_unlock_irq(&ohci->lock);
+       }
+
+       /* Normally just turn on port power and enable interrupts */
+       else {
+               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]);
+
+               ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable);
+               ohci_readl(ohci, &ohci->regs->intrenable);
+               msleep(20);
+       }
+}
+
 /* Carry out polling-, autostop-, and autoresume-related state changes */
 static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
                int any_connected)
 {
        int     poll_rh = 1;
+       int     rhsc;
 
+       rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC;
        switch (ohci->hc_control & OHCI_CTRL_HCFS) {
 
        case OHCI_USB_OPER:
-               /* keep on polling until we know a device is connected
-                * and RHSC is enabled */
+               /* If no status changes are pending, enable status-change
+                * interrupts.
+                */
+               if (!rhsc && !changed) {
+                       rhsc = OHCI_INTR_RHSC;
+                       ohci_writel(ohci, rhsc, &ohci->regs->intrenable);
+               }
+
+               /* Keep on polling until we know a device is connected
+                * and RHSC is enabled, or until we autostop.
+                */
                if (!ohci->autostop) {
                        if (any_connected ||
                                        !device_may_wakeup(&ohci_to_hcd(ohci)
                                                ->self.root_hub->dev)) {
-                               if (ohci_readl(ohci, &ohci->regs->intrenable) &
-                                               OHCI_INTR_RHSC)
+                               if (rhsc)
                                        poll_rh = 0;
                        } else {
                                ohci->autostop = 1;
@@ -355,12 +396,13 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
                                ohci->autostop = 0;
                                ohci->next_statechange = jiffies +
                                                STATECHANGE_DELAY;
-                       } else if (time_after_eq(jiffies,
+                       } else if (rhsc && time_after_eq(jiffies,
                                                ohci->next_statechange)
                                        && !ohci->ed_rm_list
                                        && !(ohci->hc_control &
                                                OHCI_SCHED_ENABLES)) {
                                ohci_rh_suspend(ohci, 1);
+                               poll_rh = 0;
                        }
                }
                break;
@@ -374,6 +416,12 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
                        else
                                usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
                } else {
+                       if (!rhsc && (ohci->autostop ||
+                                       ohci_to_hcd(ohci)->self.root_hub->
+                                               do_remote_wakeup))
+                               ohci_writel(ohci, OHCI_INTR_RHSC,
+                                               &ohci->regs->intrenable);
+
                        /* everything is idle, no need for polling */
                        poll_rh = 0;
                }
@@ -395,12 +443,16 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci)
 static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
                int any_connected)
 {
-       int     poll_rh = 1;
-
-       /* keep on polling until RHSC is enabled */
+       /* If RHSC is enabled, don't poll */
        if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
-               poll_rh = 0;
-       return poll_rh;
+               return 0;
+
+       /* If no status changes are pending, enable status-change interrupts */
+       if (!changed) {
+               ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+               return 0;
+       }
+       return 1;
 }
 
 #endif /* CONFIG_PM */
@@ -564,14 +616,18 @@ static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
        u32     temp;
        u16     now = ohci_readl(ohci, &ohci->regs->fmnumber);
        u16     reset_done = now + PORT_RESET_MSEC;
+       int     limit_1 = DIV_ROUND_UP(PORT_RESET_MSEC, PORT_RESET_HW_MSEC);
 
        /* build a "continuous enough" reset signal, with up to
         * 3msec gap between pulses.  scheduler HZ==100 must work;
         * this might need to be deadline-scheduled.
         */
        do {
+               int limit_2;
+
                /* spin until any current reset finishes */
-               for (;;) {
+               limit_2 = PORT_RESET_HW_MSEC * 2;
+               while (--limit_2 >= 0) {
                        temp = ohci_readl (ohci, portstat);
                        /* handle e.g. CardBus eject */
                        if (temp == ~(u32)0)
@@ -581,6 +637,17 @@ static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
                        udelay (500);
                }
 
+               /* timeout (a hardware error) has been observed when
+                * EHCI sets CF while this driver is resetting a port;
+                * presumably other disconnect paths might do it too.
+                */
+               if (limit_2 < 0) {
+                       ohci_dbg(ohci,
+                               "port[%d] reset timeout, stat %08x\n",
+                               port, temp);
+                       break;
+               }
+
                if (!(temp & RH_PS_CCS))
                        break;
                if (temp & RH_PS_PRSC)
@@ -590,8 +657,11 @@ static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
                ohci_writel (ohci, RH_PS_PRS, portstat);
                msleep(PORT_RESET_HW_MSEC);
                now = ohci_readl(ohci, &ohci->regs->fmnumber);
-       } while (tick_before(now, reset_done));
-       /* caller synchronizes using PRSC */
+       } while (tick_before(now, reset_done) && --limit_1 >= 0);
+
+       /* caller synchronizes using PRSC ... and handles PRS
+        * still being set when this returns.
+        */
 
        return 0;
 }
index 13c12ed22252cc90c1ace3319410819a5e111937..96d14fa1d8331b7ee2a587d9138246b99e4bceec 100644 (file)
@@ -193,7 +193,6 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index 7bfca1ed1b585e73413fbba86aaf16a5d9c3c42f..6859fb5f1d6f6a5d2f9dd29b0c3d063697c15233 100644 (file)
@@ -466,7 +466,6 @@ static const struct hc_driver ohci_omap_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -505,21 +504,20 @@ static int ohci_omap_suspend(struct platform_device *dev, pm_message_t message)
 
        omap_ohci_clock_power(0);
        ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
-       dev->dev.power.power_state = PMSG_SUSPEND;
        return 0;
 }
 
 static int ohci_omap_resume(struct platform_device *dev)
 {
-       struct ohci_hcd *ohci = hcd_to_ohci(platform_get_drvdata(dev));
+       struct usb_hcd  *hcd = platform_get_drvdata(dev);
+       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
 
        if (time_before(jiffies, ohci->next_statechange))
                msleep(5);
        ohci->next_statechange = jiffies;
 
        omap_ohci_clock_power(1);
-       dev->dev.power.power_state = PMSG_ON;
-       usb_hcd_resume_root_hub(platform_get_drvdata(dev));
+       ohci_finish_controller_resume(hcd);
        return 0;
 }
 
index d0360f65ebd99951243d8d7cbd1cfe1683419c8a..3bf175d95a2303b17d80a3561fc38a727ce13c84 100644 (file)
@@ -238,42 +238,6 @@ 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)
@@ -313,10 +277,7 @@ 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);
-
-       /* FIXME: we should try to detect loss of VBUS power here */
-       prepare_for_handover(hcd);
-
+       ohci_finish_controller_resume(hcd);
        return 0;
 }
 
@@ -345,9 +306,8 @@ static const struct hc_driver ohci_pci_hc_driver = {
        .shutdown =             ohci_shutdown,
 
 #ifdef CONFIG_PM
-       /* these suspend/resume entries are for upstream PCI glue ONLY */
-       .suspend =              ohci_pci_suspend,
-       .resume =               ohci_pci_resume,
+       .pci_suspend =          ohci_pci_suspend,
+       .pci_resume =           ohci_pci_resume,
 #endif
 
        /*
@@ -367,7 +327,6 @@ static const struct hc_driver ohci_pci_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index 28b458f20cc3013749503821119e5e741e58a85f..664f07ee87320e2a568c727d95bbf82b8d446894 100644 (file)
@@ -280,7 +280,6 @@ static const struct hc_driver ohci_pnx4008_hc_driver = {
         */
        .hub_status_data = ohci_hub_status_data,
        .hub_control = ohci_hub_control,
-       .hub_irq_enable = ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend = ohci_bus_suspend,
        .bus_resume = ohci_bus_resume,
index 605d59cba28e79d46bbbb3215cfc9ccd1b6f6a5b..28467e288a93d54607c7cb244e1e904dc6136395 100644 (file)
@@ -201,7 +201,6 @@ static const struct hc_driver ohci_pnx8550_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index a6725279122315bf7566b255164d29c7f8130bbd..50e55db13636ece797f64ae65e1a01a58800fabe 100644 (file)
@@ -72,7 +72,6 @@ static const struct hc_driver ohci_ppc_of_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index 523c30125577d39a8c24287ce30ae2b2532929e2..cd3398b675b2dea8c2402fd2178cee58c23a52e4 100644 (file)
@@ -172,7 +172,6 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index 01a0caeaa6bcc9345b74131baa03d3acfb956439..bfdeb0d22d050576755f6d1054d9d4b561bb7e3a 100644 (file)
@@ -68,7 +68,6 @@ static const struct hc_driver ps3_ohci_hc_driver = {
        .get_frame_number       = ohci_get_frame,
        .hub_status_data        = ohci_hub_status_data,
        .hub_control            = ohci_hub_control,
-       .hub_irq_enable         = ohci_rhsc_enable,
        .start_port_reset       = ohci_start_port_reset,
 #if defined(CONFIG_PM)
        .bus_suspend            = ohci_bus_suspend,
@@ -127,7 +126,6 @@ static int ps3_ohci_probe(struct ps3_system_bus_device *dev)
                goto fail_irq;
        }
 
-       dev->core.power.power_state = PMSG_ON;
        dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */
 
        hcd = usb_create_hcd(&ps3_ohci_hc_driver, &dev->core, dev->core.bus_id);
index 8ad9b3b604b5e0aeb9185281af70649617c7b48d..70b0d4b459e753bf13ed622eb32fd7b458c9d38c 100644 (file)
@@ -298,7 +298,6 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef  CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -339,7 +338,6 @@ static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *pdev, pm_message_
 
        pxa27x_stop_hc(&pdev->dev);
        hcd->state = HC_STATE_SUSPENDED;
-       pdev->dev.power.power_state = PMSG_SUSPEND;
 
        return 0;
 }
@@ -357,9 +355,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
        if ((status = pxa27x_start_hc(&pdev->dev)) < 0)
                return status;
 
-       pdev->dev.power.power_state = PMSG_ON;
-       usb_hcd_resume_root_hub(hcd);
-
+       ohci_finish_controller_resume(hcd);
        return 0;
 }
 #endif
index ead4772f0f277c0f1447636e682392612ca65aa3..a73d2ff322e28d862184ad83188da0302386f61c 100644 (file)
@@ -466,7 +466,6 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
         */
        .hub_status_data =      ohci_s3c2410_hub_status_data,
        .hub_control =          ohci_s3c2410_hub_control,
-       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index 0f48f2d992263f199ad889e31f8e0f3bf0c4f48d..99438c65981b4f8cd98e87066092c2ea1b9251b3 100644 (file)
@@ -231,7 +231,6 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index e7ee607278fece8b92570beb5b839e74ca8aa2db..60f03cc7ec4f20a4f80d228b59faebe715ae1148 100644 (file)
@@ -68,7 +68,6 @@ static const struct hc_driver ohci_sh_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index 4ea92762fb289521431431c8af5ae8b3475b5261..77204f001b9a6eefcce60ee54b241aa364013f38 100644 (file)
@@ -75,7 +75,6 @@ static const struct hc_driver ohci_sm501_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -199,7 +198,8 @@ static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev)
        usb_put_hcd(hcd);
        dma_release_declared_memory(&pdev->dev);
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       release_mem_region(mem->start, mem->end - mem->start + 1);
+       if (mem)
+               release_mem_region(mem->start, mem->end - mem->start + 1);
 
        /* mask interrupts and disable power */
 
@@ -224,24 +224,26 @@ static int ohci_sm501_suspend(struct platform_device *pdev, pm_message_t msg)
 
        sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 0);
        ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
-       dev->power.power_state = PMSG_SUSPEND;
        return 0;
 }
 
 static int ohci_sm501_resume(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       struct ohci_hcd *ohci = hcd_to_ohci(platform_get_drvdata(pdev));
+       struct usb_hcd  *hcd = platform_get_drvdata(pdev);
+       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
 
        if (time_before(jiffies, ohci->next_statechange))
                msleep(5);
        ohci->next_statechange = jiffies;
 
        sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
-       dev->power.power_state = PMSG_ON;
-       usb_hcd_resume_root_hub(platform_get_drvdata(pdev));
+       ohci_finish_controller_resume(hcd);
        return 0;
 }
+#else
+#define ohci_sm501_suspend NULL
+#define ohci_sm501_resume NULL
 #endif
 
 /*-------------------------------------------------------------------------*/
@@ -253,10 +255,8 @@ static struct platform_driver ohci_hcd_sm501_driver = {
        .probe          = ohci_hcd_sm501_drv_probe,
        .remove         = ohci_hcd_sm501_drv_remove,
        .shutdown       = usb_hcd_platform_shutdown,
-#ifdef CONFIG_PM
        .suspend        = ohci_sm501_suspend,
        .resume         = ohci_sm501_resume,
-#endif
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "sm501-usb",
index 6e9c2d6db88756370c5b2f7d9a1bf9cc5d2beabe..c4265caec78023993e62607c5be548560d34fbf4 100644 (file)
@@ -60,36 +60,6 @@ static int ssb_ohci_start(struct usb_hcd *hcd)
        return err;
 }
 
-#ifdef CONFIG_PM
-static int ssb_ohci_hcd_suspend(struct usb_hcd *hcd, pm_message_t message)
-{
-       struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
-       struct ohci_hcd *ohci = &ohcidev->ohci;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ohci->lock, flags);
-
-       ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
-       ohci_readl(ohci, &ohci->regs->intrdisable); /* commit write */
-
-       /* make sure snapshot being resumed re-enumerates everything */
-       if (message.event == PM_EVENT_PRETHAW)
-               ohci_usb_reset(ohci);
-
-       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
-       spin_unlock_irqrestore(&ohci->lock, flags);
-       return 0;
-}
-
-static int ssb_ohci_hcd_resume(struct usb_hcd *hcd)
-{
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-       usb_hcd_resume_root_hub(hcd);
-       return 0;
-}
-#endif /* CONFIG_PM */
-
 static const struct hc_driver ssb_ohci_hc_driver = {
        .description            = "ssb-usb-ohci",
        .product_desc           = "SSB OHCI Controller",
@@ -103,11 +73,6 @@ static const struct hc_driver ssb_ohci_hc_driver = {
        .stop                   = ohci_stop,
        .shutdown               = ohci_shutdown,
 
-#ifdef CONFIG_PM
-       .suspend                = ssb_ohci_hcd_suspend,
-       .resume                 = ssb_ohci_hcd_resume,
-#endif
-
        .urb_enqueue            = ohci_urb_enqueue,
        .urb_dequeue            = ohci_urb_dequeue,
        .endpoint_disable       = ohci_endpoint_disable,
@@ -116,7 +81,6 @@ static const struct hc_driver ssb_ohci_hc_driver = {
 
        .hub_status_data        = ohci_hub_status_data,
        .hub_control            = ohci_hub_control,
-       .hub_irq_enable         = ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend            = ohci_bus_suspend,
        .bus_resume             = ohci_bus_resume,
@@ -224,6 +188,7 @@ static int ssb_ohci_resume(struct ssb_device *dev)
 
        ssb_device_enable(dev, ohcidev->enable_flags);
 
+       ohci_finish_controller_resume(hcd);
        return 0;
 }
 
index 0ee694f043cc9b84d0a6aef45980a97212da1fdc..ae6e70edd745769700e8dc9d7d20057ce371817c 100644 (file)
@@ -106,7 +106,7 @@ int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base)
        pci_read_config_word(pdev, UHCI_USBLEGSUP, &legsup);
        if (legsup & ~(UHCI_USBLEGSUP_RO | UHCI_USBLEGSUP_RWC)) {
                dev_dbg(&pdev->dev, "%s: legsup = 0x%04x\n",
-                               __FUNCTION__, legsup);
+                               __func__, legsup);
                goto reset_needed;
        }
 
@@ -114,14 +114,14 @@ int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base)
        if ((cmd & UHCI_USBCMD_RUN) || !(cmd & UHCI_USBCMD_CONFIGURE) ||
                        !(cmd & UHCI_USBCMD_EGSM)) {
                dev_dbg(&pdev->dev, "%s: cmd = 0x%04x\n",
-                               __FUNCTION__, cmd);
+                               __func__, cmd);
                goto reset_needed;
        }
 
        intr = inw(base + UHCI_USBINTR);
        if (intr & (~UHCI_USBINTR_RESUME)) {
                dev_dbg(&pdev->dev, "%s: intr = 0x%04x\n",
-                               __FUNCTION__, intr);
+                               __func__, intr);
                goto reset_needed;
        }
        return 0;
index 9f80e528557529c9a33f2da13085b546872028ec..f4fa93dabdde99d77d3e632876b4d22ba5c80a83 100644 (file)
@@ -46,15 +46,17 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Yoshihiro Shimoda");
 MODULE_ALIAS("platform:r8a66597_hcd");
 
-#define DRIVER_VERSION "29 May 2007"
+#define DRIVER_VERSION "10 Apr 2008"
 
 static const char hcd_name[] = "r8a66597_hcd";
 
 /* module parameters */
+#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
 static unsigned short clock = XTAL12;
 module_param(clock, ushort, 0644);
 MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 "
                "(default=0)");
+#endif
 
 static unsigned short vif = LDRV;
 module_param(vif, ushort, 0644);
@@ -106,11 +108,22 @@ static void set_devadd_reg(struct r8a66597 *r8a66597, u8 r8a66597_address,
        r8a66597_write(r8a66597, val, devadd_reg);
 }
 
-static int enable_controller(struct r8a66597 *r8a66597)
+static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
 {
        u16 tmp;
        int i = 0;
 
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+       do {
+               r8a66597_write(r8a66597, SCKE, SYSCFG0);
+               tmp = r8a66597_read(r8a66597, SYSCFG0);
+               if (i++ > 1000) {
+                       err("register access fail.");
+                       return -ENXIO;
+               }
+       } while ((tmp & SCKE) != SCKE);
+       r8a66597_write(r8a66597, 0x04, 0x02);
+#else
        do {
                r8a66597_write(r8a66597, USBE, SYSCFG0);
                tmp = r8a66597_read(r8a66597, SYSCFG0);
@@ -132,13 +145,63 @@ static int enable_controller(struct r8a66597 *r8a66597)
                        return -ENXIO;
                }
        } while ((tmp & SCKE) != SCKE);
+#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
+
+       return 0;
+}
+
+static void r8a66597_clock_disable(struct r8a66597 *r8a66597)
+{
+       r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
+       udelay(1);
+#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+       r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
+       r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
+       r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+#endif
+}
+
+static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port)
+{
+       u16 val;
+
+       val = port ? DRPD : DCFM | DRPD;
+       r8a66597_bset(r8a66597, val, get_syscfg_reg(port));
+       r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
+
+       r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, get_dmacfg_reg(port));
+       r8a66597_bclr(r8a66597, DTCHE, get_intenb_reg(port));
+       r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
+}
 
-       r8a66597_bset(r8a66597, DCFM | DRPD, SYSCFG0);
-       r8a66597_bset(r8a66597, DRPD, SYSCFG1);
+static void r8a66597_disable_port(struct r8a66597 *r8a66597, int port)
+{
+       u16 val, tmp;
+
+       r8a66597_write(r8a66597, 0, get_intenb_reg(port));
+       r8a66597_write(r8a66597, 0, get_intsts_reg(port));
+
+       r8a66597_port_power(r8a66597, port, 0);
+
+       do {
+               tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS;
+               udelay(640);
+       } while (tmp == EDGESTS);
+
+       val = port ? DRPD : DCFM | DRPD;
+       r8a66597_bclr(r8a66597, val, get_syscfg_reg(port));
+       r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
+}
+
+static int enable_controller(struct r8a66597 *r8a66597)
+{
+       int ret, port;
+
+       ret = r8a66597_clock_enable(r8a66597);
+       if (ret < 0)
+               return ret;
 
        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);
@@ -146,53 +209,30 @@ static int enable_controller(struct r8a66597 *r8a66597)
        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);
+
+       for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
+               r8a66597_enable_port(r8a66597, port);
 
        return 0;
 }
 
 static void disable_controller(struct r8a66597 *r8a66597)
 {
-       u16 tmp;
+       int port;
 
        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);
+       for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
+               r8a66597_disable_port(r8a66597, port);
 
-       r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
-       udelay(1);
-       r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
-       r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
-       r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+       r8a66597_clock_disable(r8a66597);
 }
 
 static int get_parent_r8a66597_address(struct r8a66597 *r8a66597,
@@ -577,13 +617,9 @@ static void pipe_buffer_setting(struct r8a66597 *r8a66597,
                       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)
 {
@@ -715,6 +751,7 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
                                     struct r8a66597_pipe *pipe,
                                     struct urb *urb)
 {
+#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
        int i;
        struct r8a66597_pipe_info *info = &pipe->info;
 
@@ -742,6 +779,7 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
                        break;
                }
        }
+#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
 }
 
 /* this function must be called with interrupt disabled */
@@ -825,6 +863,25 @@ static void disable_r8a66597_pipe_all(struct r8a66597 *r8a66597,
        dev->dma_map = 0;
 }
 
+static unsigned long get_timer_interval(struct urb *urb, __u8 interval)
+{
+       __u8 i;
+       unsigned long time = 1;
+
+       if (usb_pipeisoc(urb->pipe))
+               return 0;
+
+       if (get_r8a66597_usb_speed(urb->dev->speed) == HSMODE) {
+               for (i = 0; i < (interval - 1); i++)
+                       time *= 2;
+               time = time * 125 / 1000;       /* uSOF -> msec */
+       } else {
+               time = interval;
+       }
+
+       return time;
+}
+
 /* this function must be called with interrupt disabled */
 static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb,
                           struct usb_host_endpoint *hep,
@@ -840,7 +897,16 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb,
                                      & USB_ENDPOINT_XFERTYPE_MASK);
        info.bufnum = get_bufnum(info.pipenum);
        info.buf_bsize = get_buf_bsize(info.pipenum);
-       info.interval = ep->bInterval;
+       if (info.type == R8A66597_BULK) {
+               info.interval = 0;
+               info.timer_interval = 0;
+       } else {
+               if (ep->bInterval > IITV)
+                       info.interval = IITV;
+               else
+                       info.interval = ep->bInterval ? ep->bInterval - 1 : 0;
+               info.timer_interval = get_timer_interval(urb, ep->bInterval);
+       }
        if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
                info.dir_in = 1;
        else
@@ -876,10 +942,19 @@ static void pipe_irq_disable(struct r8a66597 *r8a66597, u16 pipenum)
 }
 
 /* this function must be called with interrupt disabled */
-static void r8a66597_usb_preconnect(struct r8a66597 *r8a66597, int port)
+static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port,
+                                       u16 syssts)
 {
-       r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_CONNECTION)
-                                        | (1 << USB_PORT_FEAT_C_CONNECTION);
+       if (syssts == SE0) {
+               r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
+               return;
+       }
+
+       if (syssts == FS_JSTS)
+               r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
+       else if (syssts == LS_JSTS)
+               r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
+
        r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port));
        r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port));
 }
@@ -960,9 +1035,9 @@ static void prepare_packet_read(struct r8a66597 *r8a66597,
                                r8a66597_write(r8a66597, TRCLR,
                                                td->pipe->pipetre);
                                r8a66597_write(r8a66597,
-                                               (urb->transfer_buffer_length
-                                               + td->maxpacket - 1)
-                                               / td->maxpacket,
+                                               DIV_ROUND_UP
+                                                 (urb->transfer_buffer_length,
+                                                  td->maxpacket),
                                                td->pipe->pipetrn);
                                r8a66597_bset(r8a66597, TRENB,
                                                td->pipe->pipetre);
@@ -1021,8 +1096,7 @@ static void prepare_status_packet(struct r8a66597 *r8a66597,
                r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL);
                r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
                r8a66597_write(r8a66597, ~BEMP0, BEMPSTS);
-               r8a66597_write(r8a66597, BCLR, CFIFOCTR);
-               r8a66597_write(r8a66597, BVAL, CFIFOCTR);
+               r8a66597_write(r8a66597, BCLR | BVAL, CFIFOCTR);
                enable_irq_empty(r8a66597, 0);
        } else {
                r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
@@ -1454,13 +1528,21 @@ static void irq_pipe_nrdy(struct r8a66597 *r8a66597)
        }
 }
 
+static void r8a66597_root_hub_start_polling(struct r8a66597 *r8a66597)
+{
+       mod_timer(&r8a66597->rh_timer,
+                       jiffies + msecs_to_jiffies(R8A66597_RH_POLL_TIME));
+}
+
 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));
+       r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_CONNECTION)
+                                        | (1 << USB_PORT_FEAT_C_CONNECTION);
+       r8a66597_root_hub_start_polling(r8a66597);
 }
 
 static irqreturn_t r8a66597_irq(struct usb_hcd *hcd)
@@ -1547,41 +1629,55 @@ static void r8a66597_root_hub_control(struct r8a66597 *r8a66597, int port)
                if ((tmp & USBRST) == USBRST) {
                        r8a66597_mdfy(r8a66597, UACT, USBRST | UACT,
                                      dvstctr_reg);
-                       mod_timer(&r8a66597->rh_timer,
-                                 jiffies + msecs_to_jiffies(50));
+                       r8a66597_root_hub_start_polling(r8a66597);
                } else
                        r8a66597_usb_connect(r8a66597, port);
        }
 
+       if (!(rh->port & (1 << USB_PORT_FEAT_CONNECTION))) {
+               r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port));
+               r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(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));
-                       }
+                       if (rh->scount == 0)
+                               r8a66597_check_syssts(r8a66597, port, tmp);
+                       else
+                               r8a66597_root_hub_start_polling(r8a66597);
                } else {
                        rh->scount = R8A66597_MAX_SAMPLING;
                        rh->old_syssts = tmp;
-                       mod_timer(&r8a66597->rh_timer,
-                                 jiffies + msecs_to_jiffies(50));
+                       r8a66597_root_hub_start_polling(r8a66597);
                }
        }
 }
 
+static void r8a66597_interval_timer(unsigned long _r8a66597)
+{
+       struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
+       unsigned long flags;
+       u16 pipenum;
+       struct r8a66597_td *td;
+
+       spin_lock_irqsave(&r8a66597->lock, flags);
+
+       for (pipenum = 0; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+               if (!(r8a66597->interval_map & (1 << pipenum)))
+                       continue;
+               if (timer_pending(&r8a66597->interval_timer[pipenum]))
+                       continue;
+
+               td = r8a66597_get_td(r8a66597, pipenum);
+               if (td)
+                       start_transfer(r8a66597, td);
+       }
+
+       spin_unlock_irqrestore(&r8a66597->lock, flags);
+}
+
 static void r8a66597_td_timer(unsigned long _r8a66597)
 {
        struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
@@ -1763,10 +1859,17 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd,
        urb->hcpriv = td;
 
        if (request) {
-               ret = start_transfer(r8a66597, td);
-               if (ret < 0) {
-                       list_del(&td->queue);
-                       kfree(td);
+               if (td->pipe->info.timer_interval) {
+                       r8a66597->interval_map |= 1 << td->pipenum;
+                       mod_timer(&r8a66597->interval_timer[td->pipenum],
+                                 jiffies + msecs_to_jiffies(
+                                       td->pipe->info.timer_interval));
+               } else {
+                       ret = start_transfer(r8a66597, td);
+                       if (ret < 0) {
+                               list_del(&td->queue);
+                               kfree(td);
+                       }
                }
        } else
                set_td_timer(r8a66597, td);
@@ -2107,13 +2210,11 @@ static struct hc_driver r8a66597_hc_driver = {
 #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) */
@@ -2194,6 +2295,9 @@ static int __init r8a66597_probe(struct platform_device *pdev)
                init_timer(&r8a66597->td_timer[i]);
                r8a66597->td_timer[i].function = r8a66597_td_timer;
                r8a66597->td_timer[i].data = (unsigned long)r8a66597;
+               setup_timer(&r8a66597->interval_timer[i],
+                               r8a66597_interval_timer,
+                               (unsigned long)r8a66597);
        }
        INIT_LIST_HEAD(&r8a66597->child_device);
 
index 57388252b693cb7ca6e79fa75c251b1abc64f708..84ee014173151cd4f541cd5b798cf2800682afb7 100644 (file)
 #define        REW             0x4000  /* b14: Buffer rewind */
 #define        DCLRM           0x2000  /* b13: DMA buffer clear mode */
 #define        DREQE           0x1000  /* b12: DREQ output enable */
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+#define        MBW             0x0800
+#else
 #define        MBW             0x0400  /* b10: Maximum bit width for FIFO access */
+#endif
 #define          MBW_8          0x0000   /*  8bit */
 #define          MBW_16         0x0400   /* 16bit */
 #define        BIGEND          0x0100  /* b8: Big endian mode */
 #define R8A66597_MAX_NUM_PIPE          10
 #define R8A66597_BUF_BSIZE             8
 #define R8A66597_MAX_DEVICE            10
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+#define R8A66597_MAX_ROOT_HUB          1
+#else
 #define R8A66597_MAX_ROOT_HUB          2
-#define R8A66597_MAX_SAMPLING          10
+#endif
+#define R8A66597_MAX_SAMPLING          5
+#define R8A66597_RH_POLL_TIME          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 make_devsel(addr)              (addr << 12)
 
 struct r8a66597_pipe_info {
+       unsigned long timer_interval;
        u16 pipenum;
        u16 address;    /* R8A66597 HCD usb address */
        u16 epnum;
@@ -478,9 +488,11 @@ struct r8a66597 {
 
        struct timer_list rh_timer;
        struct timer_list td_timer[R8A66597_MAX_NUM_PIPE];
+       struct timer_list interval_timer[R8A66597_MAX_NUM_PIPE];
 
        unsigned short address_map;
        unsigned short timeout_map;
+       unsigned short interval_map;
        unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE];
        unsigned char dma_map;
 
@@ -526,8 +538,21 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
                                      unsigned long offset, u16 *buf,
                                      int len)
 {
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+       unsigned long fifoaddr = r8a66597->reg + offset;
+       unsigned long count;
+
+       count = len / 4;
+       insl(fifoaddr, buf, count);
+
+       if (len & 0x00000003) {
+               unsigned long tmp = inl(fifoaddr);
+               memcpy((unsigned char *)buf + count * 4, &tmp, len & 0x03);
+       }
+#else
        len = (len + 1) / 2;
        insw(r8a66597->reg + offset, buf, len);
+#endif
 }
 
 static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
@@ -541,6 +566,24 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
                                       int len)
 {
        unsigned long fifoaddr = r8a66597->reg + offset;
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+       unsigned long count;
+       unsigned char *pb;
+       int i;
+
+       count = len / 4;
+       outsl(fifoaddr, buf, count);
+
+       if (len & 0x00000003) {
+               pb = (unsigned char *)buf + count * 4;
+               for (i = 0; i < (len & 0x00000003); i++) {
+                       if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
+                               outb(pb[i], fifoaddr + i);
+                       else
+                               outb(pb[i], fifoaddr + 3 - i);
+               }
+       }
+#else
        int odd = len & 0x0001;
 
        len = len / 2;
@@ -549,6 +592,7 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
                buf = &buf[len];
                outb((unsigned char)*buf, fifoaddr);
        }
+#endif
 }
 
 static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
@@ -581,6 +625,11 @@ static inline unsigned long get_dvstctr_reg(int port)
        return port == 0 ? DVSTCTR0 : DVSTCTR1;
 }
 
+static inline unsigned long get_dmacfg_reg(int port)
+{
+       return port == 0 ? DMA0CFG : DMA1CFG;
+}
+
 static inline unsigned long get_intenb_reg(int port)
 {
        return port == 0 ? INTENB1 : INTENB2;
index 629bca0ebe8f2a56d366009597e770481f9a0770..274276cf8621664394bd7e9597d5c9c014695b18 100644 (file)
@@ -94,12 +94,10 @@ static void port_power(struct sl811 *sl811, int is_on)
 
                sl811->port1 = (1 << USB_PORT_FEAT_POWER);
                sl811->irq_enable = SL11H_INTMASK_INSRMV;
-               hcd->self.controller->power.power_state = PMSG_ON;
        } else {
                sl811->port1 = 0;
                sl811->irq_enable = 0;
                hcd->state = HC_STATE_HALT;
-               hcd->self.controller->power.power_state = PMSG_SUSPEND;
        }
        sl811->ctrl1 = 0;
        sl811_write(sl811, SL11H_IRQ_ENABLE, 0);
@@ -1337,7 +1335,7 @@ static int
 sl811h_bus_suspend(struct usb_hcd *hcd)
 {
        // SOFs off
-       DBG("%s\n", __FUNCTION__);
+       DBG("%s\n", __func__);
        return 0;
 }
 
@@ -1345,7 +1343,7 @@ static int
 sl811h_bus_resume(struct usb_hcd *hcd)
 {
        // SOFs on
-       DBG("%s\n", __FUNCTION__);
+       DBG("%s\n", __func__);
        return 0;
 }
 
@@ -1772,8 +1770,6 @@ sl811h_suspend(struct platform_device *dev, pm_message_t state)
                port_power(sl811, 0);
                break;
        }
-       if (retval == 0)
-               dev->dev.power.power_state = state;
        return retval;
 }
 
@@ -1786,15 +1782,13 @@ sl811h_resume(struct platform_device *dev)
        /* with no "check to see if VBUS is still powered" board hook,
         * let's assume it'd only be powered to enable remote wakeup.
         */
-       if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND
-                       || !device_can_wakeup(&hcd->self.root_hub->dev)) {
+       if (!sl811->port1 || !device_can_wakeup(&hcd->self.root_hub->dev)) {
                sl811->port1 = 0;
                port_power(sl811, 1);
                usb_root_hub_lost_power(hcd->self.root_hub);
                return 0;
        }
 
-       dev->dev.power.power_state = PMSG_ON;
        return sl811h_bus_resume(hcd);
 }
 
index 8e117a795e93768a878bab49c805b4a5410a77e8..f29307405bb36aa45ef4a764f9d483d99dfeef6e 100644 (file)
@@ -67,7 +67,7 @@
 #include "ohci.h"
 #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
 #define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \
-        OHCI_INTR_WDH)
+       OHCI_INTR_WDH)
 MODULE_AUTHOR("Tony Olech - Elan Digital Systems Limited");
 MODULE_DESCRIPTION("U132 USB Host Controller Driver");
 MODULE_LICENSE("GPL");
@@ -77,15 +77,15 @@ INT_MODULE_PARM(testing, 0);
 static int distrust_firmware = 1;
 module_param(distrust_firmware, bool, 0);
 MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
-        "t setup");
+       "t setup");
 static DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
 /*
 * u132_module_lock exists to protect access to global variables
 *
 */
 static struct mutex u132_module_lock;
-static int u132_exiting = 0;
-static int u132_instances = 0;
+static int u132_exiting;
+static int u132_instances;
 static struct list_head u132_static_list;
 /*
 * end of the global variables protected by u132_module_lock
@@ -97,115 +97,115 @@ static struct workqueue_struct *workqueue;
 #define MAX_U132_ENDPS 100
 #define MAX_U132_RINGS 4
 static const char *cc_to_text[16] = {
-        "No Error ",
-        "CRC Error ",
-        "Bit Stuff ",
-        "Data Togg ",
-        "Stall ",
-        "DevNotResp ",
-        "PIDCheck ",
-        "UnExpPID ",
-        "DataOver ",
-        "DataUnder ",
-        "(for hw) ",
-        "(for hw) ",
-        "BufferOver ",
-        "BuffUnder ",
-        "(for HCD) ",
-        "(for HCD) "
+       "No Error ",
+       "CRC Error ",
+       "Bit Stuff ",
+       "Data Togg ",
+       "Stall ",
+       "DevNotResp ",
+       "PIDCheck ",
+       "UnExpPID ",
+       "DataOver ",
+       "DataUnder ",
+       "(for hw) ",
+       "(for hw) ",
+       "BufferOver ",
+       "BuffUnder ",
+       "(for HCD) ",
+       "(for HCD) "
 };
 struct u132_port {
-        struct u132 *u132;
-        int reset;
-        int enable;
-        int power;
-        int Status;
+       struct u132 *u132;
+       int reset;
+       int enable;
+       int power;
+       int Status;
 };
 struct u132_addr {
-        u8 address;
+       u8 address;
 };
 struct u132_udev {
-        struct kref kref;
-        struct usb_device *usb_device;
-        u8 enumeration;
-        u8 udev_number;
-        u8 usb_addr;
-        u8 portnumber;
-        u8 endp_number_in[16];
-        u8 endp_number_out[16];
+       struct kref kref;
+       struct usb_device *usb_device;
+       u8 enumeration;
+       u8 udev_number;
+       u8 usb_addr;
+       u8 portnumber;
+       u8 endp_number_in[16];
+       u8 endp_number_out[16];
 };
 #define ENDP_QUEUE_SHIFT 3
 #define ENDP_QUEUE_SIZE (1<<ENDP_QUEUE_SHIFT)
 #define ENDP_QUEUE_MASK (ENDP_QUEUE_SIZE-1)
 struct u132_urbq {
-        struct list_head urb_more;
-        struct urb *urb;
+       struct list_head urb_more;
+       struct urb *urb;
 };
 struct u132_spin {
-        spinlock_t slock;
+       spinlock_t slock;
 };
 struct u132_endp {
-        struct kref kref;
-        u8 udev_number;
-        u8 endp_number;
-        u8 usb_addr;
-        u8 usb_endp;
-        struct u132 *u132;
-        struct list_head endp_ring;
-        struct u132_ring *ring;
-        unsigned toggle_bits:2;
-        unsigned active:1;
-        unsigned delayed:1;
-        unsigned input:1;
-        unsigned output:1;
-        unsigned pipetype:2;
-        unsigned dequeueing:1;
-        unsigned edset_flush:1;
-        unsigned spare_bits:14;
-        unsigned long jiffies;
-        struct usb_host_endpoint *hep;
-        struct u132_spin queue_lock;
-        u16 queue_size;
-        u16 queue_last;
-        u16 queue_next;
-        struct urb *urb_list[ENDP_QUEUE_SIZE];
-        struct list_head urb_more;
-        struct delayed_work scheduler;
+       struct kref kref;
+       u8 udev_number;
+       u8 endp_number;
+       u8 usb_addr;
+       u8 usb_endp;
+       struct u132 *u132;
+       struct list_head endp_ring;
+       struct u132_ring *ring;
+       unsigned toggle_bits:2;
+       unsigned active:1;
+       unsigned delayed:1;
+       unsigned input:1;
+       unsigned output:1;
+       unsigned pipetype:2;
+       unsigned dequeueing:1;
+       unsigned edset_flush:1;
+       unsigned spare_bits:14;
+       unsigned long jiffies;
+       struct usb_host_endpoint *hep;
+       struct u132_spin queue_lock;
+       u16 queue_size;
+       u16 queue_last;
+       u16 queue_next;
+       struct urb *urb_list[ENDP_QUEUE_SIZE];
+       struct list_head urb_more;
+       struct delayed_work scheduler;
 };
 struct u132_ring {
-        unsigned in_use:1;
-        unsigned length:7;
-        u8 number;
-        struct u132 *u132;
-        struct u132_endp *curr_endp;
-        struct delayed_work scheduler;
+       unsigned in_use:1;
+       unsigned length:7;
+       u8 number;
+       struct u132 *u132;
+       struct u132_endp *curr_endp;
+       struct delayed_work scheduler;
 };
 struct u132 {
-        struct kref kref;
-        struct list_head u132_list;
-        struct mutex sw_lock;
-        struct semaphore scheduler_lock;
-        struct u132_platform_data *board;
-        struct platform_device *platform_dev;
-        struct u132_ring ring[MAX_U132_RINGS];
-        int sequence_num;
-        int going;
-        int power;
-        int reset;
-        int num_ports;
-        u32 hc_control;
-        u32 hc_fminterval;
-        u32 hc_roothub_status;
-        u32 hc_roothub_a;
-        u32 hc_roothub_portstatus[MAX_ROOT_PORTS];
-        int flags;
-        unsigned long next_statechange;
-        struct delayed_work monitor;
-        int num_endpoints;
-        struct u132_addr addr[MAX_U132_ADDRS];
-        struct u132_udev udev[MAX_U132_UDEVS];
-        struct u132_port port[MAX_U132_PORTS];
-        struct u132_endp *endp[MAX_U132_ENDPS];
+       struct kref kref;
+       struct list_head u132_list;
+       struct mutex sw_lock;
+       struct mutex scheduler_lock;
+       struct u132_platform_data *board;
+       struct platform_device *platform_dev;
+       struct u132_ring ring[MAX_U132_RINGS];
+       int sequence_num;
+       int going;
+       int power;
+       int reset;
+       int num_ports;
+       u32 hc_control;
+       u32 hc_fminterval;
+       u32 hc_roothub_status;
+       u32 hc_roothub_a;
+       u32 hc_roothub_portstatus[MAX_ROOT_PORTS];
+       int flags;
+       unsigned long next_statechange;
+       struct delayed_work monitor;
+       int num_endpoints;
+       struct u132_addr addr[MAX_U132_ADDRS];
+       struct u132_udev udev[MAX_U132_UDEVS];
+       struct u132_port port[MAX_U132_PORTS];
+       struct u132_endp *endp[MAX_U132_ENDPS];
 };
 
 /*
@@ -213,34 +213,34 @@ struct u132 {
 * Does anyone have a better way?????
 */
 #define ftdi_read_pcimem(pdev, member, data) usb_ftdi_elan_read_pcimem(pdev, \
-        offsetof(struct ohci_regs, member), 0, data);
+       offsetof(struct ohci_regs, member), 0, data);
 #define ftdi_write_pcimem(pdev, member, data) usb_ftdi_elan_write_pcimem(pdev, \
-        offsetof(struct ohci_regs, member), 0, data);
+       offsetof(struct ohci_regs, member), 0, data);
 #define u132_read_pcimem(u132, member, data) \
-        usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
-        ohci_regs, member), 0, data);
+       usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
+       ohci_regs, member), 0, data);
 #define u132_write_pcimem(u132, member, data) \
-        usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
-        ohci_regs, member), 0, data);
+       usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
+       ohci_regs, member), 0, data);
 static inline struct u132 *udev_to_u132(struct u132_udev *udev)
 {
-        u8 udev_number = udev->udev_number;
-        return container_of(udev, struct u132, udev[udev_number]);
+       u8 udev_number = udev->udev_number;
+       return container_of(udev, struct u132, udev[udev_number]);
 }
 
 static inline struct u132 *hcd_to_u132(struct usb_hcd *hcd)
 {
-        return (struct u132 *)(hcd->hcd_priv);
+       return (struct u132 *)(hcd->hcd_priv);
 }
 
 static inline struct usb_hcd *u132_to_hcd(struct u132 *u132)
 {
-        return container_of((void *)u132, struct usb_hcd, hcd_priv);
+       return container_of((void *)u132, struct usb_hcd, hcd_priv);
 }
 
 static inline void u132_disable(struct u132 *u132)
 {
-        u132_to_hcd(u132)->state = HC_STATE_HALT;
+       u132_to_hcd(u132)->state = HC_STATE_HALT;
 }
 
 
@@ -250,147 +250,147 @@ static inline void u132_disable(struct u132 *u132)
 #include "../misc/usb_u132.h"
 static const char hcd_name[] = "u132_hcd";
 #define PORT_C_MASK ((USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | \
-        USB_PORT_STAT_C_SUSPEND | USB_PORT_STAT_C_OVERCURRENT | \
-        USB_PORT_STAT_C_RESET) << 16)
+       USB_PORT_STAT_C_SUSPEND | USB_PORT_STAT_C_OVERCURRENT | \
+       USB_PORT_STAT_C_RESET) << 16)
 static void u132_hcd_delete(struct kref *kref)
 {
-        struct u132 *u132 = kref_to_u132(kref);
-        struct platform_device *pdev = u132->platform_dev;
-        struct usb_hcd *hcd = u132_to_hcd(u132);
-        u132->going += 1;
-        mutex_lock(&u132_module_lock);
-        list_del_init(&u132->u132_list);
-        u132_instances -= 1;
-        mutex_unlock(&u132_module_lock);
-        dev_warn(&u132->platform_dev->dev, "FREEING the hcd=%p and thus the u13"
-                "2=%p going=%d pdev=%p\n", hcd, u132, u132->going, pdev);
-        usb_put_hcd(hcd);
+       struct u132 *u132 = kref_to_u132(kref);
+       struct platform_device *pdev = u132->platform_dev;
+       struct usb_hcd *hcd = u132_to_hcd(u132);
+       u132->going += 1;
+       mutex_lock(&u132_module_lock);
+       list_del_init(&u132->u132_list);
+       u132_instances -= 1;
+       mutex_unlock(&u132_module_lock);
+       dev_warn(&u132->platform_dev->dev, "FREEING the hcd=%p and thus the u13"
+               "2=%p going=%d pdev=%p\n", hcd, u132, u132->going, pdev);
+       usb_put_hcd(hcd);
 }
 
 static inline void u132_u132_put_kref(struct u132 *u132)
 {
-        kref_put(&u132->kref, u132_hcd_delete);
+       kref_put(&u132->kref, u132_hcd_delete);
 }
 
 static inline void u132_u132_init_kref(struct u132 *u132)
 {
-        kref_init(&u132->kref);
+       kref_init(&u132->kref);
 }
 
 static void u132_udev_delete(struct kref *kref)
 {
-        struct u132_udev *udev = kref_to_u132_udev(kref);
-        udev->udev_number = 0;
-        udev->usb_device = NULL;
-        udev->usb_addr = 0;
-        udev->enumeration = 0;
+       struct u132_udev *udev = kref_to_u132_udev(kref);
+       udev->udev_number = 0;
+       udev->usb_device = NULL;
+       udev->usb_addr = 0;
+       udev->enumeration = 0;
 }
 
 static inline void u132_udev_put_kref(struct u132 *u132, struct u132_udev *udev)
 {
-        kref_put(&udev->kref, u132_udev_delete);
+       kref_put(&udev->kref, u132_udev_delete);
 }
 
 static inline void u132_udev_get_kref(struct u132 *u132, struct u132_udev *udev)
 {
-        kref_get(&udev->kref);
+       kref_get(&udev->kref);
 }
 
 static inline void u132_udev_init_kref(struct u132 *u132,
-        struct u132_udev *udev)
+       struct u132_udev *udev)
 {
-        kref_init(&udev->kref);
+       kref_init(&udev->kref);
 }
 
 static inline void u132_ring_put_kref(struct u132 *u132, struct u132_ring *ring)
 {
-        kref_put(&u132->kref, u132_hcd_delete);
+       kref_put(&u132->kref, u132_hcd_delete);
 }
 
 static void u132_ring_requeue_work(struct u132 *u132, struct u132_ring *ring,
-        unsigned int delta)
+       unsigned int delta)
 {
-        if (delta > 0) {
-                if (queue_delayed_work(workqueue, &ring->scheduler, delta))
-                        return;
-        } else if (queue_delayed_work(workqueue, &ring->scheduler, 0))
-                return;
-        kref_put(&u132->kref, u132_hcd_delete);
-        return;
+       if (delta > 0) {
+               if (queue_delayed_work(workqueue, &ring->scheduler, delta))
+                       return;
+       } else if (queue_delayed_work(workqueue, &ring->scheduler, 0))
+               return;
+       kref_put(&u132->kref, u132_hcd_delete);
+       return;
 }
 
 static void u132_ring_queue_work(struct u132 *u132, struct u132_ring *ring,
-        unsigned int delta)
+       unsigned int delta)
 {
-        kref_get(&u132->kref);
-        u132_ring_requeue_work(u132, ring, delta);
-        return;
+       kref_get(&u132->kref);
+       u132_ring_requeue_work(u132, ring, delta);
+       return;
 }
 
 static void u132_ring_cancel_work(struct u132 *u132, struct u132_ring *ring)
 {
-        if (cancel_delayed_work(&ring->scheduler)) {
-                kref_put(&u132->kref, u132_hcd_delete);
-        }
+       if (cancel_delayed_work(&ring->scheduler))
+               kref_put(&u132->kref, u132_hcd_delete);
 }
 
 static void u132_endp_delete(struct kref *kref)
 {
-        struct u132_endp *endp = kref_to_u132_endp(kref);
-        struct u132 *u132 = endp->u132;
-        u8 usb_addr = endp->usb_addr;
-        u8 usb_endp = endp->usb_endp;
-        u8 address = u132->addr[usb_addr].address;
-        struct u132_udev *udev = &u132->udev[address];
-        u8 endp_number = endp->endp_number;
-        struct usb_host_endpoint *hep = endp->hep;
-        struct u132_ring *ring = endp->ring;
-        struct list_head *head = &endp->endp_ring;
-        ring->length -= 1;
-        if (endp == ring->curr_endp) {
-                if (list_empty(head)) {
-                        ring->curr_endp = NULL;
-                        list_del(head);
-                } else {
-                        struct u132_endp *next_endp = list_entry(head->next,
-                                struct u132_endp, endp_ring);
-                        ring->curr_endp = next_endp;
-                        list_del(head);
-        }} else
-                list_del(head);
-        if (endp->input) {
-                udev->endp_number_in[usb_endp] = 0;
-                u132_udev_put_kref(u132, udev);
-        }
-        if (endp->output) {
-                udev->endp_number_out[usb_endp] = 0;
-                u132_udev_put_kref(u132, udev);
-        }
-        u132->endp[endp_number - 1] = NULL;
-        hep->hcpriv = NULL;
-        kfree(endp);
-        u132_u132_put_kref(u132);
+       struct u132_endp *endp = kref_to_u132_endp(kref);
+       struct u132 *u132 = endp->u132;
+       u8 usb_addr = endp->usb_addr;
+       u8 usb_endp = endp->usb_endp;
+       u8 address = u132->addr[usb_addr].address;
+       struct u132_udev *udev = &u132->udev[address];
+       u8 endp_number = endp->endp_number;
+       struct usb_host_endpoint *hep = endp->hep;
+       struct u132_ring *ring = endp->ring;
+       struct list_head *head = &endp->endp_ring;
+       ring->length -= 1;
+       if (endp == ring->curr_endp) {
+               if (list_empty(head)) {
+                       ring->curr_endp = NULL;
+                       list_del(head);
+               } else {
+                       struct u132_endp *next_endp = list_entry(head->next,
+                               struct u132_endp, endp_ring);
+                       ring->curr_endp = next_endp;
+                       list_del(head);
+               }
+       } else
+               list_del(head);
+       if (endp->input) {
+               udev->endp_number_in[usb_endp] = 0;
+               u132_udev_put_kref(u132, udev);
+       }
+       if (endp->output) {
+               udev->endp_number_out[usb_endp] = 0;
+               u132_udev_put_kref(u132, udev);
+       }
+       u132->endp[endp_number - 1] = NULL;
+       hep->hcpriv = NULL;
+       kfree(endp);
+       u132_u132_put_kref(u132);
 }
 
 static inline void u132_endp_put_kref(struct u132 *u132, struct u132_endp *endp)
 {
-        kref_put(&endp->kref, u132_endp_delete);
+       kref_put(&endp->kref, u132_endp_delete);
 }
 
 static inline void u132_endp_get_kref(struct u132 *u132, struct u132_endp *endp)
 {
-        kref_get(&endp->kref);
+       kref_get(&endp->kref);
 }
 
 static inline void u132_endp_init_kref(struct u132 *u132,
-        struct u132_endp *endp)
+       struct u132_endp *endp)
 {
-        kref_init(&endp->kref);
-        kref_get(&u132->kref);
+       kref_init(&endp->kref);
+       kref_get(&u132->kref);
 }
 
 static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp,
-        unsigned int delta)
+       unsigned int delta)
 {
        if (queue_delayed_work(workqueue, &endp->scheduler, delta))
                kref_get(&endp->kref);
@@ -398,13 +398,13 @@ static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp,
 
 static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp)
 {
-        if (cancel_delayed_work(&endp->scheduler))
-                kref_put(&endp->kref, u132_endp_delete);
+       if (cancel_delayed_work(&endp->scheduler))
+               kref_put(&endp->kref, u132_endp_delete);
 }
 
 static inline void u132_monitor_put_kref(struct u132 *u132)
 {
-        kref_put(&u132->kref, u132_hcd_delete);
+       kref_put(&u132->kref, u132_hcd_delete);
 }
 
 static void u132_monitor_queue_work(struct u132 *u132, unsigned int delta)
@@ -421,200 +421,201 @@ static void u132_monitor_requeue_work(struct u132 *u132, unsigned int delta)
 
 static void u132_monitor_cancel_work(struct u132 *u132)
 {
-        if (cancel_delayed_work(&u132->monitor))
-                kref_put(&u132->kref, u132_hcd_delete);
+       if (cancel_delayed_work(&u132->monitor))
+               kref_put(&u132->kref, u132_hcd_delete);
 }
 
 static int read_roothub_info(struct u132 *u132)
 {
-        u32 revision;
-        int retval;
-        retval = u132_read_pcimem(u132, revision, &revision);
-        if (retval) {
-                dev_err(&u132->platform_dev->dev, "error %d accessing device co"
-                        "ntrol\n", retval);
-                return retval;
-        } else if ((revision & 0xFF) == 0x10) {
-        } else if ((revision & 0xFF) == 0x11) {
-        } else {
-                dev_err(&u132->platform_dev->dev, "device revision is not valid"
-                        " %08X\n", revision);
-                return -ENODEV;
-        }
-        retval = u132_read_pcimem(u132, control, &u132->hc_control);
-        if (retval) {
-                dev_err(&u132->platform_dev->dev, "error %d accessing device co"
-                        "ntrol\n", retval);
-                return retval;
-        }
-        retval = u132_read_pcimem(u132, roothub.status,
-                &u132->hc_roothub_status);
-        if (retval) {
-                dev_err(&u132->platform_dev->dev, "error %d accessing device re"
-                        "g roothub.status\n", retval);
-                return retval;
-        }
-        retval = u132_read_pcimem(u132, roothub.a, &u132->hc_roothub_a);
-        if (retval) {
-                dev_err(&u132->platform_dev->dev, "error %d accessing device re"
-                        "g roothub.a\n", retval);
-                return retval;
-        }
-        {
-                int I = u132->num_ports;
-                int i = 0;
-                while (I-- > 0) {
-                        retval = u132_read_pcimem(u132, roothub.portstatus[i],
-                                &u132->hc_roothub_portstatus[i]);
-                        if (retval) {
-                                dev_err(&u132->platform_dev->dev, "error %d acc"
-                                        "essing device roothub.portstatus[%d]\n"
-                                        , retval, i);
-                                return retval;
-                        } else
-                                i += 1;
-                }
-        }
-        return 0;
+       u32 revision;
+       int retval;
+       retval = u132_read_pcimem(u132, revision, &revision);
+       if (retval) {
+               dev_err(&u132->platform_dev->dev, "error %d accessing device co"
+                       "ntrol\n", retval);
+               return retval;
+       } else if ((revision & 0xFF) == 0x10) {
+       } else if ((revision & 0xFF) == 0x11) {
+       } else {
+               dev_err(&u132->platform_dev->dev, "device revision is not valid"
+                       " %08X\n", revision);
+               return -ENODEV;
+       }
+       retval = u132_read_pcimem(u132, control, &u132->hc_control);
+       if (retval) {
+               dev_err(&u132->platform_dev->dev, "error %d accessing device co"
+                       "ntrol\n", retval);
+               return retval;
+       }
+       retval = u132_read_pcimem(u132, roothub.status,
+               &u132->hc_roothub_status);
+       if (retval) {
+               dev_err(&u132->platform_dev->dev, "error %d accessing device re"
+                       "g roothub.status\n", retval);
+               return retval;
+       }
+       retval = u132_read_pcimem(u132, roothub.a, &u132->hc_roothub_a);
+       if (retval) {
+               dev_err(&u132->platform_dev->dev, "error %d accessing device re"
+                       "g roothub.a\n", retval);
+               return retval;
+       }
+       {
+               int I = u132->num_ports;
+               int i = 0;
+               while (I-- > 0) {
+                       retval = u132_read_pcimem(u132, roothub.portstatus[i],
+                               &u132->hc_roothub_portstatus[i]);
+                       if (retval) {
+                               dev_err(&u132->platform_dev->dev, "error %d acc"
+                                       "essing device roothub.portstatus[%d]\n"
+                                       , retval, i);
+                               return retval;
+                       } else
+                               i += 1;
+               }
+       }
+       return 0;
 }
 
 static void u132_hcd_monitor_work(struct work_struct *work)
 {
-        struct u132 *u132 = container_of(work, struct u132, monitor.work);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                u132_monitor_put_kref(u132);
-                return;
-        } else if (u132->going > 0) {
-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
-                u132_monitor_put_kref(u132);
-                return;
-        } else {
-                int retval;
-                mutex_lock(&u132->sw_lock);
-                retval = read_roothub_info(u132);
-                if (retval) {
-                        struct usb_hcd *hcd = u132_to_hcd(u132);
-                        u132_disable(u132);
-                        u132->going = 1;
-                        mutex_unlock(&u132->sw_lock);
-                        usb_hc_died(hcd);
-                        ftdi_elan_gone_away(u132->platform_dev);
-                        u132_monitor_put_kref(u132);
-                        return;
-                } else {
-                        u132_monitor_requeue_work(u132, 500);
-                        mutex_unlock(&u132->sw_lock);
-                        return;
-                }
-        }
+       struct u132 *u132 = container_of(work, struct u132, monitor.work);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               u132_monitor_put_kref(u132);
+               return;
+       } else if (u132->going > 0) {
+               dev_err(&u132->platform_dev->dev, "device is being removed\n");
+               u132_monitor_put_kref(u132);
+               return;
+       } else {
+               int retval;
+               mutex_lock(&u132->sw_lock);
+               retval = read_roothub_info(u132);
+               if (retval) {
+                       struct usb_hcd *hcd = u132_to_hcd(u132);
+                       u132_disable(u132);
+                       u132->going = 1;
+                       mutex_unlock(&u132->sw_lock);
+                       usb_hc_died(hcd);
+                       ftdi_elan_gone_away(u132->platform_dev);
+                       u132_monitor_put_kref(u132);
+                       return;
+               } else {
+                       u132_monitor_requeue_work(u132, 500);
+                       mutex_unlock(&u132->sw_lock);
+                       return;
+               }
+       }
 }
 
 static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp,
-        struct urb *urb, int status)
+       struct urb *urb, int status)
 {
-        struct u132_ring *ring;
-        unsigned long irqs;
-        struct usb_hcd *hcd = u132_to_hcd(u132);
-        urb->error_count = 0;
-        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+       struct u132_ring *ring;
+       unsigned long irqs;
+       struct usb_hcd *hcd = u132_to_hcd(u132);
+       urb->error_count = 0;
+       spin_lock_irqsave(&endp->queue_lock.slock, irqs);
        usb_hcd_unlink_urb_from_ep(hcd, urb);
-        endp->queue_next += 1;
-        if (ENDP_QUEUE_SIZE > --endp->queue_size) {
-                endp->active = 0;
-                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-        } else {
-                struct list_head *next = endp->urb_more.next;
-                struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
-                        urb_more);
-                list_del(next);
-                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
-                        urbq->urb;
-                endp->active = 0;
-                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-                kfree(urbq);
-        } down(&u132->scheduler_lock);
-        ring = endp->ring;
-        ring->in_use = 0;
-        u132_ring_cancel_work(u132, ring);
-        u132_ring_queue_work(u132, ring, 0);
-        up(&u132->scheduler_lock);
-        u132_endp_put_kref(u132, endp);
+       endp->queue_next += 1;
+       if (ENDP_QUEUE_SIZE > --endp->queue_size) {
+               endp->active = 0;
+               spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+       } else {
+               struct list_head *next = endp->urb_more.next;
+               struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
+                       urb_more);
+               list_del(next);
+               endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+                       urbq->urb;
+               endp->active = 0;
+               spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+               kfree(urbq);
+       }
+       mutex_lock(&u132->scheduler_lock);
+       ring = endp->ring;
+       ring->in_use = 0;
+       u132_ring_cancel_work(u132, ring);
+       u132_ring_queue_work(u132, ring, 0);
+       mutex_unlock(&u132->scheduler_lock);
+       u132_endp_put_kref(u132, endp);
        usb_hcd_giveback_urb(hcd, urb, status);
-        return;
+       return;
 }
 
 static void u132_hcd_forget_urb(struct u132 *u132, struct u132_endp *endp,
-        struct urb *urb, int status)
+       struct urb *urb, int status)
 {
-        u132_endp_put_kref(u132, endp);
+       u132_endp_put_kref(u132, endp);
 }
 
 static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp,
-        struct urb *urb, int status)
+       struct urb *urb, int status)
 {
-        unsigned long irqs;
-        struct usb_hcd *hcd = u132_to_hcd(u132);
-        urb->error_count = 0;
-        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+       unsigned long irqs;
+       struct usb_hcd *hcd = u132_to_hcd(u132);
+       urb->error_count = 0;
+       spin_lock_irqsave(&endp->queue_lock.slock, irqs);
        usb_hcd_unlink_urb_from_ep(hcd, urb);
-        endp->queue_next += 1;
-        if (ENDP_QUEUE_SIZE > --endp->queue_size) {
-                endp->active = 0;
-                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-        } else {
-                struct list_head *next = endp->urb_more.next;
-                struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
-                        urb_more);
-                list_del(next);
-                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
-                        urbq->urb;
-                endp->active = 0;
-                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-                kfree(urbq);
+       endp->queue_next += 1;
+       if (ENDP_QUEUE_SIZE > --endp->queue_size) {
+               endp->active = 0;
+               spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+       } else {
+               struct list_head *next = endp->urb_more.next;
+               struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
+                       urb_more);
+               list_del(next);
+               endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+                       urbq->urb;
+               endp->active = 0;
+               spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+               kfree(urbq);
        } usb_hcd_giveback_urb(hcd, urb, status);
-        return;
+       return;
 }
 
 static inline int edset_input(struct u132 *u132, struct u132_ring *ring,
-        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
-        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-        int toggle_bits, int error_count, int condition_code, int repeat_number,
-         int halted, int skipped, int actual, int non_null))
+       struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+       void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+       int toggle_bits, int error_count, int condition_code, int repeat_number,
+        int halted, int skipped, int actual, int non_null))
 {
-        return usb_ftdi_elan_edset_input(u132->platform_dev, ring->number, endp,
-                 urb, address, endp->usb_endp, toggle_bits, callback);
+       return usb_ftdi_elan_edset_input(u132->platform_dev, ring->number, endp,
+                urb, address, endp->usb_endp, toggle_bits, callback);
 }
 
 static inline int edset_setup(struct u132 *u132, struct u132_ring *ring,
-        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
-        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-        int toggle_bits, int error_count, int condition_code, int repeat_number,
-         int halted, int skipped, int actual, int non_null))
+       struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+       void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+       int toggle_bits, int error_count, int condition_code, int repeat_number,
+        int halted, int skipped, int actual, int non_null))
 {
-        return usb_ftdi_elan_edset_setup(u132->platform_dev, ring->number, endp,
-                 urb, address, endp->usb_endp, toggle_bits, callback);
+       return usb_ftdi_elan_edset_setup(u132->platform_dev, ring->number, endp,
+                urb, address, endp->usb_endp, toggle_bits, callback);
 }
 
 static inline int edset_single(struct u132 *u132, struct u132_ring *ring,
-        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
-        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-        int toggle_bits, int error_count, int condition_code, int repeat_number,
-         int halted, int skipped, int actual, int non_null))
+       struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+       void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+       int toggle_bits, int error_count, int condition_code, int repeat_number,
+        int halted, int skipped, int actual, int non_null))
 {
-        return usb_ftdi_elan_edset_single(u132->platform_dev, ring->number,
-                endp, urb, address, endp->usb_endp, toggle_bits, callback);
+       return usb_ftdi_elan_edset_single(u132->platform_dev, ring->number,
+               endp, urb, address, endp->usb_endp, toggle_bits, callback);
 }
 
 static inline int edset_output(struct u132 *u132, struct u132_ring *ring,
-        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
-        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-        int toggle_bits, int error_count, int condition_code, int repeat_number,
-         int halted, int skipped, int actual, int non_null))
+       struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+       void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+       int toggle_bits, int error_count, int condition_code, int repeat_number,
+        int halted, int skipped, int actual, int non_null))
 {
-        return usb_ftdi_elan_edset_output(u132->platform_dev, ring->number,
-                endp, urb, address, endp->usb_endp, toggle_bits, callback);
+       return usb_ftdi_elan_edset_output(u132->platform_dev, ring->number,
+               endp, urb, address, endp->usb_endp, toggle_bits, callback);
 }
 
 
@@ -623,683 +624,678 @@ static inline int edset_output(struct u132 *u132, struct u132_ring *ring,
 *
 */
 static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf,
-        int len, int toggle_bits, int error_count, int condition_code,
-        int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-        struct u132_endp *endp = data;
-        struct u132 *u132 = endp->u132;
-        u8 address = u132->addr[endp->usb_addr].address;
-        struct u132_udev *udev = &u132->udev[address];
-        down(&u132->scheduler_lock);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                up(&u132->scheduler_lock);
-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-                return;
-        } else if (endp->dequeueing) {
-                endp->dequeueing = 0;
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-                return;
-        } else if (u132->going > 0) {
+       int len, int toggle_bits, int error_count, int condition_code,
+       int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+       struct u132_endp *endp = data;
+       struct u132 *u132 = endp->u132;
+       u8 address = u132->addr[endp->usb_addr].address;
+       struct u132_udev *udev = &u132->udev[address];
+       mutex_lock(&u132->scheduler_lock);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+               return;
+       } else if (endp->dequeueing) {
+               endp->dequeueing = 0;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+               return;
+       } else if (u132->going > 0) {
                dev_err(&u132->platform_dev->dev, "device is being removed "
                                "urb=%p\n", urb);
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-                return;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+               return;
        } else if (!urb->unlinked) {
-                struct u132_ring *ring = endp->ring;
-                u8 *u = urb->transfer_buffer + urb->actual_length;
-                u8 *b = buf;
-                int L = len;
-                while (L-- > 0) {
-                        *u++ = *b++;
-                }
-                urb->actual_length += len;
-                if ((condition_code == TD_CC_NOERROR) &&
-                        (urb->transfer_buffer_length > urb->actual_length)) {
-                        endp->toggle_bits = toggle_bits;
-                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
-                                1 & toggle_bits);
-                        if (urb->actual_length > 0) {
-                                int retval;
-                                up(&u132->scheduler_lock);
-                                retval = edset_single(u132, ring, endp, urb,
-                                        address, endp->toggle_bits,
-                                        u132_hcd_interrupt_recv);
-                                if (retval == 0) {
-                                } else
-                                        u132_hcd_giveback_urb(u132, endp, urb,
-                                                retval);
-                        } else {
-                                ring->in_use = 0;
-                                endp->active = 0;
-                                endp->jiffies = jiffies +
-                                        msecs_to_jiffies(urb->interval);
-                                u132_ring_cancel_work(u132, ring);
-                                u132_ring_queue_work(u132, ring, 0);
-                                up(&u132->scheduler_lock);
-                                u132_endp_put_kref(u132, endp);
-                        }
-                        return;
-                } else if ((condition_code == TD_DATAUNDERRUN) &&
-                        ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
-                        endp->toggle_bits = toggle_bits;
-                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
-                                1 & toggle_bits);
-                        up(&u132->scheduler_lock);
-                        u132_hcd_giveback_urb(u132, endp, urb, 0);
-                        return;
-                } else {
-                        if (condition_code == TD_CC_NOERROR) {
-                                endp->toggle_bits = toggle_bits;
-                                usb_settoggle(udev->usb_device, endp->usb_endp,
-                                        0, 1 & toggle_bits);
-                        } else if (condition_code == TD_CC_STALL) {
-                                endp->toggle_bits = 0x2;
-                                usb_settoggle(udev->usb_device, endp->usb_endp,
-                                        0, 0);
-                        } else {
-                                endp->toggle_bits = 0x2;
-                                usb_settoggle(udev->usb_device, endp->usb_endp,
-                                        0, 0);
-                                dev_err(&u132->platform_dev->dev, "urb=%p givin"
-                                        "g back INTERRUPT %s\n", urb,
-                                        cc_to_text[condition_code]);
-                        }
-                        up(&u132->scheduler_lock);
-                        u132_hcd_giveback_urb(u132, endp, urb,
-                                cc_to_error[condition_code]);
-                        return;
-                }
-        } else {
+               struct u132_ring *ring = endp->ring;
+               u8 *u = urb->transfer_buffer + urb->actual_length;
+               u8 *b = buf;
+               int L = len;
+
+               while (L-- > 0)
+                       *u++ = *b++;
+
+               urb->actual_length += len;
+               if ((condition_code == TD_CC_NOERROR) &&
+                       (urb->transfer_buffer_length > urb->actual_length)) {
+                       endp->toggle_bits = toggle_bits;
+                       usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                               1 & toggle_bits);
+                       if (urb->actual_length > 0) {
+                               int retval;
+                               mutex_unlock(&u132->scheduler_lock);
+                               retval = edset_single(u132, ring, endp, urb,
+                                       address, endp->toggle_bits,
+                                       u132_hcd_interrupt_recv);
+                               if (retval != 0)
+                                       u132_hcd_giveback_urb(u132, endp, urb,
+                                               retval);
+                       } else {
+                               ring->in_use = 0;
+                               endp->active = 0;
+                               endp->jiffies = jiffies +
+                                       msecs_to_jiffies(urb->interval);
+                               u132_ring_cancel_work(u132, ring);
+                               u132_ring_queue_work(u132, ring, 0);
+                               mutex_unlock(&u132->scheduler_lock);
+                               u132_endp_put_kref(u132, endp);
+                       }
+                       return;
+               } else if ((condition_code == TD_DATAUNDERRUN) &&
+                       ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
+                       endp->toggle_bits = toggle_bits;
+                       usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                               1 & toggle_bits);
+                       mutex_unlock(&u132->scheduler_lock);
+                       u132_hcd_giveback_urb(u132, endp, urb, 0);
+                       return;
+               } else {
+                       if (condition_code == TD_CC_NOERROR) {
+                               endp->toggle_bits = toggle_bits;
+                               usb_settoggle(udev->usb_device, endp->usb_endp,
+                                       0, 1 & toggle_bits);
+                       } else if (condition_code == TD_CC_STALL) {
+                               endp->toggle_bits = 0x2;
+                               usb_settoggle(udev->usb_device, endp->usb_endp,
+                                       0, 0);
+                       } else {
+                               endp->toggle_bits = 0x2;
+                               usb_settoggle(udev->usb_device, endp->usb_endp,
+                                       0, 0);
+                               dev_err(&u132->platform_dev->dev, "urb=%p givin"
+                                       "g back INTERRUPT %s\n", urb,
+                                       cc_to_text[condition_code]);
+                       }
+                       mutex_unlock(&u132->scheduler_lock);
+                       u132_hcd_giveback_urb(u132, endp, urb,
+                               cc_to_error[condition_code]);
+                       return;
+               }
+       } else {
                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
                                "unlinked=%d\n", urb, urb->unlinked);
-                up(&u132->scheduler_lock);
+               mutex_unlock(&u132->scheduler_lock);
                u132_hcd_giveback_urb(u132, endp, urb, 0);
-                return;
-        }
+               return;
+       }
 }
 
 static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf,
-        int len, int toggle_bits, int error_count, int condition_code,
-        int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-        struct u132_endp *endp = data;
-        struct u132 *u132 = endp->u132;
-        u8 address = u132->addr[endp->usb_addr].address;
-        down(&u132->scheduler_lock);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                up(&u132->scheduler_lock);
-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-                return;
-        } else if (endp->dequeueing) {
-                endp->dequeueing = 0;
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-                return;
-        } else if (u132->going > 0) {
+       int len, int toggle_bits, int error_count, int condition_code,
+       int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+       struct u132_endp *endp = data;
+       struct u132 *u132 = endp->u132;
+       u8 address = u132->addr[endp->usb_addr].address;
+       mutex_lock(&u132->scheduler_lock);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+               return;
+       } else if (endp->dequeueing) {
+               endp->dequeueing = 0;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+               return;
+       } else if (u132->going > 0) {
                dev_err(&u132->platform_dev->dev, "device is being removed "
                                "urb=%p\n", urb);
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-                return;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+               return;
        } else if (!urb->unlinked) {
-                struct u132_ring *ring = endp->ring;
-                urb->actual_length += len;
-                endp->toggle_bits = toggle_bits;
-                if (urb->transfer_buffer_length > urb->actual_length) {
-                        int retval;
-                        up(&u132->scheduler_lock);
-                        retval = edset_output(u132, ring, endp, urb, address,
-                                endp->toggle_bits, u132_hcd_bulk_output_sent);
-                        if (retval == 0) {
-                        } else
-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
-                        return;
-                } else {
-                        up(&u132->scheduler_lock);
-                        u132_hcd_giveback_urb(u132, endp, urb, 0);
-                        return;
-                }
-        } else {
+               struct u132_ring *ring = endp->ring;
+               urb->actual_length += len;
+               endp->toggle_bits = toggle_bits;
+               if (urb->transfer_buffer_length > urb->actual_length) {
+                       int retval;
+                       mutex_unlock(&u132->scheduler_lock);
+                       retval = edset_output(u132, ring, endp, urb, address,
+                               endp->toggle_bits, u132_hcd_bulk_output_sent);
+                       if (retval != 0)
+                               u132_hcd_giveback_urb(u132, endp, urb, retval);
+                       return;
+               } else {
+                       mutex_unlock(&u132->scheduler_lock);
+                       u132_hcd_giveback_urb(u132, endp, urb, 0);
+                       return;
+               }
+       } else {
                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
                                "unlinked=%d\n", urb, urb->unlinked);
-                up(&u132->scheduler_lock);
+               mutex_unlock(&u132->scheduler_lock);
                u132_hcd_giveback_urb(u132, endp, urb, 0);
-                return;
-        }
+               return;
+       }
 }
 
 static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf,
-        int len, int toggle_bits, int error_count, int condition_code,
-        int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-        struct u132_endp *endp = data;
-        struct u132 *u132 = endp->u132;
-        u8 address = u132->addr[endp->usb_addr].address;
-        struct u132_udev *udev = &u132->udev[address];
-        down(&u132->scheduler_lock);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                up(&u132->scheduler_lock);
-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-                return;
-        } else if (endp->dequeueing) {
-                endp->dequeueing = 0;
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-                return;
-        } else if (u132->going > 0) {
+       int len, int toggle_bits, int error_count, int condition_code,
+       int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+       struct u132_endp *endp = data;
+       struct u132 *u132 = endp->u132;
+       u8 address = u132->addr[endp->usb_addr].address;
+       struct u132_udev *udev = &u132->udev[address];
+       mutex_lock(&u132->scheduler_lock);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+               return;
+       } else if (endp->dequeueing) {
+               endp->dequeueing = 0;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+               return;
+       } else if (u132->going > 0) {
                dev_err(&u132->platform_dev->dev, "device is being removed "
                                "urb=%p\n", urb);
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-                return;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+               return;
        } else if (!urb->unlinked) {
-                struct u132_ring *ring = endp->ring;
-                u8 *u = urb->transfer_buffer + urb->actual_length;
-                u8 *b = buf;
-                int L = len;
-                while (L-- > 0) {
-                        *u++ = *b++;
-                }
-                urb->actual_length += len;
-                if ((condition_code == TD_CC_NOERROR) &&
-                        (urb->transfer_buffer_length > urb->actual_length)) {
-                        int retval;
-                        endp->toggle_bits = toggle_bits;
-                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
-                                1 & toggle_bits);
-                        up(&u132->scheduler_lock);
-                        retval = usb_ftdi_elan_edset_input(u132->platform_dev,
-                                ring->number, endp, urb, address,
-                                endp->usb_endp, endp->toggle_bits,
-                                u132_hcd_bulk_input_recv);
-                        if (retval == 0) {
-                        } else
-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
-                        return;
-                } else if (condition_code == TD_CC_NOERROR) {
-                        endp->toggle_bits = toggle_bits;
-                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
-                                1 & toggle_bits);
-                        up(&u132->scheduler_lock);
-                        u132_hcd_giveback_urb(u132, endp, urb,
-                                cc_to_error[condition_code]);
-                        return;
-                } else if ((condition_code == TD_DATAUNDERRUN) &&
-                        ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
-                        endp->toggle_bits = toggle_bits;
-                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
-                                1 & toggle_bits);
-                        up(&u132->scheduler_lock);
-                        u132_hcd_giveback_urb(u132, endp, urb, 0);
-                        return;
-                } else if (condition_code == TD_DATAUNDERRUN) {
-                        endp->toggle_bits = toggle_bits;
-                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
-                                1 & toggle_bits);
-                        dev_warn(&u132->platform_dev->dev, "urb=%p(SHORT NOT OK"
-                                ") giving back BULK IN %s\n", urb,
-                                cc_to_text[condition_code]);
-                        up(&u132->scheduler_lock);
-                        u132_hcd_giveback_urb(u132, endp, urb, 0);
-                        return;
-                } else if (condition_code == TD_CC_STALL) {
-                        endp->toggle_bits = 0x2;
-                        usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
-                        up(&u132->scheduler_lock);
-                        u132_hcd_giveback_urb(u132, endp, urb,
-                                cc_to_error[condition_code]);
-                        return;
-                } else {
-                        endp->toggle_bits = 0x2;
-                        usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
-                        dev_err(&u132->platform_dev->dev, "urb=%p giving back B"
-                                "ULK IN code=%d %s\n", urb, condition_code,
-                                cc_to_text[condition_code]);
-                        up(&u132->scheduler_lock);
-                        u132_hcd_giveback_urb(u132, endp, urb,
-                                cc_to_error[condition_code]);
-                        return;
-                }
-        } else {
+               struct u132_ring *ring = endp->ring;
+               u8 *u = urb->transfer_buffer + urb->actual_length;
+               u8 *b = buf;
+               int L = len;
+
+               while (L-- > 0)
+                       *u++ = *b++;
+
+               urb->actual_length += len;
+               if ((condition_code == TD_CC_NOERROR) &&
+                       (urb->transfer_buffer_length > urb->actual_length)) {
+                       int retval;
+                       endp->toggle_bits = toggle_bits;
+                       usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                               1 & toggle_bits);
+                       mutex_unlock(&u132->scheduler_lock);
+                       retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                               ring->number, endp, urb, address,
+                               endp->usb_endp, endp->toggle_bits,
+                               u132_hcd_bulk_input_recv);
+                       if (retval != 0)
+                               u132_hcd_giveback_urb(u132, endp, urb, retval);
+                       return;
+               } else if (condition_code == TD_CC_NOERROR) {
+                       endp->toggle_bits = toggle_bits;
+                       usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                               1 & toggle_bits);
+                       mutex_unlock(&u132->scheduler_lock);
+                       u132_hcd_giveback_urb(u132, endp, urb,
+                               cc_to_error[condition_code]);
+                       return;
+               } else if ((condition_code == TD_DATAUNDERRUN) &&
+                       ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
+                       endp->toggle_bits = toggle_bits;
+                       usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                               1 & toggle_bits);
+                       mutex_unlock(&u132->scheduler_lock);
+                       u132_hcd_giveback_urb(u132, endp, urb, 0);
+                       return;
+               } else if (condition_code == TD_DATAUNDERRUN) {
+                       endp->toggle_bits = toggle_bits;
+                       usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                               1 & toggle_bits);
+                       dev_warn(&u132->platform_dev->dev, "urb=%p(SHORT NOT OK"
+                               ") giving back BULK IN %s\n", urb,
+                               cc_to_text[condition_code]);
+                       mutex_unlock(&u132->scheduler_lock);
+                       u132_hcd_giveback_urb(u132, endp, urb, 0);
+                       return;
+               } else if (condition_code == TD_CC_STALL) {
+                       endp->toggle_bits = 0x2;
+                       usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
+                       mutex_unlock(&u132->scheduler_lock);
+                       u132_hcd_giveback_urb(u132, endp, urb,
+                               cc_to_error[condition_code]);
+                       return;
+               } else {
+                       endp->toggle_bits = 0x2;
+                       usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
+                       dev_err(&u132->platform_dev->dev, "urb=%p giving back B"
+                               "ULK IN code=%d %s\n", urb, condition_code,
+                               cc_to_text[condition_code]);
+                       mutex_unlock(&u132->scheduler_lock);
+                       u132_hcd_giveback_urb(u132, endp, urb,
+                               cc_to_error[condition_code]);
+                       return;
+               }
+       } else {
                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
                                "unlinked=%d\n", urb, urb->unlinked);
-                up(&u132->scheduler_lock);
+               mutex_unlock(&u132->scheduler_lock);
                u132_hcd_giveback_urb(u132, endp, urb, 0);
-                return;
-        }
+               return;
+       }
 }
 
 static void u132_hcd_configure_empty_sent(void *data, struct urb *urb, u8 *buf,
-        int len, int toggle_bits, int error_count, int condition_code,
-        int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-        struct u132_endp *endp = data;
-        struct u132 *u132 = endp->u132;
-        down(&u132->scheduler_lock);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                up(&u132->scheduler_lock);
-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-                return;
-        } else if (endp->dequeueing) {
-                endp->dequeueing = 0;
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-                return;
-        } else if (u132->going > 0) {
+       int len, int toggle_bits, int error_count, int condition_code,
+       int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+       struct u132_endp *endp = data;
+       struct u132 *u132 = endp->u132;
+       mutex_lock(&u132->scheduler_lock);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+               return;
+       } else if (endp->dequeueing) {
+               endp->dequeueing = 0;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+               return;
+       } else if (u132->going > 0) {
                dev_err(&u132->platform_dev->dev, "device is being removed "
                                "urb=%p\n", urb);
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-                return;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+               return;
        } else if (!urb->unlinked) {
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, 0);
-                return;
-        } else {
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, 0);
+               return;
+       } else {
                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
                                "unlinked=%d\n", urb, urb->unlinked);
-                up(&u132->scheduler_lock);
+               mutex_unlock(&u132->scheduler_lock);
                u132_hcd_giveback_urb(u132, endp, urb, 0);
-                return;
-        }
+               return;
+       }
 }
 
 static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf,
-        int len, int toggle_bits, int error_count, int condition_code,
-        int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-        struct u132_endp *endp = data;
-        struct u132 *u132 = endp->u132;
-        u8 address = u132->addr[endp->usb_addr].address;
-        down(&u132->scheduler_lock);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                up(&u132->scheduler_lock);
-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-                return;
-        } else if (endp->dequeueing) {
-                endp->dequeueing = 0;
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-                return;
-        } else if (u132->going > 0) {
+       int len, int toggle_bits, int error_count, int condition_code,
+       int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+       struct u132_endp *endp = data;
+       struct u132 *u132 = endp->u132;
+       u8 address = u132->addr[endp->usb_addr].address;
+       mutex_lock(&u132->scheduler_lock);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+               return;
+       } else if (endp->dequeueing) {
+               endp->dequeueing = 0;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+               return;
+       } else if (u132->going > 0) {
                dev_err(&u132->platform_dev->dev, "device is being removed "
                                "urb=%p\n", urb);
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-                return;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+               return;
        } else if (!urb->unlinked) {
-                struct u132_ring *ring = endp->ring;
-                u8 *u = urb->transfer_buffer;
-                u8 *b = buf;
-                int L = len;
-                while (L-- > 0) {
-                        *u++ = *b++;
-                }
-                urb->actual_length = len;
-                if ((condition_code == TD_CC_NOERROR) || ((condition_code ==
-                        TD_DATAUNDERRUN) && ((urb->transfer_flags &
-                        URB_SHORT_NOT_OK) == 0))) {
-                        int retval;
-                        up(&u132->scheduler_lock);
-                        retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
-                                ring->number, endp, urb, address,
-                                endp->usb_endp, 0x3,
-                                u132_hcd_configure_empty_sent);
-                        if (retval == 0) {
-                        } else
-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
-                        return;
-                } else if (condition_code == TD_CC_STALL) {
-                        up(&u132->scheduler_lock);
-                        dev_warn(&u132->platform_dev->dev, "giving back SETUP I"
-                                "NPUT STALL urb %p\n", urb);
-                        u132_hcd_giveback_urb(u132, endp, urb,
-                                cc_to_error[condition_code]);
-                        return;
-                } else {
-                        up(&u132->scheduler_lock);
-                        dev_err(&u132->platform_dev->dev, "giving back SETUP IN"
-                                "PUT %s urb %p\n", cc_to_text[condition_code],
-                                urb);
-                        u132_hcd_giveback_urb(u132, endp, urb,
-                                cc_to_error[condition_code]);
-                        return;
-                }
-        } else {
+               struct u132_ring *ring = endp->ring;
+               u8 *u = urb->transfer_buffer;
+               u8 *b = buf;
+               int L = len;
+
+               while (L-- > 0)
+                       *u++ = *b++;
+
+               urb->actual_length = len;
+               if ((condition_code == TD_CC_NOERROR) || ((condition_code ==
+                       TD_DATAUNDERRUN) && ((urb->transfer_flags &
+                       URB_SHORT_NOT_OK) == 0))) {
+                       int retval;
+                       mutex_unlock(&u132->scheduler_lock);
+                       retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
+                               ring->number, endp, urb, address,
+                               endp->usb_endp, 0x3,
+                               u132_hcd_configure_empty_sent);
+                       if (retval != 0)
+                               u132_hcd_giveback_urb(u132, endp, urb, retval);
+                       return;
+               } else if (condition_code == TD_CC_STALL) {
+                       mutex_unlock(&u132->scheduler_lock);
+                       dev_warn(&u132->platform_dev->dev, "giving back SETUP I"
+                               "NPUT STALL urb %p\n", urb);
+                       u132_hcd_giveback_urb(u132, endp, urb,
+                               cc_to_error[condition_code]);
+                       return;
+               } else {
+                       mutex_unlock(&u132->scheduler_lock);
+                       dev_err(&u132->platform_dev->dev, "giving back SETUP IN"
+                               "PUT %s urb %p\n", cc_to_text[condition_code],
+                               urb);
+                       u132_hcd_giveback_urb(u132, endp, urb,
+                               cc_to_error[condition_code]);
+                       return;
+               }
+       } else {
                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
                                "unlinked=%d\n", urb, urb->unlinked);
-                up(&u132->scheduler_lock);
+               mutex_unlock(&u132->scheduler_lock);
                u132_hcd_giveback_urb(u132, endp, urb, 0);
-                return;
-        }
+               return;
+       }
 }
 
 static void u132_hcd_configure_empty_recv(void *data, struct urb *urb, u8 *buf,
-        int len, int toggle_bits, int error_count, int condition_code,
-        int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-        struct u132_endp *endp = data;
-        struct u132 *u132 = endp->u132;
-        down(&u132->scheduler_lock);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                up(&u132->scheduler_lock);
-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-                return;
-        } else if (endp->dequeueing) {
-                endp->dequeueing = 0;
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-                return;
-        } else if (u132->going > 0) {
+       int len, int toggle_bits, int error_count, int condition_code,
+       int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+       struct u132_endp *endp = data;
+       struct u132 *u132 = endp->u132;
+       mutex_lock(&u132->scheduler_lock);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+               return;
+       } else if (endp->dequeueing) {
+               endp->dequeueing = 0;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+               return;
+       } else if (u132->going > 0) {
                dev_err(&u132->platform_dev->dev, "device is being removed "
                                "urb=%p\n", urb);
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-                return;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+               return;
        } else if (!urb->unlinked) {
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, 0);
-                return;
-        } else {
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, 0);
+               return;
+       } else {
                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
                                "unlinked=%d\n", urb, urb->unlinked);
-                up(&u132->scheduler_lock);
+               mutex_unlock(&u132->scheduler_lock);
                u132_hcd_giveback_urb(u132, endp, urb, 0);
-                return;
-        }
+               return;
+       }
 }
 
 static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf,
-        int len, int toggle_bits, int error_count, int condition_code,
-        int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-        struct u132_endp *endp = data;
-        struct u132 *u132 = endp->u132;
-        u8 address = u132->addr[endp->usb_addr].address;
-        down(&u132->scheduler_lock);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                up(&u132->scheduler_lock);
-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-                return;
-        } else if (endp->dequeueing) {
-                endp->dequeueing = 0;
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-                return;
-        } else if (u132->going > 0) {
+       int len, int toggle_bits, int error_count, int condition_code,
+       int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+       struct u132_endp *endp = data;
+       struct u132 *u132 = endp->u132;
+       u8 address = u132->addr[endp->usb_addr].address;
+       mutex_lock(&u132->scheduler_lock);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+               return;
+       } else if (endp->dequeueing) {
+               endp->dequeueing = 0;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+               return;
+       } else if (u132->going > 0) {
                dev_err(&u132->platform_dev->dev, "device is being removed "
                                "urb=%p\n", urb);
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-                return;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+               return;
        } else if (!urb->unlinked) {
-                if (usb_pipein(urb->pipe)) {
-                        int retval;
-                        struct u132_ring *ring = endp->ring;
-                        up(&u132->scheduler_lock);
-                        retval = usb_ftdi_elan_edset_input(u132->platform_dev,
-                                ring->number, endp, urb, address,
-                                endp->usb_endp, 0,
-                                u132_hcd_configure_input_recv);
-                        if (retval == 0) {
-                        } else
-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
-                        return;
-                } else {
-                        int retval;
-                        struct u132_ring *ring = endp->ring;
-                        up(&u132->scheduler_lock);
-                        retval = usb_ftdi_elan_edset_input(u132->platform_dev,
-                                ring->number, endp, urb, address,
-                                endp->usb_endp, 0,
-                                u132_hcd_configure_empty_recv);
-                        if (retval == 0) {
-                        } else
-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
-                        return;
-                }
-        } else {
+               if (usb_pipein(urb->pipe)) {
+                       int retval;
+                       struct u132_ring *ring = endp->ring;
+                       mutex_unlock(&u132->scheduler_lock);
+                       retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                               ring->number, endp, urb, address,
+                               endp->usb_endp, 0,
+                               u132_hcd_configure_input_recv);
+                       if (retval != 0)
+                               u132_hcd_giveback_urb(u132, endp, urb, retval);
+                       return;
+               } else {
+                       int retval;
+                       struct u132_ring *ring = endp->ring;
+                       mutex_unlock(&u132->scheduler_lock);
+                       retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                               ring->number, endp, urb, address,
+                               endp->usb_endp, 0,
+                               u132_hcd_configure_empty_recv);
+                       if (retval != 0)
+                               u132_hcd_giveback_urb(u132, endp, urb, retval);
+                       return;
+               }
+       } else {
                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
                                "unlinked=%d\n", urb, urb->unlinked);
-                up(&u132->scheduler_lock);
+               mutex_unlock(&u132->scheduler_lock);
                u132_hcd_giveback_urb(u132, endp, urb, 0);
-                return;
-        }
+               return;
+       }
 }
 
 static void u132_hcd_enumeration_empty_recv(void *data, struct urb *urb,
-        u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
-        int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-        struct u132_endp *endp = data;
-        struct u132 *u132 = endp->u132;
-        u8 address = u132->addr[endp->usb_addr].address;
-        struct u132_udev *udev = &u132->udev[address];
-        down(&u132->scheduler_lock);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                up(&u132->scheduler_lock);
-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-                return;
-        } else if (endp->dequeueing) {
-                endp->dequeueing = 0;
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-                return;
-        } else if (u132->going > 0) {
+       u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
+       int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+       struct u132_endp *endp = data;
+       struct u132 *u132 = endp->u132;
+       u8 address = u132->addr[endp->usb_addr].address;
+       struct u132_udev *udev = &u132->udev[address];
+       mutex_lock(&u132->scheduler_lock);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+               return;
+       } else if (endp->dequeueing) {
+               endp->dequeueing = 0;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+               return;
+       } else if (u132->going > 0) {
                dev_err(&u132->platform_dev->dev, "device is being removed "
                                "urb=%p\n", urb);
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-                return;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+               return;
        } else if (!urb->unlinked) {
-                u132->addr[0].address = 0;
-                endp->usb_addr = udev->usb_addr;
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, 0);
-                return;
-        } else {
+               u132->addr[0].address = 0;
+               endp->usb_addr = udev->usb_addr;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, 0);
+               return;
+       } else {
                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
                                "unlinked=%d\n", urb, urb->unlinked);
-                up(&u132->scheduler_lock);
+               mutex_unlock(&u132->scheduler_lock);
                u132_hcd_giveback_urb(u132, endp, urb, 0);
-                return;
-        }
+               return;
+       }
 }
 
 static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb,
-        u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
-        int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-        struct u132_endp *endp = data;
-        struct u132 *u132 = endp->u132;
-        down(&u132->scheduler_lock);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                up(&u132->scheduler_lock);
-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-                return;
-        } else if (endp->dequeueing) {
-                endp->dequeueing = 0;
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-                return;
-        } else if (u132->going > 0) {
+       u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
+       int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+       struct u132_endp *endp = data;
+       struct u132 *u132 = endp->u132;
+       mutex_lock(&u132->scheduler_lock);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+               return;
+       } else if (endp->dequeueing) {
+               endp->dequeueing = 0;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+               return;
+       } else if (u132->going > 0) {
                dev_err(&u132->platform_dev->dev, "device is being removed "
                                "urb=%p\n", urb);
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-                return;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+               return;
        } else if (!urb->unlinked) {
-                int retval;
-                struct u132_ring *ring = endp->ring;
-                up(&u132->scheduler_lock);
-                retval = usb_ftdi_elan_edset_input(u132->platform_dev,
-                        ring->number, endp, urb, 0, endp->usb_endp, 0,
-                        u132_hcd_enumeration_empty_recv);
-                if (retval == 0) {
-                } else
-                        u132_hcd_giveback_urb(u132, endp, urb, retval);
-                return;
-        } else {
+               int retval;
+               struct u132_ring *ring = endp->ring;
+               mutex_unlock(&u132->scheduler_lock);
+               retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                       ring->number, endp, urb, 0, endp->usb_endp, 0,
+                       u132_hcd_enumeration_empty_recv);
+               if (retval != 0)
+                       u132_hcd_giveback_urb(u132, endp, urb, retval);
+               return;
+       } else {
                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
                                "unlinked=%d\n", urb, urb->unlinked);
-                up(&u132->scheduler_lock);
+               mutex_unlock(&u132->scheduler_lock);
                u132_hcd_giveback_urb(u132, endp, urb, 0);
-                return;
-        }
+               return;
+       }
 }
 
 static void u132_hcd_initial_empty_sent(void *data, struct urb *urb, u8 *buf,
-        int len, int toggle_bits, int error_count, int condition_code,
-        int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-        struct u132_endp *endp = data;
-        struct u132 *u132 = endp->u132;
-        down(&u132->scheduler_lock);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                up(&u132->scheduler_lock);
-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-                return;
-        } else if (endp->dequeueing) {
-                endp->dequeueing = 0;
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-                return;
-        } else if (u132->going > 0) {
+       int len, int toggle_bits, int error_count, int condition_code,
+       int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+       struct u132_endp *endp = data;
+       struct u132 *u132 = endp->u132;
+       mutex_lock(&u132->scheduler_lock);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+               return;
+       } else if (endp->dequeueing) {
+               endp->dequeueing = 0;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+               return;
+       } else if (u132->going > 0) {
                dev_err(&u132->platform_dev->dev, "device is being removed "
                                "urb=%p\n", urb);
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-                return;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+               return;
        } else if (!urb->unlinked) {
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, 0);
-                return;
-        } else {
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, 0);
+               return;
+       } else {
                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
                                "unlinked=%d\n", urb, urb->unlinked);
-                up(&u132->scheduler_lock);
+               mutex_unlock(&u132->scheduler_lock);
                u132_hcd_giveback_urb(u132, endp, urb, 0);
-                return;
-        }
+               return;
+       }
 }
 
 static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf,
-        int len, int toggle_bits, int error_count, int condition_code,
-        int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-        struct u132_endp *endp = data;
-        struct u132 *u132 = endp->u132;
-        u8 address = u132->addr[endp->usb_addr].address;
-        down(&u132->scheduler_lock);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                up(&u132->scheduler_lock);
-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-                return;
-        } else if (endp->dequeueing) {
-                endp->dequeueing = 0;
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-                return;
-        } else if (u132->going > 0) {
+       int len, int toggle_bits, int error_count, int condition_code,
+       int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+       struct u132_endp *endp = data;
+       struct u132 *u132 = endp->u132;
+       u8 address = u132->addr[endp->usb_addr].address;
+       mutex_lock(&u132->scheduler_lock);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+               return;
+       } else if (endp->dequeueing) {
+               endp->dequeueing = 0;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+               return;
+       } else if (u132->going > 0) {
                dev_err(&u132->platform_dev->dev, "device is being removed "
                                "urb=%p\n", urb);
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-                return;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+               return;
        } else if (!urb->unlinked) {
-                int retval;
-                struct u132_ring *ring = endp->ring;
-                u8 *u = urb->transfer_buffer;
-                u8 *b = buf;
-                int L = len;
-                while (L-- > 0) {
-                        *u++ = *b++;
-                }
-                urb->actual_length = len;
-                up(&u132->scheduler_lock);
-                retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
-                        ring->number, endp, urb, address, endp->usb_endp, 0x3,
-                        u132_hcd_initial_empty_sent);
-                if (retval == 0) {
-                } else
-                        u132_hcd_giveback_urb(u132, endp, urb, retval);
-                return;
-        } else {
+               int retval;
+               struct u132_ring *ring = endp->ring;
+               u8 *u = urb->transfer_buffer;
+               u8 *b = buf;
+               int L = len;
+
+               while (L-- > 0)
+                       *u++ = *b++;
+
+               urb->actual_length = len;
+               mutex_unlock(&u132->scheduler_lock);
+               retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
+                       ring->number, endp, urb, address, endp->usb_endp, 0x3,
+                       u132_hcd_initial_empty_sent);
+               if (retval != 0)
+                       u132_hcd_giveback_urb(u132, endp, urb, retval);
+               return;
+       } else {
                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
                                "unlinked=%d\n", urb, urb->unlinked);
-                up(&u132->scheduler_lock);
+               mutex_unlock(&u132->scheduler_lock);
                u132_hcd_giveback_urb(u132, endp, urb, 0);
-                return;
-        }
+               return;
+       }
 }
 
 static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
-        int len, int toggle_bits, int error_count, int condition_code,
-        int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-        struct u132_endp *endp = data;
-        struct u132 *u132 = endp->u132;
-        u8 address = u132->addr[endp->usb_addr].address;
-        down(&u132->scheduler_lock);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                up(&u132->scheduler_lock);
-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-                return;
-        } else if (endp->dequeueing) {
-                endp->dequeueing = 0;
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-                return;
-        } else if (u132->going > 0) {
+       int len, int toggle_bits, int error_count, int condition_code,
+       int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+       struct u132_endp *endp = data;
+       struct u132 *u132 = endp->u132;
+       u8 address = u132->addr[endp->usb_addr].address;
+       mutex_lock(&u132->scheduler_lock);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+               return;
+       } else if (endp->dequeueing) {
+               endp->dequeueing = 0;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+               return;
+       } else if (u132->going > 0) {
                dev_err(&u132->platform_dev->dev, "device is being removed "
                                "urb=%p\n", urb);
-                up(&u132->scheduler_lock);
-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-                return;
+               mutex_unlock(&u132->scheduler_lock);
+               u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+               return;
        } else if (!urb->unlinked) {
-                int retval;
-                struct u132_ring *ring = endp->ring;
-                up(&u132->scheduler_lock);
-                retval = usb_ftdi_elan_edset_input(u132->platform_dev,
-                        ring->number, endp, urb, address, endp->usb_endp, 0,
-                        u132_hcd_initial_input_recv);
-                if (retval == 0) {
-                } else
-                        u132_hcd_giveback_urb(u132, endp, urb, retval);
-                return;
-        } else {
+               int retval;
+               struct u132_ring *ring = endp->ring;
+               mutex_unlock(&u132->scheduler_lock);
+               retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                       ring->number, endp, urb, address, endp->usb_endp, 0,
+                       u132_hcd_initial_input_recv);
+               if (retval != 0)
+                       u132_hcd_giveback_urb(u132, endp, urb, retval);
+               return;
+       } else {
                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
                                "unlinked=%d\n", urb, urb->unlinked);
-                up(&u132->scheduler_lock);
+               mutex_unlock(&u132->scheduler_lock);
                u132_hcd_giveback_urb(u132, endp, urb, 0);
-                return;
-        }
+               return;
+       }
 }
 
 /*
@@ -1308,302 +1304,296 @@ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
 */
 static void u132_hcd_ring_work_scheduler(struct work_struct *work)
 {
-        struct u132_ring *ring =
+       struct u132_ring *ring =
                container_of(work, struct u132_ring, scheduler.work);
-        struct u132 *u132 = ring->u132;
-        down(&u132->scheduler_lock);
-        if (ring->in_use) {
-                up(&u132->scheduler_lock);
-                u132_ring_put_kref(u132, ring);
-                return;
-        } else if (ring->curr_endp) {
-                struct u132_endp *last_endp = ring->curr_endp;
-                struct list_head *scan;
-                struct list_head *head = &last_endp->endp_ring;
-                unsigned long wakeup = 0;
-                list_for_each(scan, head) {
-                        struct u132_endp *endp = list_entry(scan,
-                                struct u132_endp, endp_ring);
-                        if (endp->queue_next == endp->queue_last) {
-                        } else if ((endp->delayed == 0)
-                                || time_after_eq(jiffies, endp->jiffies)) {
-                                ring->curr_endp = endp;
-                                u132_endp_cancel_work(u132, last_endp);
-                                u132_endp_queue_work(u132, last_endp, 0);
-                                up(&u132->scheduler_lock);
-                                u132_ring_put_kref(u132, ring);
-                                return;
-                        } else {
-                                unsigned long delta = endp->jiffies - jiffies;
-                                if (delta > wakeup)
-                                        wakeup = delta;
-                        }
-                }
-                if (last_endp->queue_next == last_endp->queue_last) {
-                } else if ((last_endp->delayed == 0) || time_after_eq(jiffies,
-                        last_endp->jiffies)) {
-                        u132_endp_cancel_work(u132, last_endp);
-                        u132_endp_queue_work(u132, last_endp, 0);
-                        up(&u132->scheduler_lock);
-                        u132_ring_put_kref(u132, ring);
-                        return;
-                } else {
-                        unsigned long delta = last_endp->jiffies - jiffies;
-                        if (delta > wakeup)
-                                wakeup = delta;
-                }
-                if (wakeup > 0) {
-                        u132_ring_requeue_work(u132, ring, wakeup);
-                        up(&u132->scheduler_lock);
-                        return;
-                } else {
-                        up(&u132->scheduler_lock);
-                        u132_ring_put_kref(u132, ring);
-                        return;
-                }
-        } else {
-                up(&u132->scheduler_lock);
-                u132_ring_put_kref(u132, ring);
-                return;
-        }
+       struct u132 *u132 = ring->u132;
+       mutex_lock(&u132->scheduler_lock);
+       if (ring->in_use) {
+               mutex_unlock(&u132->scheduler_lock);
+               u132_ring_put_kref(u132, ring);
+               return;
+       } else if (ring->curr_endp) {
+               struct u132_endp *last_endp = ring->curr_endp;
+               struct list_head *scan;
+               struct list_head *head = &last_endp->endp_ring;
+               unsigned long wakeup = 0;
+               list_for_each(scan, head) {
+                       struct u132_endp *endp = list_entry(scan,
+                               struct u132_endp, endp_ring);
+                       if (endp->queue_next == endp->queue_last) {
+                       } else if ((endp->delayed == 0)
+                               || time_after_eq(jiffies, endp->jiffies)) {
+                               ring->curr_endp = endp;
+                               u132_endp_cancel_work(u132, last_endp);
+                               u132_endp_queue_work(u132, last_endp, 0);
+                               mutex_unlock(&u132->scheduler_lock);
+                               u132_ring_put_kref(u132, ring);
+                               return;
+                       } else {
+                               unsigned long delta = endp->jiffies - jiffies;
+                               if (delta > wakeup)
+                                       wakeup = delta;
+                       }
+               }
+               if (last_endp->queue_next == last_endp->queue_last) {
+               } else if ((last_endp->delayed == 0) || time_after_eq(jiffies,
+                       last_endp->jiffies)) {
+                       u132_endp_cancel_work(u132, last_endp);
+                       u132_endp_queue_work(u132, last_endp, 0);
+                       mutex_unlock(&u132->scheduler_lock);
+                       u132_ring_put_kref(u132, ring);
+                       return;
+               } else {
+                       unsigned long delta = last_endp->jiffies - jiffies;
+                       if (delta > wakeup)
+                               wakeup = delta;
+               }
+               if (wakeup > 0) {
+                       u132_ring_requeue_work(u132, ring, wakeup);
+                       mutex_unlock(&u132->scheduler_lock);
+                       return;
+               } else {
+                       mutex_unlock(&u132->scheduler_lock);
+                       u132_ring_put_kref(u132, ring);
+                       return;
+               }
+       } else {
+               mutex_unlock(&u132->scheduler_lock);
+               u132_ring_put_kref(u132, ring);
+               return;
+       }
 }
 
 static void u132_hcd_endp_work_scheduler(struct work_struct *work)
 {
-        struct u132_ring *ring;
-        struct u132_endp *endp =
+       struct u132_ring *ring;
+       struct u132_endp *endp =
                container_of(work, struct u132_endp, scheduler.work);
-        struct u132 *u132 = endp->u132;
-        down(&u132->scheduler_lock);
-        ring = endp->ring;
-        if (endp->edset_flush) {
-                endp->edset_flush = 0;
-                if (endp->dequeueing)
-                        usb_ftdi_elan_edset_flush(u132->platform_dev,
-                                ring->number, endp);
-                up(&u132->scheduler_lock);
-                u132_endp_put_kref(u132, endp);
-                return;
-        } else if (endp->active) {
-                up(&u132->scheduler_lock);
-                u132_endp_put_kref(u132, endp);
-                return;
-        } else if (ring->in_use) {
-                up(&u132->scheduler_lock);
-                u132_endp_put_kref(u132, endp);
-                return;
-        } else if (endp->queue_next == endp->queue_last) {
-                up(&u132->scheduler_lock);
-                u132_endp_put_kref(u132, endp);
-                return;
-        } else if (endp->pipetype == PIPE_INTERRUPT) {
-                u8 address = u132->addr[endp->usb_addr].address;
-                if (ring->in_use) {
-                        up(&u132->scheduler_lock);
-                        u132_endp_put_kref(u132, endp);
-                        return;
-                } else {
-                        int retval;
-                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
-                                endp->queue_next];
-                        endp->active = 1;
-                        ring->curr_endp = endp;
-                        ring->in_use = 1;
-                        up(&u132->scheduler_lock);
-                        retval = edset_single(u132, ring, endp, urb, address,
-                                endp->toggle_bits, u132_hcd_interrupt_recv);
-                        if (retval == 0) {
-                        } else
-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
-                        return;
-                }
-        } else if (endp->pipetype == PIPE_CONTROL) {
-                u8 address = u132->addr[endp->usb_addr].address;
-                if (ring->in_use) {
-                        up(&u132->scheduler_lock);
-                        u132_endp_put_kref(u132, endp);
-                        return;
-                } else if (address == 0) {
-                        int retval;
-                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
-                                endp->queue_next];
-                        endp->active = 1;
-                        ring->curr_endp = endp;
-                        ring->in_use = 1;
-                        up(&u132->scheduler_lock);
-                        retval = edset_setup(u132, ring, endp, urb, address,
-                                0x2, u132_hcd_initial_setup_sent);
-                        if (retval == 0) {
-                        } else
-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
-                        return;
-                } else if (endp->usb_addr == 0) {
-                        int retval;
-                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
-                                endp->queue_next];
-                        endp->active = 1;
-                        ring->curr_endp = endp;
-                        ring->in_use = 1;
-                        up(&u132->scheduler_lock);
-                        retval = edset_setup(u132, ring, endp, urb, 0, 0x2,
-                                u132_hcd_enumeration_address_sent);
-                        if (retval == 0) {
-                        } else
-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
-                        return;
-                } else {
-                        int retval;
-                        u8 address = u132->addr[endp->usb_addr].address;
-                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
-                                endp->queue_next];
-                        endp->active = 1;
-                        ring->curr_endp = endp;
-                        ring->in_use = 1;
-                        up(&u132->scheduler_lock);
-                        retval = edset_setup(u132, ring, endp, urb, address,
-                                0x2, u132_hcd_configure_setup_sent);
-                        if (retval == 0) {
-                        } else
-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
-                        return;
-                }
-        } else {
-                if (endp->input) {
-                        u8 address = u132->addr[endp->usb_addr].address;
-                        if (ring->in_use) {
-                                up(&u132->scheduler_lock);
-                                u132_endp_put_kref(u132, endp);
-                                return;
-                        } else {
-                                int retval;
-                                struct urb *urb = endp->urb_list[
-                                        ENDP_QUEUE_MASK & endp->queue_next];
-                                endp->active = 1;
-                                ring->curr_endp = endp;
-                                ring->in_use = 1;
-                                up(&u132->scheduler_lock);
-                                retval = edset_input(u132, ring, endp, urb,
-                                        address, endp->toggle_bits,
-                                        u132_hcd_bulk_input_recv);
-                                if (retval == 0) {
-                                } else
-                                        u132_hcd_giveback_urb(u132, endp, urb,
-                                                retval);
-                                return;
-                        }
-                } else {        /* output pipe */
-                        u8 address = u132->addr[endp->usb_addr].address;
-                        if (ring->in_use) {
-                                up(&u132->scheduler_lock);
-                                u132_endp_put_kref(u132, endp);
-                                return;
-                        } else {
-                                int retval;
-                                struct urb *urb = endp->urb_list[
-                                        ENDP_QUEUE_MASK & endp->queue_next];
-                                endp->active = 1;
-                                ring->curr_endp = endp;
-                                ring->in_use = 1;
-                                up(&u132->scheduler_lock);
-                                retval = edset_output(u132, ring, endp, urb,
-                                        address, endp->toggle_bits,
-                                        u132_hcd_bulk_output_sent);
-                                if (retval == 0) {
-                                } else
-                                        u132_hcd_giveback_urb(u132, endp, urb,
-                                                retval);
-                                return;
-                        }
-                }
-        }
+       struct u132 *u132 = endp->u132;
+       mutex_lock(&u132->scheduler_lock);
+       ring = endp->ring;
+       if (endp->edset_flush) {
+               endp->edset_flush = 0;
+               if (endp->dequeueing)
+                       usb_ftdi_elan_edset_flush(u132->platform_dev,
+                               ring->number, endp);
+               mutex_unlock(&u132->scheduler_lock);
+               u132_endp_put_kref(u132, endp);
+               return;
+       } else if (endp->active) {
+               mutex_unlock(&u132->scheduler_lock);
+               u132_endp_put_kref(u132, endp);
+               return;
+       } else if (ring->in_use) {
+               mutex_unlock(&u132->scheduler_lock);
+               u132_endp_put_kref(u132, endp);
+               return;
+       } else if (endp->queue_next == endp->queue_last) {
+               mutex_unlock(&u132->scheduler_lock);
+               u132_endp_put_kref(u132, endp);
+               return;
+       } else if (endp->pipetype == PIPE_INTERRUPT) {
+               u8 address = u132->addr[endp->usb_addr].address;
+               if (ring->in_use) {
+                       mutex_unlock(&u132->scheduler_lock);
+                       u132_endp_put_kref(u132, endp);
+                       return;
+               } else {
+                       int retval;
+                       struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+                               endp->queue_next];
+                       endp->active = 1;
+                       ring->curr_endp = endp;
+                       ring->in_use = 1;
+                       mutex_unlock(&u132->scheduler_lock);
+                       retval = edset_single(u132, ring, endp, urb, address,
+                               endp->toggle_bits, u132_hcd_interrupt_recv);
+                       if (retval != 0)
+                               u132_hcd_giveback_urb(u132, endp, urb, retval);
+                       return;
+               }
+       } else if (endp->pipetype == PIPE_CONTROL) {
+               u8 address = u132->addr[endp->usb_addr].address;
+               if (ring->in_use) {
+                       mutex_unlock(&u132->scheduler_lock);
+                       u132_endp_put_kref(u132, endp);
+                       return;
+               } else if (address == 0) {
+                       int retval;
+                       struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+                               endp->queue_next];
+                       endp->active = 1;
+                       ring->curr_endp = endp;
+                       ring->in_use = 1;
+                       mutex_unlock(&u132->scheduler_lock);
+                       retval = edset_setup(u132, ring, endp, urb, address,
+                               0x2, u132_hcd_initial_setup_sent);
+                       if (retval != 0)
+                               u132_hcd_giveback_urb(u132, endp, urb, retval);
+                       return;
+               } else if (endp->usb_addr == 0) {
+                       int retval;
+                       struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+                               endp->queue_next];
+                       endp->active = 1;
+                       ring->curr_endp = endp;
+                       ring->in_use = 1;
+                       mutex_unlock(&u132->scheduler_lock);
+                       retval = edset_setup(u132, ring, endp, urb, 0, 0x2,
+                               u132_hcd_enumeration_address_sent);
+                       if (retval != 0)
+                               u132_hcd_giveback_urb(u132, endp, urb, retval);
+                       return;
+               } else {
+                       int retval;
+                       u8 address = u132->addr[endp->usb_addr].address;
+                       struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+                               endp->queue_next];
+                       endp->active = 1;
+                       ring->curr_endp = endp;
+                       ring->in_use = 1;
+                       mutex_unlock(&u132->scheduler_lock);
+                       retval = edset_setup(u132, ring, endp, urb, address,
+                               0x2, u132_hcd_configure_setup_sent);
+                       if (retval != 0)
+                               u132_hcd_giveback_urb(u132, endp, urb, retval);
+                       return;
+               }
+       } else {
+               if (endp->input) {
+                       u8 address = u132->addr[endp->usb_addr].address;
+                       if (ring->in_use) {
+                               mutex_unlock(&u132->scheduler_lock);
+                               u132_endp_put_kref(u132, endp);
+                               return;
+                       } else {
+                               int retval;
+                               struct urb *urb = endp->urb_list[
+                                       ENDP_QUEUE_MASK & endp->queue_next];
+                               endp->active = 1;
+                               ring->curr_endp = endp;
+                               ring->in_use = 1;
+                               mutex_unlock(&u132->scheduler_lock);
+                               retval = edset_input(u132, ring, endp, urb,
+                                       address, endp->toggle_bits,
+                                       u132_hcd_bulk_input_recv);
+                               if (retval == 0) {
+                               } else
+                                       u132_hcd_giveback_urb(u132, endp, urb,
+                                               retval);
+                               return;
+                       }
+               } else {        /* output pipe */
+                       u8 address = u132->addr[endp->usb_addr].address;
+                       if (ring->in_use) {
+                               mutex_unlock(&u132->scheduler_lock);
+                               u132_endp_put_kref(u132, endp);
+                               return;
+                       } else {
+                               int retval;
+                               struct urb *urb = endp->urb_list[
+                                       ENDP_QUEUE_MASK & endp->queue_next];
+                               endp->active = 1;
+                               ring->curr_endp = endp;
+                               ring->in_use = 1;
+                               mutex_unlock(&u132->scheduler_lock);
+                               retval = edset_output(u132, ring, endp, urb,
+                                       address, endp->toggle_bits,
+                                       u132_hcd_bulk_output_sent);
+                               if (retval == 0) {
+                               } else
+                                       u132_hcd_giveback_urb(u132, endp, urb,
+                                               retval);
+                               return;
+                       }
+               }
+       }
 }
 #ifdef CONFIG_PM
 
 static void port_power(struct u132 *u132, int pn, int is_on)
 {
-        u132->port[pn].power = is_on;
+       u132->port[pn].power = is_on;
 }
 
 #endif
 
 static void u132_power(struct u132 *u132, int is_on)
 {
-        struct usb_hcd *hcd = u132_to_hcd(u132)
-                ;        /* hub is inactive unless the port is powered */
-        if (is_on) {
-                if (u132->power)
-                        return;
-                u132->power = 1;
-                hcd->self.controller->power.power_state = PMSG_ON;
-        } else {
-                u132->power = 0;
-                hcd->state = HC_STATE_HALT;
-                hcd->self.controller->power.power_state = PMSG_SUSPEND;
-        }
+       struct usb_hcd *hcd = u132_to_hcd(u132)
+               ;       /* hub is inactive unless the port is powered */
+       if (is_on) {
+               if (u132->power)
+                       return;
+               u132->power = 1;
+       } else {
+               u132->power = 0;
+               hcd->state = HC_STATE_HALT;
+       }
 }
 
 static int u132_periodic_reinit(struct u132 *u132)
 {
-        int retval;
-        u32 fi = u132->hc_fminterval & 0x03fff;
-        u32 fit;
-        u32 fminterval;
-        retval = u132_read_pcimem(u132, fminterval, &fminterval);
-        if (retval)
-                return retval;
-        fit = fminterval & FIT;
-        retval = u132_write_pcimem(u132, fminterval,
-                (fit ^ FIT) | u132->hc_fminterval);
-        if (retval)
-                return retval;
-        retval = u132_write_pcimem(u132, periodicstart,
-                ((9 *fi) / 10) & 0x3fff);
-        if (retval)
-                return retval;
-        return 0;
+       int retval;
+       u32 fi = u132->hc_fminterval & 0x03fff;
+       u32 fit;
+       u32 fminterval;
+       retval = u132_read_pcimem(u132, fminterval, &fminterval);
+       if (retval)
+               return retval;
+       fit = fminterval & FIT;
+       retval = u132_write_pcimem(u132, fminterval,
+               (fit ^ FIT) | u132->hc_fminterval);
+       if (retval)
+               return retval;
+       retval = u132_write_pcimem(u132, periodicstart,
+               ((9 * fi) / 10) & 0x3fff);
+       if (retval)
+               return retval;
+       return 0;
 }
 
 static char *hcfs2string(int state)
 {
-        switch (state) {
-        case OHCI_USB_RESET:
-                return "reset";
-        case OHCI_USB_RESUME:
-                return "resume";
-        case OHCI_USB_OPER:
-                return "operational";
-        case OHCI_USB_SUSPEND:
-                return "suspend";
-        }
-        return "?";
+       switch (state) {
+       case OHCI_USB_RESET:
+               return "reset";
+       case OHCI_USB_RESUME:
+               return "resume";
+       case OHCI_USB_OPER:
+               return "operational";
+       case OHCI_USB_SUSPEND:
+               return "suspend";
+       }
+       return "?";
 }
 
 static int u132_init(struct u132 *u132)
 {
-        int retval;
-        u32 control;
-        u132_disable(u132);
-        u132->next_statechange = jiffies;
-        retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE);
-        if (retval)
-                return retval;
-        retval = u132_read_pcimem(u132, control, &control);
-        if (retval)
-                return retval;
-        if (u132->num_ports == 0) {
-                u32 rh_a = -1;
-                retval = u132_read_pcimem(u132, roothub.a, &rh_a);
-                if (retval)
-                        return retval;
-                u132->num_ports = rh_a & RH_A_NDP;
-                retval = read_roothub_info(u132);
-                if (retval)
-                        return retval;
-        }
-        if (u132->num_ports > MAX_U132_PORTS) {
-                return -EINVAL;
-        }
-        return 0;
+       int retval;
+       u32 control;
+       u132_disable(u132);
+       u132->next_statechange = jiffies;
+       retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE);
+       if (retval)
+               return retval;
+       retval = u132_read_pcimem(u132, control, &control);
+       if (retval)
+               return retval;
+       if (u132->num_ports == 0) {
+               u32 rh_a = -1;
+               retval = u132_read_pcimem(u132, roothub.a, &rh_a);
+               if (retval)
+                       return retval;
+               u132->num_ports = rh_a & RH_A_NDP;
+               retval = read_roothub_info(u132);
+               if (retval)
+                       return retval;
+       }
+       if (u132->num_ports > MAX_U132_PORTS)
+               return -EINVAL;
+
+       return 0;
 }
 
 
@@ -1613,280 +1603,278 @@ static int u132_init(struct u132 *u132)
 */
 static int u132_run(struct u132 *u132)
 {
-        int retval;
-        u32 control;
-        u32 status;
-        u32 fminterval;
-        u32 periodicstart;
-        u32 cmdstatus;
-        u32 roothub_a;
-        int mask = OHCI_INTR_INIT;
-        int first = u132->hc_fminterval == 0;
-        int sleep_time = 0;
-        int reset_timeout = 30;        /* ... allow extra time */
-        u132_disable(u132);
-        if (first) {
-                u32 temp;
-                retval = u132_read_pcimem(u132, fminterval, &temp);
-                if (retval)
-                        return retval;
-                u132->hc_fminterval = temp & 0x3fff;
-                if (u132->hc_fminterval != FI) {
-                }
-                u132->hc_fminterval |= FSMP(u132->hc_fminterval) << 16;
-        }
-        retval = u132_read_pcimem(u132, control, &u132->hc_control);
-        if (retval)
-                return retval;
-        dev_info(&u132->platform_dev->dev, "resetting from state '%s', control "
-                "= %08X\n", hcfs2string(u132->hc_control & OHCI_CTRL_HCFS),
-                u132->hc_control);
-        switch (u132->hc_control & OHCI_CTRL_HCFS) {
-        case OHCI_USB_OPER:
-                sleep_time = 0;
-                break;
-        case OHCI_USB_SUSPEND:
-        case OHCI_USB_RESUME:
-                u132->hc_control &= OHCI_CTRL_RWC;
-                u132->hc_control |= OHCI_USB_RESUME;
-                sleep_time = 10;
-                break;
-        default:
-                u132->hc_control &= OHCI_CTRL_RWC;
-                u132->hc_control |= OHCI_USB_RESET;
-                sleep_time = 50;
-                break;
-        }
-        retval = u132_write_pcimem(u132, control, u132->hc_control);
-        if (retval)
-                return retval;
-        retval = u132_read_pcimem(u132, control, &control);
-        if (retval)
-                return retval;
-        msleep(sleep_time);
-        retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
-        if (retval)
-                return retval;
-        if (!(roothub_a & RH_A_NPS)) {
-                int temp;        /* power down each port */
-                for (temp = 0; temp < u132->num_ports; temp++) {
-                        retval = u132_write_pcimem(u132,
-                                roothub.portstatus[temp], RH_PS_LSDA);
-                        if (retval)
-                                return retval;
-                }
-        }
-        retval = u132_read_pcimem(u132, control, &control);
-        if (retval)
-                return retval;
-      retry:retval = u132_read_pcimem(u132, cmdstatus, &status);
-        if (retval)
-                return retval;
-        retval = u132_write_pcimem(u132, cmdstatus, OHCI_HCR);
-        if (retval)
-                return retval;
-      extra:{
-                retval = u132_read_pcimem(u132, cmdstatus, &status);
-                if (retval)
-                        return retval;
-                if (0 != (status & OHCI_HCR)) {
-                        if (--reset_timeout == 0) {
-                                dev_err(&u132->platform_dev->dev, "USB HC reset"
-                                        " timed out!\n");
-                                return -ENODEV;
-                        } else {
-                                msleep(5);
-                                goto extra;
-                        }
-                }
-        }
-        if (u132->flags & OHCI_QUIRK_INITRESET) {
-                retval = u132_write_pcimem(u132, control, u132->hc_control);
-                if (retval)
-                        return retval;
-                retval = u132_read_pcimem(u132, control, &control);
-                if (retval)
-                        return retval;
-        }
-        retval = u132_write_pcimem(u132, ed_controlhead, 0x00000000);
-        if (retval)
-                return retval;
-        retval = u132_write_pcimem(u132, ed_bulkhead, 0x11000000);
-        if (retval)
-                return retval;
-        retval = u132_write_pcimem(u132, hcca, 0x00000000);
-        if (retval)
-                return retval;
-        retval = u132_periodic_reinit(u132);
-        if (retval)
-                return retval;
-        retval = u132_read_pcimem(u132, fminterval, &fminterval);
-        if (retval)
-                return retval;
-        retval = u132_read_pcimem(u132, periodicstart, &periodicstart);
-        if (retval)
-                return retval;
-        if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) {
-                if (!(u132->flags & OHCI_QUIRK_INITRESET)) {
-                        u132->flags |= OHCI_QUIRK_INITRESET;
-                        goto retry;
-                } else
-                        dev_err(&u132->platform_dev->dev, "init err(%08x %04x)"
-                                "\n", fminterval, periodicstart);
-        }                        /* start controller operations */
-        u132->hc_control &= OHCI_CTRL_RWC;
-        u132->hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER;
-        retval = u132_write_pcimem(u132, control, u132->hc_control);
-        if (retval)
-                return retval;
-        retval = u132_write_pcimem(u132, cmdstatus, OHCI_BLF);
-        if (retval)
-                return retval;
-        retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus);
-        if (retval)
-                return retval;
-        retval = u132_read_pcimem(u132, control, &control);
-        if (retval)
-                return retval;
-        u132_to_hcd(u132)->state = HC_STATE_RUNNING;
-        retval = u132_write_pcimem(u132, roothub.status, RH_HS_DRWE);
-        if (retval)
-                return retval;
-        retval = u132_write_pcimem(u132, intrstatus, mask);
-        if (retval)
-                return retval;
-        retval = u132_write_pcimem(u132, intrdisable,
-                OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO |
-                OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH |
-                OHCI_INTR_SO);
-        if (retval)
-                return retval;        /* handle root hub init quirks ... */
-        retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
-        if (retval)
-                return retval;
-        roothub_a &= ~(RH_A_PSM | RH_A_OCPM);
-        if (u132->flags & OHCI_QUIRK_SUPERIO) {
-                roothub_a |= RH_A_NOCP;
-                roothub_a &= ~(RH_A_POTPGT | RH_A_NPS);
-                retval = u132_write_pcimem(u132, roothub.a, roothub_a);
-                if (retval)
-                        return retval;
-        } else if ((u132->flags & OHCI_QUIRK_AMD756) || distrust_firmware) {
-                roothub_a |= RH_A_NPS;
-                retval = u132_write_pcimem(u132, roothub.a, roothub_a);
-                if (retval)
-                        return retval;
-        }
-        retval = u132_write_pcimem(u132, roothub.status, RH_HS_LPSC);
-        if (retval)
-                return retval;
-        retval = u132_write_pcimem(u132, roothub.b,
-                (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM);
-        if (retval)
-                return retval;
-        retval = u132_read_pcimem(u132, control, &control);
-        if (retval)
-                return retval;
-        mdelay((roothub_a >> 23) & 0x1fe);
-        u132_to_hcd(u132)->state = HC_STATE_RUNNING;
-        return 0;
+       int retval;
+       u32 control;
+       u32 status;
+       u32 fminterval;
+       u32 periodicstart;
+       u32 cmdstatus;
+       u32 roothub_a;
+       int mask = OHCI_INTR_INIT;
+       int first = u132->hc_fminterval == 0;
+       int sleep_time = 0;
+       int reset_timeout = 30; /* ... allow extra time */
+       u132_disable(u132);
+       if (first) {
+               u32 temp;
+               retval = u132_read_pcimem(u132, fminterval, &temp);
+               if (retval)
+                       return retval;
+               u132->hc_fminterval = temp & 0x3fff;
+               u132->hc_fminterval |= FSMP(u132->hc_fminterval) << 16;
+       }
+       retval = u132_read_pcimem(u132, control, &u132->hc_control);
+       if (retval)
+               return retval;
+       dev_info(&u132->platform_dev->dev, "resetting from state '%s', control "
+               "= %08X\n", hcfs2string(u132->hc_control & OHCI_CTRL_HCFS),
+               u132->hc_control);
+       switch (u132->hc_control & OHCI_CTRL_HCFS) {
+       case OHCI_USB_OPER:
+               sleep_time = 0;
+               break;
+       case OHCI_USB_SUSPEND:
+       case OHCI_USB_RESUME:
+               u132->hc_control &= OHCI_CTRL_RWC;
+               u132->hc_control |= OHCI_USB_RESUME;
+               sleep_time = 10;
+               break;
+       default:
+               u132->hc_control &= OHCI_CTRL_RWC;
+               u132->hc_control |= OHCI_USB_RESET;
+               sleep_time = 50;
+               break;
+       }
+       retval = u132_write_pcimem(u132, control, u132->hc_control);
+       if (retval)
+               return retval;
+       retval = u132_read_pcimem(u132, control, &control);
+       if (retval)
+               return retval;
+       msleep(sleep_time);
+       retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
+       if (retval)
+               return retval;
+       if (!(roothub_a & RH_A_NPS)) {
+               int temp;       /* power down each port */
+               for (temp = 0; temp < u132->num_ports; temp++) {
+                       retval = u132_write_pcimem(u132,
+                               roothub.portstatus[temp], RH_PS_LSDA);
+                       if (retval)
+                               return retval;
+               }
+       }
+       retval = u132_read_pcimem(u132, control, &control);
+       if (retval)
+               return retval;
+retry:
+       retval = u132_read_pcimem(u132, cmdstatus, &status);
+       if (retval)
+               return retval;
+       retval = u132_write_pcimem(u132, cmdstatus, OHCI_HCR);
+       if (retval)
+               return retval;
+extra: {
+               retval = u132_read_pcimem(u132, cmdstatus, &status);
+               if (retval)
+                       return retval;
+               if (0 != (status & OHCI_HCR)) {
+                       if (--reset_timeout == 0) {
+                               dev_err(&u132->platform_dev->dev, "USB HC reset"
+                                       " timed out!\n");
+                               return -ENODEV;
+                       } else {
+                               msleep(5);
+                               goto extra;
+                       }
+               }
+       }
+       if (u132->flags & OHCI_QUIRK_INITRESET) {
+               retval = u132_write_pcimem(u132, control, u132->hc_control);
+               if (retval)
+                       return retval;
+               retval = u132_read_pcimem(u132, control, &control);
+               if (retval)
+                       return retval;
+       }
+       retval = u132_write_pcimem(u132, ed_controlhead, 0x00000000);
+       if (retval)
+               return retval;
+       retval = u132_write_pcimem(u132, ed_bulkhead, 0x11000000);
+       if (retval)
+               return retval;
+       retval = u132_write_pcimem(u132, hcca, 0x00000000);
+       if (retval)
+               return retval;
+       retval = u132_periodic_reinit(u132);
+       if (retval)
+               return retval;
+       retval = u132_read_pcimem(u132, fminterval, &fminterval);
+       if (retval)
+               return retval;
+       retval = u132_read_pcimem(u132, periodicstart, &periodicstart);
+       if (retval)
+               return retval;
+       if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) {
+               if (!(u132->flags & OHCI_QUIRK_INITRESET)) {
+                       u132->flags |= OHCI_QUIRK_INITRESET;
+                       goto retry;
+               } else
+                       dev_err(&u132->platform_dev->dev, "init err(%08x %04x)"
+                               "\n", fminterval, periodicstart);
+       }                       /* start controller operations */
+       u132->hc_control &= OHCI_CTRL_RWC;
+       u132->hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER;
+       retval = u132_write_pcimem(u132, control, u132->hc_control);
+       if (retval)
+               return retval;
+       retval = u132_write_pcimem(u132, cmdstatus, OHCI_BLF);
+       if (retval)
+               return retval;
+       retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus);
+       if (retval)
+               return retval;
+       retval = u132_read_pcimem(u132, control, &control);
+       if (retval)
+               return retval;
+       u132_to_hcd(u132)->state = HC_STATE_RUNNING;
+       retval = u132_write_pcimem(u132, roothub.status, RH_HS_DRWE);
+       if (retval)
+               return retval;
+       retval = u132_write_pcimem(u132, intrstatus, mask);
+       if (retval)
+               return retval;
+       retval = u132_write_pcimem(u132, intrdisable,
+               OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO |
+               OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH |
+               OHCI_INTR_SO);
+       if (retval)
+               return retval;  /* handle root hub init quirks ... */
+       retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
+       if (retval)
+               return retval;
+       roothub_a &= ~(RH_A_PSM | RH_A_OCPM);
+       if (u132->flags & OHCI_QUIRK_SUPERIO) {
+               roothub_a |= RH_A_NOCP;
+               roothub_a &= ~(RH_A_POTPGT | RH_A_NPS);
+               retval = u132_write_pcimem(u132, roothub.a, roothub_a);
+               if (retval)
+                       return retval;
+       } else if ((u132->flags & OHCI_QUIRK_AMD756) || distrust_firmware) {
+               roothub_a |= RH_A_NPS;
+               retval = u132_write_pcimem(u132, roothub.a, roothub_a);
+               if (retval)
+                       return retval;
+       }
+       retval = u132_write_pcimem(u132, roothub.status, RH_HS_LPSC);
+       if (retval)
+               return retval;
+       retval = u132_write_pcimem(u132, roothub.b,
+               (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM);
+       if (retval)
+               return retval;
+       retval = u132_read_pcimem(u132, control, &control);
+       if (retval)
+               return retval;
+       mdelay((roothub_a >> 23) & 0x1fe);
+       u132_to_hcd(u132)->state = HC_STATE_RUNNING;
+       return 0;
 }
 
 static void u132_hcd_stop(struct usb_hcd *hcd)
 {
-        struct u132 *u132 = hcd_to_u132(hcd);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p) has b"
-                        "een removed %d\n", u132, hcd, u132->going);
-        } else if (u132->going > 0) {
-                dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
-                        "ed\n", hcd);
-        } else {
-                mutex_lock(&u132->sw_lock);
-                msleep(100);
-                u132_power(u132, 0);
-                mutex_unlock(&u132->sw_lock);
-        }
+       struct u132 *u132 = hcd_to_u132(hcd);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p) has b"
+                       "een removed %d\n", u132, hcd, u132->going);
+       } else if (u132->going > 0) {
+               dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
+                       "ed\n", hcd);
+       } else {
+               mutex_lock(&u132->sw_lock);
+               msleep(100);
+               u132_power(u132, 0);
+               mutex_unlock(&u132->sw_lock);
+       }
 }
 
 static int u132_hcd_start(struct usb_hcd *hcd)
 {
-        struct u132 *u132 = hcd_to_u132(hcd);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                return -ENODEV;
-        } else if (u132->going > 0) {
-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
-                return -ESHUTDOWN;
-        } else if (hcd->self.controller) {
-                int retval;
-                struct platform_device *pdev =
-                        to_platform_device(hcd->self.controller);
-                u16 vendor = ((struct u132_platform_data *)
-                        (pdev->dev.platform_data))->vendor;
-                u16 device = ((struct u132_platform_data *)
-                        (pdev->dev.platform_data))->device;
-                mutex_lock(&u132->sw_lock);
-                msleep(10);
-                if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) {
-                        u132->flags = OHCI_QUIRK_AMD756;
-                } else if (vendor == PCI_VENDOR_ID_OPTI && device == 0xc861) {
-                        dev_err(&u132->platform_dev->dev, "WARNING: OPTi workar"
-                                "ounds unavailable\n");
-                } else if (vendor == PCI_VENDOR_ID_COMPAQ && device == 0xa0f8)
-                        u132->flags |= OHCI_QUIRK_ZFMICRO;
-                retval = u132_run(u132);
-                if (retval) {
-                        u132_disable(u132);
-                        u132->going = 1;
-                }
-                msleep(100);
-                mutex_unlock(&u132->sw_lock);
-                return retval;
-        } else {
-                dev_err(&u132->platform_dev->dev, "platform_device missing\n");
-                return -ENODEV;
-        }
+       struct u132 *u132 = hcd_to_u132(hcd);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               return -ENODEV;
+       } else if (u132->going > 0) {
+               dev_err(&u132->platform_dev->dev, "device is being removed\n");
+               return -ESHUTDOWN;
+       } else if (hcd->self.controller) {
+               int retval;
+               struct platform_device *pdev =
+                       to_platform_device(hcd->self.controller);
+               u16 vendor = ((struct u132_platform_data *)
+                       (pdev->dev.platform_data))->vendor;
+               u16 device = ((struct u132_platform_data *)
+                       (pdev->dev.platform_data))->device;
+               mutex_lock(&u132->sw_lock);
+               msleep(10);
+               if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) {
+                       u132->flags = OHCI_QUIRK_AMD756;
+               } else if (vendor == PCI_VENDOR_ID_OPTI && device == 0xc861) {
+                       dev_err(&u132->platform_dev->dev, "WARNING: OPTi workar"
+                               "ounds unavailable\n");
+               } else if (vendor == PCI_VENDOR_ID_COMPAQ && device == 0xa0f8)
+                       u132->flags |= OHCI_QUIRK_ZFMICRO;
+               retval = u132_run(u132);
+               if (retval) {
+                       u132_disable(u132);
+                       u132->going = 1;
+               }
+               msleep(100);
+               mutex_unlock(&u132->sw_lock);
+               return retval;
+       } else {
+               dev_err(&u132->platform_dev->dev, "platform_device missing\n");
+               return -ENODEV;
+       }
 }
 
 static int u132_hcd_reset(struct usb_hcd *hcd)
 {
-        struct u132 *u132 = hcd_to_u132(hcd);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                return -ENODEV;
-        } else if (u132->going > 0) {
-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
-                return -ESHUTDOWN;
-        } else {
-                int retval;
-                mutex_lock(&u132->sw_lock);
-                retval = u132_init(u132);
-                if (retval) {
-                        u132_disable(u132);
-                        u132->going = 1;
-                }
-                mutex_unlock(&u132->sw_lock);
-                return retval;
-        }
+       struct u132 *u132 = hcd_to_u132(hcd);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               return -ENODEV;
+       } else if (u132->going > 0) {
+               dev_err(&u132->platform_dev->dev, "device is being removed\n");
+               return -ESHUTDOWN;
+       } else {
+               int retval;
+               mutex_lock(&u132->sw_lock);
+               retval = u132_init(u132);
+               if (retval) {
+                       u132_disable(u132);
+                       u132->going = 1;
+               }
+               mutex_unlock(&u132->sw_lock);
+               return retval;
+       }
 }
 
 static int create_endpoint_and_queue_int(struct u132 *u132,
        struct u132_udev *udev, struct urb *urb,
-        struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
-        gfp_t mem_flags)
+       struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
+       gfp_t mem_flags)
 {
-        struct u132_ring *ring;
-        unsigned long irqs;
+       struct u132_ring *ring;
+       unsigned long irqs;
        int rc;
        u8 endp_number;
        struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
 
-        if (!endp) {
-                return -ENOMEM;
-        }
+       if (!endp)
+               return -ENOMEM;
 
        spin_lock_init(&endp->queue_lock.slock);
        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
@@ -1899,94 +1887,93 @@ static int create_endpoint_and_queue_int(struct u132 *u132,
 
        endp_number = ++u132->num_endpoints;
        urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
-        INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
-        INIT_LIST_HEAD(&endp->urb_more);
-        ring = endp->ring = &u132->ring[0];
-        if (ring->curr_endp) {
-                list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
-        } else {
-                INIT_LIST_HEAD(&endp->endp_ring);
-                ring->curr_endp = endp;
-        }
-        ring->length += 1;
-        endp->dequeueing = 0;
-        endp->edset_flush = 0;
-        endp->active = 0;
-        endp->delayed = 0;
-        endp->endp_number = endp_number;
-        endp->u132 = u132;
+       INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
+       INIT_LIST_HEAD(&endp->urb_more);
+       ring = endp->ring = &u132->ring[0];
+       if (ring->curr_endp) {
+               list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+       } else {
+               INIT_LIST_HEAD(&endp->endp_ring);
+               ring->curr_endp = endp;
+       }
+       ring->length += 1;
+       endp->dequeueing = 0;
+       endp->edset_flush = 0;
+       endp->active = 0;
+       endp->delayed = 0;
+       endp->endp_number = endp_number;
+       endp->u132 = u132;
        endp->hep = urb->ep;
-        endp->pipetype = usb_pipetype(urb->pipe);
-        u132_endp_init_kref(u132, endp);
-        if (usb_pipein(urb->pipe)) {
-                endp->toggle_bits = 0x2;
-                usb_settoggle(udev->usb_device, usb_endp, 0, 0);
-                endp->input = 1;
-                endp->output = 0;
-                udev->endp_number_in[usb_endp] = endp_number;
-                u132_udev_get_kref(u132, udev);
-        } else {
-                endp->toggle_bits = 0x2;
-                usb_settoggle(udev->usb_device, usb_endp, 1, 0);
-                endp->input = 0;
-                endp->output = 1;
-                udev->endp_number_out[usb_endp] = endp_number;
-                u132_udev_get_kref(u132, udev);
-        }
-        urb->hcpriv = u132;
-        endp->delayed = 1;
-        endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
-        endp->udev_number = address;
-        endp->usb_addr = usb_addr;
-        endp->usb_endp = usb_endp;
-        endp->queue_size = 1;
-        endp->queue_last = 0;
-        endp->queue_next = 0;
-        endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
-        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-        u132_endp_queue_work(u132, endp, msecs_to_jiffies(urb->interval));
-        return 0;
+       endp->pipetype = usb_pipetype(urb->pipe);
+       u132_endp_init_kref(u132, endp);
+       if (usb_pipein(urb->pipe)) {
+               endp->toggle_bits = 0x2;
+               usb_settoggle(udev->usb_device, usb_endp, 0, 0);
+               endp->input = 1;
+               endp->output = 0;
+               udev->endp_number_in[usb_endp] = endp_number;
+               u132_udev_get_kref(u132, udev);
+       } else {
+               endp->toggle_bits = 0x2;
+               usb_settoggle(udev->usb_device, usb_endp, 1, 0);
+               endp->input = 0;
+               endp->output = 1;
+               udev->endp_number_out[usb_endp] = endp_number;
+               u132_udev_get_kref(u132, udev);
+       }
+       urb->hcpriv = u132;
+       endp->delayed = 1;
+       endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
+       endp->udev_number = address;
+       endp->usb_addr = usb_addr;
+       endp->usb_endp = usb_endp;
+       endp->queue_size = 1;
+       endp->queue_last = 0;
+       endp->queue_next = 0;
+       endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+       spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+       u132_endp_queue_work(u132, endp, msecs_to_jiffies(urb->interval));
+       return 0;
 }
 
 static int queue_int_on_old_endpoint(struct u132 *u132,
        struct u132_udev *udev, struct urb *urb,
-        struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
-        u8 usb_endp, u8 address)
-{
-        urb->hcpriv = u132;
-        endp->delayed = 1;
-        endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
-        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
-                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
-        } else {
-                struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
-                        GFP_ATOMIC);
-                if (urbq == NULL) {
-                        endp->queue_size -= 1;
-                        return -ENOMEM;
-                } else {
-                        list_add_tail(&urbq->urb_more, &endp->urb_more);
-                        urbq->urb = urb;
-                }
-        }
-        return 0;
+       struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+       u8 usb_endp, u8 address)
+{
+       urb->hcpriv = u132;
+       endp->delayed = 1;
+       endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
+       if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+               endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+       } else {
+               struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
+                       GFP_ATOMIC);
+               if (urbq == NULL) {
+                       endp->queue_size -= 1;
+                       return -ENOMEM;
+               } else {
+                       list_add_tail(&urbq->urb_more, &endp->urb_more);
+                       urbq->urb = urb;
+               }
+       }
+       return 0;
 }
 
 static int create_endpoint_and_queue_bulk(struct u132 *u132,
        struct u132_udev *udev, struct urb *urb,
-        struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
-        gfp_t mem_flags)
+       struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
+       gfp_t mem_flags)
 {
-        int ring_number;
-        struct u132_ring *ring;
-        unsigned long irqs;
+       int ring_number;
+       struct u132_ring *ring;
+       unsigned long irqs;
        int rc;
        u8 endp_number;
        struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
 
-        if (!endp) {
-                return -ENOMEM;
-        }
+       if (!endp)
+               return -ENOMEM;
 
        spin_lock_init(&endp->queue_lock.slock);
        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
@@ -1999,91 +1986,90 @@ static int create_endpoint_and_queue_bulk(struct u132 *u132,
 
        endp_number = ++u132->num_endpoints;
        urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
-        INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
-        INIT_LIST_HEAD(&endp->urb_more);
-        endp->dequeueing = 0;
-        endp->edset_flush = 0;
-        endp->active = 0;
-        endp->delayed = 0;
-        endp->endp_number = endp_number;
-        endp->u132 = u132;
+       INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
+       INIT_LIST_HEAD(&endp->urb_more);
+       endp->dequeueing = 0;
+       endp->edset_flush = 0;
+       endp->active = 0;
+       endp->delayed = 0;
+       endp->endp_number = endp_number;
+       endp->u132 = u132;
        endp->hep = urb->ep;
-        endp->pipetype = usb_pipetype(urb->pipe);
-        u132_endp_init_kref(u132, endp);
-        if (usb_pipein(urb->pipe)) {
-                endp->toggle_bits = 0x2;
-                usb_settoggle(udev->usb_device, usb_endp, 0, 0);
-                ring_number = 3;
-                endp->input = 1;
-                endp->output = 0;
-                udev->endp_number_in[usb_endp] = endp_number;
-                u132_udev_get_kref(u132, udev);
-        } else {
-                endp->toggle_bits = 0x2;
-                usb_settoggle(udev->usb_device, usb_endp, 1, 0);
-                ring_number = 2;
-                endp->input = 0;
-                endp->output = 1;
-                udev->endp_number_out[usb_endp] = endp_number;
-                u132_udev_get_kref(u132, udev);
-        }
-        ring = endp->ring = &u132->ring[ring_number - 1];
-        if (ring->curr_endp) {
-                list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
-        } else {
-                INIT_LIST_HEAD(&endp->endp_ring);
-                ring->curr_endp = endp;
-        }
-        ring->length += 1;
-        urb->hcpriv = u132;
-        endp->udev_number = address;
-        endp->usb_addr = usb_addr;
-        endp->usb_endp = usb_endp;
-        endp->queue_size = 1;
-        endp->queue_last = 0;
-        endp->queue_next = 0;
-        endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
-        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-        u132_endp_queue_work(u132, endp, 0);
-        return 0;
+       endp->pipetype = usb_pipetype(urb->pipe);
+       u132_endp_init_kref(u132, endp);
+       if (usb_pipein(urb->pipe)) {
+               endp->toggle_bits = 0x2;
+               usb_settoggle(udev->usb_device, usb_endp, 0, 0);
+               ring_number = 3;
+               endp->input = 1;
+               endp->output = 0;
+               udev->endp_number_in[usb_endp] = endp_number;
+               u132_udev_get_kref(u132, udev);
+       } else {
+               endp->toggle_bits = 0x2;
+               usb_settoggle(udev->usb_device, usb_endp, 1, 0);
+               ring_number = 2;
+               endp->input = 0;
+               endp->output = 1;
+               udev->endp_number_out[usb_endp] = endp_number;
+               u132_udev_get_kref(u132, udev);
+       }
+       ring = endp->ring = &u132->ring[ring_number - 1];
+       if (ring->curr_endp) {
+               list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+       } else {
+               INIT_LIST_HEAD(&endp->endp_ring);
+               ring->curr_endp = endp;
+       }
+       ring->length += 1;
+       urb->hcpriv = u132;
+       endp->udev_number = address;
+       endp->usb_addr = usb_addr;
+       endp->usb_endp = usb_endp;
+       endp->queue_size = 1;
+       endp->queue_last = 0;
+       endp->queue_next = 0;
+       endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+       spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+       u132_endp_queue_work(u132, endp, 0);
+       return 0;
 }
 
 static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
        struct urb *urb,
-        struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
-        u8 usb_endp, u8 address)
-{
-        urb->hcpriv = u132;
-        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
-                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
-        } else {
-                struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
-                        GFP_ATOMIC);
-                if (urbq == NULL) {
-                        endp->queue_size -= 1;
-                        return -ENOMEM;
-                } else {
-                        list_add_tail(&urbq->urb_more, &endp->urb_more);
-                        urbq->urb = urb;
-                }
-        }
-        return 0;
+       struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+       u8 usb_endp, u8 address)
+{
+       urb->hcpriv = u132;
+       if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+               endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+       } else {
+               struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
+                       GFP_ATOMIC);
+               if (urbq == NULL) {
+                       endp->queue_size -= 1;
+                       return -ENOMEM;
+               } else {
+                       list_add_tail(&urbq->urb_more, &endp->urb_more);
+                       urbq->urb = urb;
+               }
+       }
+       return 0;
 }
 
 static int create_endpoint_and_queue_control(struct u132 *u132,
        struct urb *urb,
-        struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp,
-        gfp_t mem_flags)
+       struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp,
+       gfp_t mem_flags)
 {
-        struct u132_ring *ring;
+       struct u132_ring *ring;
        unsigned long irqs;
        int rc;
        u8 endp_number;
        struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
 
-        if (!endp) {
-                return -ENOMEM;
-        }
+       if (!endp)
+               return -ENOMEM;
 
        spin_lock_init(&endp->queue_lock.slock);
        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
@@ -2096,204 +2082,203 @@ static int create_endpoint_and_queue_control(struct u132 *u132,
 
        endp_number = ++u132->num_endpoints;
        urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
-        INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
-        INIT_LIST_HEAD(&endp->urb_more);
-        ring = endp->ring = &u132->ring[0];
-        if (ring->curr_endp) {
-                list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
-        } else {
-                INIT_LIST_HEAD(&endp->endp_ring);
-                ring->curr_endp = endp;
-        }
-        ring->length += 1;
-        endp->dequeueing = 0;
-        endp->edset_flush = 0;
-        endp->active = 0;
-        endp->delayed = 0;
-        endp->endp_number = endp_number;
-        endp->u132 = u132;
+       INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
+       INIT_LIST_HEAD(&endp->urb_more);
+       ring = endp->ring = &u132->ring[0];
+       if (ring->curr_endp) {
+               list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+       } else {
+               INIT_LIST_HEAD(&endp->endp_ring);
+               ring->curr_endp = endp;
+       }
+       ring->length += 1;
+       endp->dequeueing = 0;
+       endp->edset_flush = 0;
+       endp->active = 0;
+       endp->delayed = 0;
+       endp->endp_number = endp_number;
+       endp->u132 = u132;
        endp->hep = urb->ep;
-        u132_endp_init_kref(u132, endp);
-        u132_endp_get_kref(u132, endp);
-        if (usb_addr == 0) {
-                u8 address = u132->addr[usb_addr].address;
-                struct u132_udev *udev = &u132->udev[address];
-                endp->udev_number = address;
-                endp->usb_addr = usb_addr;
-                endp->usb_endp = usb_endp;
-                endp->input = 1;
-                endp->output = 1;
-                endp->pipetype = usb_pipetype(urb->pipe);
-                u132_udev_init_kref(u132, udev);
-                u132_udev_get_kref(u132, udev);
-                udev->endp_number_in[usb_endp] = endp_number;
-                udev->endp_number_out[usb_endp] = endp_number;
-                urb->hcpriv = u132;
-                endp->queue_size = 1;
-                endp->queue_last = 0;
-                endp->queue_next = 0;
-                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
-                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-                u132_endp_queue_work(u132, endp, 0);
-                return 0;
-        } else {                /*(usb_addr > 0) */
-                u8 address = u132->addr[usb_addr].address;
-                struct u132_udev *udev = &u132->udev[address];
-                endp->udev_number = address;
-                endp->usb_addr = usb_addr;
-                endp->usb_endp = usb_endp;
-                endp->input = 1;
-                endp->output = 1;
-                endp->pipetype = usb_pipetype(urb->pipe);
-                u132_udev_get_kref(u132, udev);
-                udev->enumeration = 2;
-                udev->endp_number_in[usb_endp] = endp_number;
-                udev->endp_number_out[usb_endp] = endp_number;
-                urb->hcpriv = u132;
-                endp->queue_size = 1;
-                endp->queue_last = 0;
-                endp->queue_next = 0;
-                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
-                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-                u132_endp_queue_work(u132, endp, 0);
-                return 0;
-        }
+       u132_endp_init_kref(u132, endp);
+       u132_endp_get_kref(u132, endp);
+       if (usb_addr == 0) {
+               u8 address = u132->addr[usb_addr].address;
+               struct u132_udev *udev = &u132->udev[address];
+               endp->udev_number = address;
+               endp->usb_addr = usb_addr;
+               endp->usb_endp = usb_endp;
+               endp->input = 1;
+               endp->output = 1;
+               endp->pipetype = usb_pipetype(urb->pipe);
+               u132_udev_init_kref(u132, udev);
+               u132_udev_get_kref(u132, udev);
+               udev->endp_number_in[usb_endp] = endp_number;
+               udev->endp_number_out[usb_endp] = endp_number;
+               urb->hcpriv = u132;
+               endp->queue_size = 1;
+               endp->queue_last = 0;
+               endp->queue_next = 0;
+               endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+               spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+               u132_endp_queue_work(u132, endp, 0);
+               return 0;
+       } else {                /*(usb_addr > 0) */
+               u8 address = u132->addr[usb_addr].address;
+               struct u132_udev *udev = &u132->udev[address];
+               endp->udev_number = address;
+               endp->usb_addr = usb_addr;
+               endp->usb_endp = usb_endp;
+               endp->input = 1;
+               endp->output = 1;
+               endp->pipetype = usb_pipetype(urb->pipe);
+               u132_udev_get_kref(u132, udev);
+               udev->enumeration = 2;
+               udev->endp_number_in[usb_endp] = endp_number;
+               udev->endp_number_out[usb_endp] = endp_number;
+               urb->hcpriv = u132;
+               endp->queue_size = 1;
+               endp->queue_last = 0;
+               endp->queue_next = 0;
+               endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+               spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+               u132_endp_queue_work(u132, endp, 0);
+               return 0;
+       }
 }
 
 static int queue_control_on_old_endpoint(struct u132 *u132,
        struct urb *urb,
-        struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
-        u8 usb_endp)
-{
-        if (usb_addr == 0) {
-                if (usb_pipein(urb->pipe)) {
-                        urb->hcpriv = u132;
-                        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
-                                endp->urb_list[ENDP_QUEUE_MASK &
-                                        endp->queue_last++] = urb;
-                        } else {
-                                struct u132_urbq *urbq =
-                                        kmalloc(sizeof(struct u132_urbq),
-                                        GFP_ATOMIC);
-                                if (urbq == NULL) {
-                                        endp->queue_size -= 1;
-                                        return -ENOMEM;
-                                } else {
-                                        list_add_tail(&urbq->urb_more,
-                                                &endp->urb_more);
-                                        urbq->urb = urb;
-                                }
-                        }
-                        return 0;
-                } else {        /* usb_pipeout(urb->pipe) */
-                        struct u132_addr *addr = &u132->addr[usb_dev->devnum];
-                        int I = MAX_U132_UDEVS;
-                        int i = 0;
-                        while (--I > 0) {
-                                struct u132_udev *udev = &u132->udev[++i];
-                                if (udev->usb_device) {
-                                        continue;
-                                } else {
-                                        udev->enumeration = 1;
-                                        u132->addr[0].address = i;
-                                        endp->udev_number = i;
-                                        udev->udev_number = i;
-                                        udev->usb_addr = usb_dev->devnum;
-                                        u132_udev_init_kref(u132, udev);
-                                        udev->endp_number_in[usb_endp] =
-                                                endp->endp_number;
-                                        u132_udev_get_kref(u132, udev);
-                                        udev->endp_number_out[usb_endp] =
-                                                endp->endp_number;
-                                        udev->usb_device = usb_dev;
-                                        ((u8 *) (urb->setup_packet))[2] =
-                                                addr->address = i;
-                                        u132_udev_get_kref(u132, udev);
-                                        break;
-                                }
-                        }
-                        if (I == 0) {
-                                dev_err(&u132->platform_dev->dev, "run out of d"
-                                        "evice space\n");
-                                return -EINVAL;
-                        }
-                        urb->hcpriv = u132;
-                        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
-                                endp->urb_list[ENDP_QUEUE_MASK &
-                                        endp->queue_last++] = urb;
-                        } else {
-                                struct u132_urbq *urbq =
-                                        kmalloc(sizeof(struct u132_urbq),
-                                        GFP_ATOMIC);
-                                if (urbq == NULL) {
-                                        endp->queue_size -= 1;
-                                        return -ENOMEM;
-                                } else {
-                                        list_add_tail(&urbq->urb_more,
-                                                &endp->urb_more);
-                                        urbq->urb = urb;
-                                }
-                        }
-                        return 0;
-                }
-        } else {                /*(usb_addr > 0) */
-                u8 address = u132->addr[usb_addr].address;
-                struct u132_udev *udev = &u132->udev[address];
-                urb->hcpriv = u132;
-                if (udev->enumeration == 2) {
-                } else
-                        udev->enumeration = 2;
-                if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
-                        endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
-                                urb;
-                } else {
-                        struct u132_urbq *urbq =
-                                kmalloc(sizeof(struct u132_urbq), GFP_ATOMIC);
-                        if (urbq == NULL) {
-                                endp->queue_size -= 1;
-                                return -ENOMEM;
-                        } else {
-                                list_add_tail(&urbq->urb_more, &endp->urb_more);
-                                urbq->urb = urb;
-                        }
-                }
-                return 0;
-        }
+       struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+       u8 usb_endp)
+{
+       if (usb_addr == 0) {
+               if (usb_pipein(urb->pipe)) {
+                       urb->hcpriv = u132;
+                       if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                               endp->urb_list[ENDP_QUEUE_MASK &
+                                       endp->queue_last++] = urb;
+                       } else {
+                               struct u132_urbq *urbq =
+                                       kmalloc(sizeof(struct u132_urbq),
+                                       GFP_ATOMIC);
+                               if (urbq == NULL) {
+                                       endp->queue_size -= 1;
+                                       return -ENOMEM;
+                               } else {
+                                       list_add_tail(&urbq->urb_more,
+                                               &endp->urb_more);
+                                       urbq->urb = urb;
+                               }
+                       }
+                       return 0;
+               } else {        /* usb_pipeout(urb->pipe) */
+                       struct u132_addr *addr = &u132->addr[usb_dev->devnum];
+                       int I = MAX_U132_UDEVS;
+                       int i = 0;
+                       while (--I > 0) {
+                               struct u132_udev *udev = &u132->udev[++i];
+                               if (udev->usb_device) {
+                                       continue;
+                               } else {
+                                       udev->enumeration = 1;
+                                       u132->addr[0].address = i;
+                                       endp->udev_number = i;
+                                       udev->udev_number = i;
+                                       udev->usb_addr = usb_dev->devnum;
+                                       u132_udev_init_kref(u132, udev);
+                                       udev->endp_number_in[usb_endp] =
+                                               endp->endp_number;
+                                       u132_udev_get_kref(u132, udev);
+                                       udev->endp_number_out[usb_endp] =
+                                               endp->endp_number;
+                                       udev->usb_device = usb_dev;
+                                       ((u8 *) (urb->setup_packet))[2] =
+                                               addr->address = i;
+                                       u132_udev_get_kref(u132, udev);
+                                       break;
+                               }
+                       }
+                       if (I == 0) {
+                               dev_err(&u132->platform_dev->dev, "run out of d"
+                                       "evice space\n");
+                               return -EINVAL;
+                       }
+                       urb->hcpriv = u132;
+                       if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                               endp->urb_list[ENDP_QUEUE_MASK &
+                                       endp->queue_last++] = urb;
+                       } else {
+                               struct u132_urbq *urbq =
+                                       kmalloc(sizeof(struct u132_urbq),
+                                       GFP_ATOMIC);
+                               if (urbq == NULL) {
+                                       endp->queue_size -= 1;
+                                       return -ENOMEM;
+                               } else {
+                                       list_add_tail(&urbq->urb_more,
+                                               &endp->urb_more);
+                                       urbq->urb = urb;
+                               }
+                       }
+                       return 0;
+               }
+       } else {                /*(usb_addr > 0) */
+               u8 address = u132->addr[usb_addr].address;
+               struct u132_udev *udev = &u132->udev[address];
+               urb->hcpriv = u132;
+               if (udev->enumeration != 2)
+                       udev->enumeration = 2;
+               if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                       endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+                               urb;
+               } else {
+                       struct u132_urbq *urbq =
+                               kmalloc(sizeof(struct u132_urbq), GFP_ATOMIC);
+                       if (urbq == NULL) {
+                               endp->queue_size -= 1;
+                               return -ENOMEM;
+                       } else {
+                               list_add_tail(&urbq->urb_more, &endp->urb_more);
+                               urbq->urb = urb;
+                       }
+               }
+               return 0;
+       }
 }
 
 static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
                gfp_t mem_flags)
 {
-        struct u132 *u132 = hcd_to_u132(hcd);
-        if (irqs_disabled()) {
-                if (__GFP_WAIT & mem_flags) {
-                        printk(KERN_ERR "invalid context for function that migh"
-                                "t sleep\n");
-                        return -EINVAL;
-                }
-        }
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                return -ENODEV;
-        } else if (u132->going > 0) {
+       struct u132 *u132 = hcd_to_u132(hcd);
+       if (irqs_disabled()) {
+               if (__GFP_WAIT & mem_flags) {
+                       printk(KERN_ERR "invalid context for function that migh"
+                               "t sleep\n");
+                       return -EINVAL;
+               }
+       }
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               return -ENODEV;
+       } else if (u132->going > 0) {
                dev_err(&u132->platform_dev->dev, "device is being removed "
                                "urb=%p\n", urb);
-                return -ESHUTDOWN;
-        } else {
-                u8 usb_addr = usb_pipedevice(urb->pipe);
-                u8 usb_endp = usb_pipeendpoint(urb->pipe);
-                struct usb_device *usb_dev = urb->dev;
-                if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
-                        u8 address = u132->addr[usb_addr].address;
-                        struct u132_udev *udev = &u132->udev[address];
-                        struct u132_endp *endp = urb->ep->hcpriv;
-                        urb->actual_length = 0;
-                        if (endp) {
-                                unsigned long irqs;
-                                int retval;
-                                spin_lock_irqsave(&endp->queue_lock.slock,
-                                        irqs);
+               return -ESHUTDOWN;
+       } else {
+               u8 usb_addr = usb_pipedevice(urb->pipe);
+               u8 usb_endp = usb_pipeendpoint(urb->pipe);
+               struct usb_device *usb_dev = urb->dev;
+               if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
+                       u8 address = u132->addr[usb_addr].address;
+                       struct u132_udev *udev = &u132->udev[address];
+                       struct u132_endp *endp = urb->ep->hcpriv;
+                       urb->actual_length = 0;
+                       if (endp) {
+                               unsigned long irqs;
+                               int retval;
+                               spin_lock_irqsave(&endp->queue_lock.slock,
+                                       irqs);
                                retval = usb_hcd_link_urb_to_ep(hcd, urb);
                                if (retval == 0) {
                                        retval = queue_int_on_old_endpoint(
@@ -2303,39 +2288,39 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
                                                        address);
                                        if (retval)
                                                usb_hcd_unlink_urb_from_ep(
-                                                               hcd, urb);
+       hcd, urb);
                                }
-                                spin_unlock_irqrestore(&endp->queue_lock.slock,
-                                        irqs);
-                                if (retval) {
-                                        return retval;
-                                } else {
-                                        u132_endp_queue_work(u132, endp,
-                                                msecs_to_jiffies(urb->interval))
-                                                ;
-                                        return 0;
-                                }
-                        } else if (u132->num_endpoints == MAX_U132_ENDPS) {
-                                return -EINVAL;
-                        } else {        /*(endp == NULL) */
-                                return create_endpoint_and_queue_int(u132, udev,
+                               spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                       irqs);
+                               if (retval) {
+                                       return retval;
+                               } else {
+                                       u132_endp_queue_work(u132, endp,
+                                               msecs_to_jiffies(urb->interval))
+                                               ;
+                                       return 0;
+                               }
+                       } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+                               return -EINVAL;
+                       } else {        /*(endp == NULL) */
+                               return create_endpoint_and_queue_int(u132, udev,
                                                urb, usb_dev, usb_addr,
                                                usb_endp, address, mem_flags);
-                        }
-                } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
-                        dev_err(&u132->platform_dev->dev, "the hardware does no"
-                                "t support PIPE_ISOCHRONOUS\n");
-                        return -EINVAL;
-                } else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
-                        u8 address = u132->addr[usb_addr].address;
-                        struct u132_udev *udev = &u132->udev[address];
-                        struct u132_endp *endp = urb->ep->hcpriv;
-                        urb->actual_length = 0;
-                        if (endp) {
-                                unsigned long irqs;
-                                int retval;
-                                spin_lock_irqsave(&endp->queue_lock.slock,
-                                        irqs);
+                       }
+               } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+                       dev_err(&u132->platform_dev->dev, "the hardware does no"
+                               "t support PIPE_ISOCHRONOUS\n");
+                       return -EINVAL;
+               } else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
+                       u8 address = u132->addr[usb_addr].address;
+                       struct u132_udev *udev = &u132->udev[address];
+                       struct u132_endp *endp = urb->ep->hcpriv;
+                       urb->actual_length = 0;
+                       if (endp) {
+                               unsigned long irqs;
+                               int retval;
+                               spin_lock_irqsave(&endp->queue_lock.slock,
+                                       irqs);
                                retval = usb_hcd_link_urb_to_ep(hcd, urb);
                                if (retval == 0) {
                                        retval = queue_bulk_on_old_endpoint(
@@ -2345,46 +2330,46 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
                                                        address);
                                        if (retval)
                                                usb_hcd_unlink_urb_from_ep(
-                                                               hcd, urb);
+       hcd, urb);
+                               }
+                               spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                       irqs);
+                               if (retval) {
+                                       return retval;
+                               } else {
+                                       u132_endp_queue_work(u132, endp, 0);
+                                       return 0;
                                }
-                                spin_unlock_irqrestore(&endp->queue_lock.slock,
-                                        irqs);
-                                if (retval) {
-                                        return retval;
-                                } else {
-                                        u132_endp_queue_work(u132, endp, 0);
-                                        return 0;
-                                }
-                        } else if (u132->num_endpoints == MAX_U132_ENDPS) {
-                                return -EINVAL;
-                        } else
-                                return create_endpoint_and_queue_bulk(u132,
+                       } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+                               return -EINVAL;
+                       } else
+                               return create_endpoint_and_queue_bulk(u132,
                                        udev, urb, usb_dev, usb_addr,
-                                        usb_endp, address, mem_flags);
-                } else {
-                        struct u132_endp *endp = urb->ep->hcpriv;
-                        u16 urb_size = 8;
-                        u8 *b = urb->setup_packet;
-                        int i = 0;
-                        char data[30 *3 + 4];
-                        char *d = data;
-                        int m = (sizeof(data) - 1) / 3;
-                        int l = 0;
-                        data[0] = 0;
-                        while (urb_size-- > 0) {
-                                if (i > m) {
-                                } else if (i++ < m) {
-                                        int w = sprintf(d, " %02X", *b++);
-                                        d += w;
-                                        l += w;
-                                } else
-                                        d += sprintf(d, " ..");
-                        }
-                        if (endp) {
-                                unsigned long irqs;
-                                int retval;
-                                spin_lock_irqsave(&endp->queue_lock.slock,
-                                        irqs);
+                                       usb_endp, address, mem_flags);
+               } else {
+                       struct u132_endp *endp = urb->ep->hcpriv;
+                       u16 urb_size = 8;
+                       u8 *b = urb->setup_packet;
+                       int i = 0;
+                       char data[30 * 3 + 4];
+                       char *d = data;
+                       int m = (sizeof(data) - 1) / 3;
+                       int l = 0;
+                       data[0] = 0;
+                       while (urb_size-- > 0) {
+                               if (i > m) {
+                               } else if (i++ < m) {
+                                       int w = sprintf(d, " %02X", *b++);
+                                       d += w;
+                                       l += w;
+                               } else
+                                       d += sprintf(d, " ..");
+                       }
+                       if (endp) {
+                               unsigned long irqs;
+                               int retval;
+                               spin_lock_irqsave(&endp->queue_lock.slock,
+                                       irqs);
                                retval = usb_hcd_link_urb_to_ep(hcd, urb);
                                if (retval == 0) {
                                        retval = queue_control_on_old_endpoint(
@@ -2395,267 +2380,267 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
                                                usb_hcd_unlink_urb_from_ep(
                                                                hcd, urb);
                                }
-                                spin_unlock_irqrestore(&endp->queue_lock.slock,
-                                        irqs);
-                                if (retval) {
-                                        return retval;
-                                } else {
-                                        u132_endp_queue_work(u132, endp, 0);
-                                        return 0;
-                                }
-                        } else if (u132->num_endpoints == MAX_U132_ENDPS) {
-                                return -EINVAL;
-                        } else
-                                return create_endpoint_and_queue_control(u132,
+                               spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                       irqs);
+                               if (retval) {
+                                       return retval;
+                               } else {
+                                       u132_endp_queue_work(u132, endp, 0);
+                                       return 0;
+                               }
+                       } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+                               return -EINVAL;
+                       } else
+                               return create_endpoint_and_queue_control(u132,
                                        urb, usb_dev, usb_addr, usb_endp,
-                                        mem_flags);
-                }
-        }
+                                       mem_flags);
+               }
+       }
 }
 
 static int dequeue_from_overflow_chain(struct u132 *u132,
-        struct u132_endp *endp, struct urb *urb)
-{
-        struct list_head *scan;
-        struct list_head *head = &endp->urb_more;
-        list_for_each(scan, head) {
-                struct u132_urbq *urbq = list_entry(scan, struct u132_urbq,
-                        urb_more);
-                if (urbq->urb == urb) {
-                        struct usb_hcd *hcd = u132_to_hcd(u132);
-                        list_del(scan);
-                        endp->queue_size -= 1;
-                        urb->error_count = 0;
+       struct u132_endp *endp, struct urb *urb)
+{
+       struct list_head *scan;
+       struct list_head *head = &endp->urb_more;
+       list_for_each(scan, head) {
+               struct u132_urbq *urbq = list_entry(scan, struct u132_urbq,
+                       urb_more);
+               if (urbq->urb == urb) {
+                       struct usb_hcd *hcd = u132_to_hcd(u132);
+                       list_del(scan);
+                       endp->queue_size -= 1;
+                       urb->error_count = 0;
                        usb_hcd_giveback_urb(hcd, urb, 0);
-                        return 0;
-                } else
-                        continue;
-        }
-        dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]=%p ring"
-                "[%d] %c%c usb_endp=%d usb_addr=%d size=%d next=%04X last=%04X"
-                "\n", urb, endp->endp_number, endp, endp->ring->number,
-                endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
-                endp->usb_endp, endp->usb_addr, endp->queue_size,
-                endp->queue_next, endp->queue_last);
-        return -EINVAL;
+                       return 0;
+               } else
+                       continue;
+       }
+       dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]=%p ring"
+               "[%d] %c%c usb_endp=%d usb_addr=%d size=%d next=%04X last=%04X"
+               "\n", urb, endp->endp_number, endp, endp->ring->number,
+               endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
+               endp->usb_endp, endp->usb_addr, endp->queue_size,
+               endp->queue_next, endp->queue_last);
+       return -EINVAL;
 }
 
 static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
                struct urb *urb, int status)
 {
-        unsigned long irqs;
+       unsigned long irqs;
        int rc;
 
-        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+       spin_lock_irqsave(&endp->queue_lock.slock, irqs);
        rc = usb_hcd_check_unlink_urb(u132_to_hcd(u132), urb, status);
        if (rc) {
                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
                return rc;
        }
-        if (endp->queue_size == 0) {
-                dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]"
-                        "=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb,
-                        endp->endp_number, endp, endp->ring->number,
-                        endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
-                        endp->usb_endp, endp->usb_addr);
-                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-                return -EINVAL;
-        }
-        if (urb == endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]) {
-                if (endp->active) {
-                        endp->dequeueing = 1;
-                        endp->edset_flush = 1;
-                        u132_endp_queue_work(u132, endp, 0);
-                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-                        return 0;
-                } else {
-                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+       if (endp->queue_size == 0) {
+               dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]"
+                       "=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb,
+                       endp->endp_number, endp, endp->ring->number,
+                       endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
+                       endp->usb_endp, endp->usb_addr);
+               spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+               return -EINVAL;
+       }
+       if (urb == endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]) {
+               if (endp->active) {
+                       endp->dequeueing = 1;
+                       endp->edset_flush = 1;
+                       u132_endp_queue_work(u132, endp, 0);
+                       spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                       return 0;
+               } else {
+                       spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
                        u132_hcd_abandon_urb(u132, endp, urb, status);
-                        return 0;
-                }
-        } else {
-                u16 queue_list = 0;
-                u16 queue_size = endp->queue_size;
-                u16 queue_scan = endp->queue_next;
-                struct urb **urb_slot = NULL;
-                while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
-                        if (urb == endp->urb_list[ENDP_QUEUE_MASK &
-                                ++queue_scan]) {
-                                urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
-                                        queue_scan];
-                                break;
-                        } else
-                                continue;
-                }
-                while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
-                        *urb_slot = endp->urb_list[ENDP_QUEUE_MASK &
-                                ++queue_scan];
-                        urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
-                                queue_scan];
-                }
-                if (urb_slot) {
-                        struct usb_hcd *hcd = u132_to_hcd(u132);
+                       return 0;
+               }
+       } else {
+               u16 queue_list = 0;
+               u16 queue_size = endp->queue_size;
+               u16 queue_scan = endp->queue_next;
+               struct urb **urb_slot = NULL;
+               while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
+                       if (urb == endp->urb_list[ENDP_QUEUE_MASK &
+                               ++queue_scan]) {
+                               urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
+                                       queue_scan];
+                               break;
+                       } else
+                               continue;
+               }
+               while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
+                       *urb_slot = endp->urb_list[ENDP_QUEUE_MASK &
+                               ++queue_scan];
+                       urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
+                               queue_scan];
+               }
+               if (urb_slot) {
+                       struct usb_hcd *hcd = u132_to_hcd(u132);
 
                        usb_hcd_unlink_urb_from_ep(hcd, urb);
-                        endp->queue_size -= 1;
-                        if (list_empty(&endp->urb_more)) {
-                                spin_unlock_irqrestore(&endp->queue_lock.slock,
-                                        irqs);
-                        } else {
-                                struct list_head *next = endp->urb_more.next;
-                                struct u132_urbq *urbq = list_entry(next,
-                                        struct u132_urbq, urb_more);
-                                list_del(next);
-                                *urb_slot = urbq->urb;
-                                spin_unlock_irqrestore(&endp->queue_lock.slock,
-                                        irqs);
-                                kfree(urbq);
-                        } urb->error_count = 0;
+                       endp->queue_size -= 1;
+                       if (list_empty(&endp->urb_more)) {
+                               spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                       irqs);
+                       } else {
+                               struct list_head *next = endp->urb_more.next;
+                               struct u132_urbq *urbq = list_entry(next,
+                                       struct u132_urbq, urb_more);
+                               list_del(next);
+                               *urb_slot = urbq->urb;
+                               spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                       irqs);
+                               kfree(urbq);
+                       } urb->error_count = 0;
                        usb_hcd_giveback_urb(hcd, urb, status);
-                        return 0;
-                } else if (list_empty(&endp->urb_more)) {
-                        dev_err(&u132->platform_dev->dev, "urb=%p not found in "
-                                "endp[%d]=%p ring[%d] %c%c usb_endp=%d usb_addr"
-                                "=%d size=%d next=%04X last=%04X\n", urb,
-                                endp->endp_number, endp, endp->ring->number,
-                                endp->input ? 'I' : ' ',
-                                endp->output ? 'O' : ' ', endp->usb_endp,
-                                endp->usb_addr, endp->queue_size,
-                                endp->queue_next, endp->queue_last);
-                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-                        return -EINVAL;
-                } else {
+                       return 0;
+               } else if (list_empty(&endp->urb_more)) {
+                       dev_err(&u132->platform_dev->dev, "urb=%p not found in "
+                               "endp[%d]=%p ring[%d] %c%c usb_endp=%d usb_addr"
+                               "=%d size=%d next=%04X last=%04X\n", urb,
+                               endp->endp_number, endp, endp->ring->number,
+                               endp->input ? 'I' : ' ',
+                               endp->output ? 'O' : ' ', endp->usb_endp,
+                               endp->usb_addr, endp->queue_size,
+                               endp->queue_next, endp->queue_last);
+                       spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                       return -EINVAL;
+               } else {
                        int retval;
 
                        usb_hcd_unlink_urb_from_ep(u132_to_hcd(u132), urb);
                        retval = dequeue_from_overflow_chain(u132, endp,
-                                urb);
-                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-                        return retval;
-                }
-        }
+                               urb);
+                       spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                       return retval;
+               }
+       }
 }
 
 static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 {
-        struct u132 *u132 = hcd_to_u132(hcd);
-        if (u132->going > 2) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                return -ENODEV;
-        } else {
-                u8 usb_addr = usb_pipedevice(urb->pipe);
-                u8 usb_endp = usb_pipeendpoint(urb->pipe);
-                u8 address = u132->addr[usb_addr].address;
-                struct u132_udev *udev = &u132->udev[address];
-                if (usb_pipein(urb->pipe)) {
-                        u8 endp_number = udev->endp_number_in[usb_endp];
-                        struct u132_endp *endp = u132->endp[endp_number - 1];
-                        return u132_endp_urb_dequeue(u132, endp, urb, status);
-                } else {
-                        u8 endp_number = udev->endp_number_out[usb_endp];
-                        struct u132_endp *endp = u132->endp[endp_number - 1];
-                        return u132_endp_urb_dequeue(u132, endp, urb, status);
-                }
-        }
+       struct u132 *u132 = hcd_to_u132(hcd);
+       if (u132->going > 2) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               return -ENODEV;
+       } else {
+               u8 usb_addr = usb_pipedevice(urb->pipe);
+               u8 usb_endp = usb_pipeendpoint(urb->pipe);
+               u8 address = u132->addr[usb_addr].address;
+               struct u132_udev *udev = &u132->udev[address];
+               if (usb_pipein(urb->pipe)) {
+                       u8 endp_number = udev->endp_number_in[usb_endp];
+                       struct u132_endp *endp = u132->endp[endp_number - 1];
+                       return u132_endp_urb_dequeue(u132, endp, urb, status);
+               } else {
+                       u8 endp_number = udev->endp_number_out[usb_endp];
+                       struct u132_endp *endp = u132->endp[endp_number - 1];
+                       return u132_endp_urb_dequeue(u132, endp, urb, status);
+               }
+       }
 }
 
 static void u132_endpoint_disable(struct usb_hcd *hcd,
-        struct usb_host_endpoint *hep)
-{
-        struct u132 *u132 = hcd_to_u132(hcd);
-        if (u132->going > 2) {
-                dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p hep=%p"
-                        ") has been removed %d\n", u132, hcd, hep,
-                        u132->going);
-        } else {
-                struct u132_endp *endp = hep->hcpriv;
-                if (endp)
-                        u132_endp_put_kref(u132, endp);
-        }
+       struct usb_host_endpoint *hep)
+{
+       struct u132 *u132 = hcd_to_u132(hcd);
+       if (u132->going > 2) {
+               dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p hep=%p"
+                       ") has been removed %d\n", u132, hcd, hep,
+                       u132->going);
+       } else {
+               struct u132_endp *endp = hep->hcpriv;
+               if (endp)
+                       u132_endp_put_kref(u132, endp);
+       }
 }
 
 static int u132_get_frame(struct usb_hcd *hcd)
 {
-        struct u132 *u132 = hcd_to_u132(hcd);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                return -ENODEV;
-        } else if (u132->going > 0) {
-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
-                return -ESHUTDOWN;
-        } else {
-                int frame = 0;
-                dev_err(&u132->platform_dev->dev, "TODO: u132_get_frame\n");
-                msleep(100);
-                return frame;
-        }
+       struct u132 *u132 = hcd_to_u132(hcd);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               return -ENODEV;
+       } else if (u132->going > 0) {
+               dev_err(&u132->platform_dev->dev, "device is being removed\n");
+               return -ESHUTDOWN;
+       } else {
+               int frame = 0;
+               dev_err(&u132->platform_dev->dev, "TODO: u132_get_frame\n");
+               msleep(100);
+               return frame;
+       }
 }
 
 static int u132_roothub_descriptor(struct u132 *u132,
-        struct usb_hub_descriptor *desc)
-{
-        int retval;
-        u16 temp;
-        u32 rh_a = -1;
-        u32 rh_b = -1;
-        retval = u132_read_pcimem(u132, roothub.a, &rh_a);
-        if (retval)
-                return retval;
-        desc->bDescriptorType = 0x29;
-        desc->bPwrOn2PwrGood = (rh_a & RH_A_POTPGT) >> 24;
-        desc->bHubContrCurrent = 0;
-        desc->bNbrPorts = u132->num_ports;
-        temp = 1 + (u132->num_ports / 8);
-        desc->bDescLength = 7 + 2 *temp;
-        temp = 0;
-        if (rh_a & RH_A_NPS)
-                temp |= 0x0002;
-        if (rh_a & RH_A_PSM)
-                temp |= 0x0001;
-        if (rh_a & RH_A_NOCP) {
-                temp |= 0x0010;
-        } else if (rh_a & RH_A_OCPM)
-                temp |= 0x0008;
-        desc->wHubCharacteristics = cpu_to_le16(temp);
-        retval = u132_read_pcimem(u132, roothub.b, &rh_b);
-        if (retval)
-                return retval;
-        memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
-        desc->bitmap[0] = rh_b & RH_B_DR;
-        if (u132->num_ports > 7) {
-                desc->bitmap[1] = (rh_b & RH_B_DR) >> 8;
-                desc->bitmap[2] = 0xff;
-        } else
-                desc->bitmap[1] = 0xff;
-        return 0;
+       struct usb_hub_descriptor *desc)
+{
+       int retval;
+       u16 temp;
+       u32 rh_a = -1;
+       u32 rh_b = -1;
+       retval = u132_read_pcimem(u132, roothub.a, &rh_a);
+       if (retval)
+               return retval;
+       desc->bDescriptorType = 0x29;
+       desc->bPwrOn2PwrGood = (rh_a & RH_A_POTPGT) >> 24;
+       desc->bHubContrCurrent = 0;
+       desc->bNbrPorts = u132->num_ports;
+       temp = 1 + (u132->num_ports / 8);
+       desc->bDescLength = 7 + 2 * temp;
+       temp = 0;
+       if (rh_a & RH_A_NPS)
+               temp |= 0x0002;
+       if (rh_a & RH_A_PSM)
+               temp |= 0x0001;
+       if (rh_a & RH_A_NOCP)
+               temp |= 0x0010;
+       else if (rh_a & RH_A_OCPM)
+               temp |= 0x0008;
+       desc->wHubCharacteristics = cpu_to_le16(temp);
+       retval = u132_read_pcimem(u132, roothub.b, &rh_b);
+       if (retval)
+               return retval;
+       memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
+       desc->bitmap[0] = rh_b & RH_B_DR;
+       if (u132->num_ports > 7) {
+               desc->bitmap[1] = (rh_b & RH_B_DR) >> 8;
+               desc->bitmap[2] = 0xff;
+       } else
+               desc->bitmap[1] = 0xff;
+       return 0;
 }
 
 static int u132_roothub_status(struct u132 *u132, __le32 *desc)
 {
-        u32 rh_status = -1;
-        int ret_status = u132_read_pcimem(u132, roothub.status, &rh_status);
-        *desc = cpu_to_le32(rh_status);
-        return ret_status;
+       u32 rh_status = -1;
+       int ret_status = u132_read_pcimem(u132, roothub.status, &rh_status);
+       *desc = cpu_to_le32(rh_status);
+       return ret_status;
 }
 
 static int u132_roothub_portstatus(struct u132 *u132, __le32 *desc, u16 wIndex)
 {
-        if (wIndex == 0 || wIndex > u132->num_ports) {
-                return -EINVAL;
-        } else {
-                int port = wIndex - 1;
-                u32 rh_portstatus = -1;
-                int ret_portstatus = u132_read_pcimem(u132,
-                        roothub.portstatus[port], &rh_portstatus);
-                *desc = cpu_to_le32(rh_portstatus);
-                if (*(u16 *) (desc + 2)) {
-                        dev_info(&u132->platform_dev->dev, "Port %d Status Chan"
-                                "ge = %08X\n", port, *desc);
-                }
-                return ret_portstatus;
-        }
+       if (wIndex == 0 || wIndex > u132->num_ports) {
+               return -EINVAL;
+       } else {
+               int port = wIndex - 1;
+               u32 rh_portstatus = -1;
+               int ret_portstatus = u132_read_pcimem(u132,
+                       roothub.portstatus[port], &rh_portstatus);
+               *desc = cpu_to_le32(rh_portstatus);
+               if (*(u16 *) (desc + 2)) {
+                       dev_info(&u132->platform_dev->dev, "Port %d Status Chan"
+                               "ge = %08X\n", port, *desc);
+               }
+               return ret_portstatus;
+       }
 }
 
 
@@ -2666,381 +2651,340 @@ static int u132_roothub_portstatus(struct u132 *u132, __le32 *desc, u16 wIndex)
 #define tick_before(t1, t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0)
 static int u132_roothub_portreset(struct u132 *u132, int port_index)
 {
-        int retval;
-        u32 fmnumber;
-        u16 now;
-        u16 reset_done;
-        retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
-        if (retval)
-                return retval;
-        now = fmnumber;
-        reset_done = now + PORT_RESET_MSEC;
-        do {
-                u32 portstat;
-                do {
-                        retval = u132_read_pcimem(u132,
-                                roothub.portstatus[port_index], &portstat);
-                        if (retval)
-                                return retval;
-                        if (RH_PS_PRS & portstat) {
-                                continue;
-                        } else
-                                break;
-                } while (tick_before(now, reset_done));
-                if (RH_PS_PRS & portstat)
-                        return -ENODEV;
-                if (RH_PS_CCS & portstat) {
-                        if (RH_PS_PRSC & portstat) {
-                                retval = u132_write_pcimem(u132,
-                                        roothub.portstatus[port_index],
-                                        RH_PS_PRSC);
-                                if (retval)
-                                        return retval;
-                        }
-                } else
-                        break;        /* start the next reset,
-                                sleep till it's probably done */
-                retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
-                         RH_PS_PRS);
-                if (retval)
-                        return retval;
-                msleep(PORT_RESET_HW_MSEC);
-                retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
-                if (retval)
-                        return retval;
-                now = fmnumber;
-        } while (tick_before(now, reset_done));
-        return 0;
+       int retval;
+       u32 fmnumber;
+       u16 now;
+       u16 reset_done;
+       retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
+       if (retval)
+               return retval;
+       now = fmnumber;
+       reset_done = now + PORT_RESET_MSEC;
+       do {
+               u32 portstat;
+               do {
+                       retval = u132_read_pcimem(u132,
+                               roothub.portstatus[port_index], &portstat);
+                       if (retval)
+                               return retval;
+                       if (RH_PS_PRS & portstat)
+                               continue;
+                       else
+                               break;
+               } while (tick_before(now, reset_done));
+               if (RH_PS_PRS & portstat)
+                       return -ENODEV;
+               if (RH_PS_CCS & portstat) {
+                       if (RH_PS_PRSC & portstat) {
+                               retval = u132_write_pcimem(u132,
+                                       roothub.portstatus[port_index],
+                                       RH_PS_PRSC);
+                               if (retval)
+                                       return retval;
+                       }
+               } else
+                       break;  /* start the next reset,
+                               sleep till it's probably done */
+               retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
+                        RH_PS_PRS);
+               if (retval)
+                       return retval;
+               msleep(PORT_RESET_HW_MSEC);
+               retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
+               if (retval)
+                       return retval;
+               now = fmnumber;
+       } while (tick_before(now, reset_done));
+       return 0;
 }
 
 static int u132_roothub_setportfeature(struct u132 *u132, u16 wValue,
-        u16 wIndex)
-{
-        if (wIndex == 0 || wIndex > u132->num_ports) {
-                return -EINVAL;
-        } else {
-                int retval;
-                int port_index = wIndex - 1;
-                struct u132_port *port = &u132->port[port_index];
-                port->Status &= ~(1 << wValue);
-                switch (wValue) {
-                case USB_PORT_FEAT_SUSPEND:
-                        retval = u132_write_pcimem(u132,
-                                roothub.portstatus[port_index], RH_PS_PSS);
-                        if (retval)
-                                return retval;
-                        return 0;
-                case USB_PORT_FEAT_POWER:
-                        retval = u132_write_pcimem(u132,
-                                roothub.portstatus[port_index], RH_PS_PPS);
-                        if (retval)
-                                return retval;
-                        return 0;
-                case USB_PORT_FEAT_RESET:
-                        retval = u132_roothub_portreset(u132, port_index);
-                        if (retval)
-                                return retval;
-                        return 0;
-                default:
-                        return -EPIPE;
-                }
-        }
+       u16 wIndex)
+{
+       if (wIndex == 0 || wIndex > u132->num_ports) {
+               return -EINVAL;
+       } else {
+               int retval;
+               int port_index = wIndex - 1;
+               struct u132_port *port = &u132->port[port_index];
+               port->Status &= ~(1 << wValue);
+               switch (wValue) {
+               case USB_PORT_FEAT_SUSPEND:
+                       retval = u132_write_pcimem(u132,
+                               roothub.portstatus[port_index], RH_PS_PSS);
+                       if (retval)
+                               return retval;
+                       return 0;
+               case USB_PORT_FEAT_POWER:
+                       retval = u132_write_pcimem(u132,
+                               roothub.portstatus[port_index], RH_PS_PPS);
+                       if (retval)
+                               return retval;
+                       return 0;
+               case USB_PORT_FEAT_RESET:
+                       retval = u132_roothub_portreset(u132, port_index);
+                       if (retval)
+                               return retval;
+                       return 0;
+               default:
+                       return -EPIPE;
+               }
+       }
 }
 
 static int u132_roothub_clearportfeature(struct u132 *u132, u16 wValue,
-        u16 wIndex)
-{
-        if (wIndex == 0 || wIndex > u132->num_ports) {
-                return -EINVAL;
-        } else {
-                int port_index = wIndex - 1;
-                u32 temp;
-                int retval;
-                struct u132_port *port = &u132->port[port_index];
-                port->Status &= ~(1 << wValue);
-                switch (wValue) {
-                case USB_PORT_FEAT_ENABLE:
-                        temp = RH_PS_CCS;
-                        break;
-                case USB_PORT_FEAT_C_ENABLE:
-                        temp = RH_PS_PESC;
-                        break;
-                case USB_PORT_FEAT_SUSPEND:
-                        temp = RH_PS_POCI;
-                        if ((u132->hc_control & OHCI_CTRL_HCFS)
-                                != OHCI_USB_OPER) {
-                                dev_err(&u132->platform_dev->dev, "TODO resume_"
-                                        "root_hub\n");
-                        }
-                        break;
-                case USB_PORT_FEAT_C_SUSPEND:
-                        temp = RH_PS_PSSC;
-                        break;
-                case USB_PORT_FEAT_POWER:
-                        temp = RH_PS_LSDA;
-                        break;
-                case USB_PORT_FEAT_C_CONNECTION:
-                        temp = RH_PS_CSC;
-                        break;
-                case USB_PORT_FEAT_C_OVER_CURRENT:
-                        temp = RH_PS_OCIC;
-                        break;
-                case USB_PORT_FEAT_C_RESET:
-                        temp = RH_PS_PRSC;
-                        break;
-                default:
-                        return -EPIPE;
-                }
-                retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
-                         temp);
-                if (retval)
-                        return retval;
-                return 0;
-        }
+       u16 wIndex)
+{
+       if (wIndex == 0 || wIndex > u132->num_ports) {
+               return -EINVAL;
+       } else {
+               int port_index = wIndex - 1;
+               u32 temp;
+               int retval;
+               struct u132_port *port = &u132->port[port_index];
+               port->Status &= ~(1 << wValue);
+               switch (wValue) {
+               case USB_PORT_FEAT_ENABLE:
+                       temp = RH_PS_CCS;
+                       break;
+               case USB_PORT_FEAT_C_ENABLE:
+                       temp = RH_PS_PESC;
+                       break;
+               case USB_PORT_FEAT_SUSPEND:
+                       temp = RH_PS_POCI;
+                       if ((u132->hc_control & OHCI_CTRL_HCFS)
+                               != OHCI_USB_OPER) {
+                               dev_err(&u132->platform_dev->dev, "TODO resume_"
+                                       "root_hub\n");
+                       }
+                       break;
+               case USB_PORT_FEAT_C_SUSPEND:
+                       temp = RH_PS_PSSC;
+                       break;
+               case USB_PORT_FEAT_POWER:
+                       temp = RH_PS_LSDA;
+                       break;
+               case USB_PORT_FEAT_C_CONNECTION:
+                       temp = RH_PS_CSC;
+                       break;
+               case USB_PORT_FEAT_C_OVER_CURRENT:
+                       temp = RH_PS_OCIC;
+                       break;
+               case USB_PORT_FEAT_C_RESET:
+                       temp = RH_PS_PRSC;
+                       break;
+               default:
+                       return -EPIPE;
+               }
+               retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
+                        temp);
+               if (retval)
+                       return retval;
+               return 0;
+       }
 }
 
 
 /* the virtual root hub timer IRQ checks for hub status*/
 static int u132_hub_status_data(struct usb_hcd *hcd, char *buf)
 {
-        struct u132 *u132 = hcd_to_u132(hcd);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device hcd=%p has been remov"
-                        "ed %d\n", hcd, u132->going);
-                return -ENODEV;
-        } else if (u132->going > 0) {
-                dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
-                        "ed\n", hcd);
-                return -ESHUTDOWN;
-        } else {
-                int i, changed = 0, length = 1;
-                if (u132->flags & OHCI_QUIRK_AMD756) {
-                        if ((u132->hc_roothub_a & RH_A_NDP) > MAX_ROOT_PORTS) {
-                                dev_err(&u132->platform_dev->dev, "bogus NDP, r"
-                                        "ereads as NDP=%d\n",
-                                        u132->hc_roothub_a & RH_A_NDP);
-                                goto done;
-                        }
-                }
-                if (u132->hc_roothub_status & (RH_HS_LPSC | RH_HS_OCIC)) {
-                        buf[0] = changed = 1;
-                } else
-                        buf[0] = 0;
-                if (u132->num_ports > 7) {
-                        buf[1] = 0;
-                        length++;
-                }
-                for (i = 0; i < u132->num_ports; i++) {
-                        if (u132->hc_roothub_portstatus[i] & (RH_PS_CSC |
-                                RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC |
-                                RH_PS_PRSC)) {
-                                changed = 1;
-                                if (i < 7) {
-                                        buf[0] |= 1 << (i + 1);
-                                } else
-                                        buf[1] |= 1 << (i - 7);
-                                continue;
-                        }
-                        if (!(u132->hc_roothub_portstatus[i] & RH_PS_CCS)) {
-                                continue;
-                        }
-                        if ((u132->hc_roothub_portstatus[i] & RH_PS_PSS)) {
-                                continue;
-                        }
-                }
-              done:return changed ? length : 0;
-        }
+       struct u132 *u132 = hcd_to_u132(hcd);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device hcd=%p has been remov"
+                       "ed %d\n", hcd, u132->going);
+               return -ENODEV;
+       } else if (u132->going > 0) {
+               dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
+                       "ed\n", hcd);
+               return -ESHUTDOWN;
+       } else {
+               int i, changed = 0, length = 1;
+               if (u132->flags & OHCI_QUIRK_AMD756) {
+                       if ((u132->hc_roothub_a & RH_A_NDP) > MAX_ROOT_PORTS) {
+                               dev_err(&u132->platform_dev->dev, "bogus NDP, r"
+                                       "ereads as NDP=%d\n",
+                                       u132->hc_roothub_a & RH_A_NDP);
+                               goto done;
+                       }
+               }
+               if (u132->hc_roothub_status & (RH_HS_LPSC | RH_HS_OCIC))
+                       buf[0] = changed = 1;
+               else
+                       buf[0] = 0;
+               if (u132->num_ports > 7) {
+                       buf[1] = 0;
+                       length++;
+               }
+               for (i = 0; i < u132->num_ports; i++) {
+                       if (u132->hc_roothub_portstatus[i] & (RH_PS_CSC |
+                               RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC |
+                               RH_PS_PRSC)) {
+                               changed = 1;
+                               if (i < 7)
+                                       buf[0] |= 1 << (i + 1);
+                               else
+                                       buf[1] |= 1 << (i - 7);
+                               continue;
+                       }
+                       if (!(u132->hc_roothub_portstatus[i] & RH_PS_CCS))
+                               continue;
+
+                       if ((u132->hc_roothub_portstatus[i] & RH_PS_PSS))
+                               continue;
+               }
+done:
+               return changed ? length : 0;
+       }
 }
 
 static int u132_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
-        u16 wIndex, char *buf, u16 wLength)
-{
-        struct u132 *u132 = hcd_to_u132(hcd);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                return -ENODEV;
-        } else if (u132->going > 0) {
-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
-                return -ESHUTDOWN;
-        } else {
-                int retval = 0;
-                mutex_lock(&u132->sw_lock);
-                switch (typeReq) {
-                case ClearHubFeature:
-                        switch (wValue) {
-                        case C_HUB_OVER_CURRENT:
-                        case C_HUB_LOCAL_POWER:
-                                break;
-                        default:
-                                goto stall;
-                        }
-                        break;
-                case SetHubFeature:
-                        switch (wValue) {
-                        case C_HUB_OVER_CURRENT:
-                        case C_HUB_LOCAL_POWER:
-                                break;
-                        default:
-                                goto stall;
-                        }
-                        break;
-                case ClearPortFeature:{
-                                retval = u132_roothub_clearportfeature(u132,
-                                        wValue, wIndex);
-                                if (retval)
-                                        goto error;
-                                break;
-                        }
-                case GetHubDescriptor:{
-                                retval = u132_roothub_descriptor(u132,
-                                        (struct usb_hub_descriptor *)buf);
-                                if (retval)
-                                        goto error;
-                                break;
-                        }
-                case GetHubStatus:{
-                                retval = u132_roothub_status(u132,
-                                        (__le32 *) buf);
-                                if (retval)
-                                        goto error;
-                                break;
-                        }
-                case GetPortStatus:{
-                                retval = u132_roothub_portstatus(u132,
-                                        (__le32 *) buf, wIndex);
-                                if (retval)
-                                        goto error;
-                                break;
-                        }
-                case SetPortFeature:{
-                                retval = u132_roothub_setportfeature(u132,
-                                        wValue, wIndex);
-                                if (retval)
-                                        goto error;
-                                break;
-                        }
-                default:
-                        goto stall;
-                      error:u132_disable(u132);
-                        u132->going = 1;
-                        break;
-                      stall:retval = -EPIPE;
-                        break;
-                }
-                mutex_unlock(&u132->sw_lock);
-                return retval;
-        }
+       u16 wIndex, char *buf, u16 wLength)
+{
+       struct u132 *u132 = hcd_to_u132(hcd);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               return -ENODEV;
+       } else if (u132->going > 0) {
+               dev_err(&u132->platform_dev->dev, "device is being removed\n");
+               return -ESHUTDOWN;
+       } else {
+               int retval = 0;
+               mutex_lock(&u132->sw_lock);
+               switch (typeReq) {
+               case ClearHubFeature:
+                       switch (wValue) {
+                       case C_HUB_OVER_CURRENT:
+                       case C_HUB_LOCAL_POWER:
+                               break;
+                       default:
+                               goto stall;
+                       }
+                       break;
+               case SetHubFeature:
+                       switch (wValue) {
+                       case C_HUB_OVER_CURRENT:
+                       case C_HUB_LOCAL_POWER:
+                               break;
+                       default:
+                               goto stall;
+                       }
+                       break;
+               case ClearPortFeature:{
+                               retval = u132_roothub_clearportfeature(u132,
+                                       wValue, wIndex);
+                               if (retval)
+                                       goto error;
+                               break;
+                       }
+               case GetHubDescriptor:{
+                               retval = u132_roothub_descriptor(u132,
+                                       (struct usb_hub_descriptor *)buf);
+                               if (retval)
+                                       goto error;
+                               break;
+                       }
+               case GetHubStatus:{
+                               retval = u132_roothub_status(u132,
+                                       (__le32 *) buf);
+                               if (retval)
+                                       goto error;
+                               break;
+                       }
+               case GetPortStatus:{
+                               retval = u132_roothub_portstatus(u132,
+                                       (__le32 *) buf, wIndex);
+                               if (retval)
+                                       goto error;
+                               break;
+                       }
+               case SetPortFeature:{
+                               retval = u132_roothub_setportfeature(u132,
+                                       wValue, wIndex);
+                               if (retval)
+                                       goto error;
+                               break;
+                       }
+               default:
+                       goto stall;
+               error:
+                       u132_disable(u132);
+                       u132->going = 1;
+                       break;
+               stall:
+                       retval = -EPIPE;
+                       break;
+               }
+               mutex_unlock(&u132->sw_lock);
+               return retval;
+       }
 }
 
 static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num)
 {
-        struct u132 *u132 = hcd_to_u132(hcd);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                return -ENODEV;
-        } else if (u132->going > 0) {
-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
-                return -ESHUTDOWN;
-        } else
-                return 0;
-}
-
-static void u132_hub_irq_enable(struct usb_hcd *hcd)
-{
-        struct u132 *u132 = hcd_to_u132(hcd);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-        } else if (u132->going > 0)
-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+       struct u132 *u132 = hcd_to_u132(hcd);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               return -ENODEV;
+       } else if (u132->going > 0) {
+               dev_err(&u132->platform_dev->dev, "device is being removed\n");
+               return -ESHUTDOWN;
+       } else
+               return 0;
 }
 
 
 #ifdef CONFIG_PM
-static int u132_hcd_suspend(struct usb_hcd *hcd, pm_message_t message)
-{
-        struct u132 *u132 = hcd_to_u132(hcd);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                return -ENODEV;
-        } else if (u132->going > 0) {
-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
-                return -ESHUTDOWN;
-        } else
-                return 0;
-}
-
-static int u132_hcd_resume(struct usb_hcd *hcd)
-{
-        struct u132 *u132 = hcd_to_u132(hcd);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                return -ENODEV;
-        } else if (u132->going > 0) {
-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
-                return -ESHUTDOWN;
-        } else
-                return 0;
-}
-
 static int u132_bus_suspend(struct usb_hcd *hcd)
 {
-        struct u132 *u132 = hcd_to_u132(hcd);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                return -ENODEV;
-        } else if (u132->going > 0) {
-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
-                return -ESHUTDOWN;
-        } else
-                return 0;
+       struct u132 *u132 = hcd_to_u132(hcd);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               return -ENODEV;
+       } else if (u132->going > 0) {
+               dev_err(&u132->platform_dev->dev, "device is being removed\n");
+               return -ESHUTDOWN;
+       } else
+               return 0;
 }
 
 static int u132_bus_resume(struct usb_hcd *hcd)
 {
-        struct u132 *u132 = hcd_to_u132(hcd);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                return -ENODEV;
-        } else if (u132->going > 0) {
-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
-                return -ESHUTDOWN;
-        } else
-                return 0;
+       struct u132 *u132 = hcd_to_u132(hcd);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               return -ENODEV;
+       } else if (u132->going > 0) {
+               dev_err(&u132->platform_dev->dev, "device is being removed\n");
+               return -ESHUTDOWN;
+       } else
+               return 0;
 }
 
 #else
-#define u132_hcd_suspend NULL
-#define u132_hcd_resume NULL
 #define u132_bus_suspend NULL
 #define u132_bus_resume NULL
 #endif
 static struct hc_driver u132_hc_driver = {
-        .description = hcd_name,
-        .hcd_priv_size = sizeof(struct u132),
-        .irq = NULL,
-        .flags = HCD_USB11 | HCD_MEMORY,
-        .reset = u132_hcd_reset,
-        .start = u132_hcd_start,
-        .suspend = u132_hcd_suspend,
-        .resume = u132_hcd_resume,
-        .stop = u132_hcd_stop,
-        .urb_enqueue = u132_urb_enqueue,
-        .urb_dequeue = u132_urb_dequeue,
-        .endpoint_disable = u132_endpoint_disable,
-        .get_frame_number = u132_get_frame,
-        .hub_status_data = u132_hub_status_data,
-        .hub_control = u132_hub_control,
-        .bus_suspend = u132_bus_suspend,
-        .bus_resume = u132_bus_resume,
-        .start_port_reset = u132_start_port_reset,
-        .hub_irq_enable = u132_hub_irq_enable,
+       .description = hcd_name,
+       .hcd_priv_size = sizeof(struct u132),
+       .irq = NULL,
+       .flags = HCD_USB11 | HCD_MEMORY,
+       .reset = u132_hcd_reset,
+       .start = u132_hcd_start,
+       .stop = u132_hcd_stop,
+       .urb_enqueue = u132_urb_enqueue,
+       .urb_dequeue = u132_urb_dequeue,
+       .endpoint_disable = u132_endpoint_disable,
+       .get_frame_number = u132_get_frame,
+       .hub_status_data = u132_hub_status_data,
+       .hub_control = u132_hub_control,
+       .bus_suspend = u132_bus_suspend,
+       .bus_resume = u132_bus_resume,
+       .start_port_reset = u132_start_port_reset,
 };
 
 /*
@@ -3051,148 +2995,152 @@ static struct hc_driver u132_hc_driver = {
 */
 static int __devexit u132_remove(struct platform_device *pdev)
 {
-        struct usb_hcd *hcd = platform_get_drvdata(pdev);
-        if (hcd) {
-                struct u132 *u132 = hcd_to_u132(hcd);
-                if (u132->going++ > 1) {
-                        dev_err(&u132->platform_dev->dev, "already being remove"
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+       if (hcd) {
+               struct u132 *u132 = hcd_to_u132(hcd);
+               if (u132->going++ > 1) {
+                       dev_err(&u132->platform_dev->dev, "already being remove"
                                "d\n");
-                        return -ENODEV;
-                } else {
-                        int rings = MAX_U132_RINGS;
-                        int endps = MAX_U132_ENDPS;
-                        dev_err(&u132->platform_dev->dev, "removing device u132"
+                       return -ENODEV;
+               } else {
+                       int rings = MAX_U132_RINGS;
+                       int endps = MAX_U132_ENDPS;
+                       dev_err(&u132->platform_dev->dev, "removing device u132"
                                ".%d\n", u132->sequence_num);
-                        msleep(100);
-                        mutex_lock(&u132->sw_lock);
-                        u132_monitor_cancel_work(u132);
-                        while (rings-- > 0) {
-                                struct u132_ring *ring = &u132->ring[rings];
-                                u132_ring_cancel_work(u132, ring);
-                        } while (endps-- > 0) {
-                                struct u132_endp *endp = u132->endp[endps];
-                                if (endp)
-                                        u132_endp_cancel_work(u132, endp);
-                        }
-                        u132->going += 1;
-                        printk(KERN_INFO "removing device u132.%d\n",
-                                u132->sequence_num);
-                        mutex_unlock(&u132->sw_lock);
-                        usb_remove_hcd(hcd);
-                        u132_u132_put_kref(u132);
-                        return 0;
-                }
-        } else
-                return 0;
+                       msleep(100);
+                       mutex_lock(&u132->sw_lock);
+                       u132_monitor_cancel_work(u132);
+                       while (rings-- > 0) {
+                               struct u132_ring *ring = &u132->ring[rings];
+                               u132_ring_cancel_work(u132, ring);
+                       } while (endps-- > 0) {
+                               struct u132_endp *endp = u132->endp[endps];
+                               if (endp)
+                                       u132_endp_cancel_work(u132, endp);
+                       }
+                       u132->going += 1;
+                       printk(KERN_INFO "removing device u132.%d\n",
+                               u132->sequence_num);
+                       mutex_unlock(&u132->sw_lock);
+                       usb_remove_hcd(hcd);
+                       u132_u132_put_kref(u132);
+                       return 0;
+               }
+       } else
+               return 0;
 }
 
 static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
 {
-        int rings = MAX_U132_RINGS;
-        int ports = MAX_U132_PORTS;
-        int addrs = MAX_U132_ADDRS;
-        int udevs = MAX_U132_UDEVS;
-        int endps = MAX_U132_ENDPS;
-        u132->board = pdev->dev.platform_data;
-        u132->platform_dev = pdev;
-        u132->power = 0;
-        u132->reset = 0;
-        mutex_init(&u132->sw_lock);
-        init_MUTEX(&u132->scheduler_lock);
-        while (rings-- > 0) {
-                struct u132_ring *ring = &u132->ring[rings];
-                ring->u132 = u132;
-                ring->number = rings + 1;
-                ring->length = 0;
-                ring->curr_endp = NULL;
-                INIT_DELAYED_WORK(&ring->scheduler,
+       int rings = MAX_U132_RINGS;
+       int ports = MAX_U132_PORTS;
+       int addrs = MAX_U132_ADDRS;
+       int udevs = MAX_U132_UDEVS;
+       int endps = MAX_U132_ENDPS;
+       u132->board = pdev->dev.platform_data;
+       u132->platform_dev = pdev;
+       u132->power = 0;
+       u132->reset = 0;
+       mutex_init(&u132->sw_lock);
+       mutex_init(&u132->scheduler_lock);
+       while (rings-- > 0) {
+               struct u132_ring *ring = &u132->ring[rings];
+               ring->u132 = u132;
+               ring->number = rings + 1;
+               ring->length = 0;
+               ring->curr_endp = NULL;
+               INIT_DELAYED_WORK(&ring->scheduler,
                                  u132_hcd_ring_work_scheduler);
-        } mutex_lock(&u132->sw_lock);
-        INIT_DELAYED_WORK(&u132->monitor, u132_hcd_monitor_work);
-        while (ports-- > 0) {
-                struct u132_port *port = &u132->port[ports];
-                port->u132 = u132;
-                port->reset = 0;
-                port->enable = 0;
-                port->power = 0;
-                port->Status = 0;
-        } while (addrs-- > 0) {
-                struct u132_addr *addr = &u132->addr[addrs];
-                addr->address = 0;
-        } while (udevs-- > 0) {
-                struct u132_udev *udev = &u132->udev[udevs];
-                int i = ARRAY_SIZE(udev->endp_number_in);
-                int o = ARRAY_SIZE(udev->endp_number_out);
-                udev->usb_device = NULL;
-                udev->udev_number = 0;
-                udev->usb_addr = 0;
-                udev->portnumber = 0;
-                while (i-- > 0) {
-                        udev->endp_number_in[i] = 0;
-                }
-                while (o-- > 0) {
-                        udev->endp_number_out[o] = 0;
-                }
-        }
-        while (endps-- > 0) {
-                u132->endp[endps] = NULL;
-        }
-        mutex_unlock(&u132->sw_lock);
-        return;
+       }
+       mutex_lock(&u132->sw_lock);
+       INIT_DELAYED_WORK(&u132->monitor, u132_hcd_monitor_work);
+       while (ports-- > 0) {
+               struct u132_port *port = &u132->port[ports];
+               port->u132 = u132;
+               port->reset = 0;
+               port->enable = 0;
+               port->power = 0;
+               port->Status = 0;
+       }
+       while (addrs-- > 0) {
+               struct u132_addr *addr = &u132->addr[addrs];
+               addr->address = 0;
+       }
+       while (udevs-- > 0) {
+               struct u132_udev *udev = &u132->udev[udevs];
+               int i = ARRAY_SIZE(udev->endp_number_in);
+               int o = ARRAY_SIZE(udev->endp_number_out);
+               udev->usb_device = NULL;
+               udev->udev_number = 0;
+               udev->usb_addr = 0;
+               udev->portnumber = 0;
+               while (i-- > 0)
+                       udev->endp_number_in[i] = 0;
+
+               while (o-- > 0)
+                       udev->endp_number_out[o] = 0;
+
+       }
+       while (endps-- > 0)
+               u132->endp[endps] = NULL;
+
+       mutex_unlock(&u132->sw_lock);
+       return;
 }
 
 static int __devinit u132_probe(struct platform_device *pdev)
 {
-        struct usb_hcd *hcd;
-        int retval;
-        u32 control;
-        u32 rh_a = -1;
-        u32 num_ports;
-        msleep(100);
-        if (u132_exiting > 0) {
-                return -ENODEV;
-        }
-        retval = ftdi_write_pcimem(pdev, intrdisable, OHCI_INTR_MIE);
-        if (retval)
-                return retval;
-        retval = ftdi_read_pcimem(pdev, control, &control);
-        if (retval)
-                return retval;
-        retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a);
-        if (retval)
-                return retval;
-        num_ports = rh_a & RH_A_NDP;        /* refuse to confuse usbcore */
-        if (pdev->dev.dma_mask) {
-                return -EINVAL;
-        }
-        hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, pdev->dev.bus_id);
-        if (!hcd) {
-                printk(KERN_ERR "failed to create the usb hcd struct for U132\n"
-                        );
-                ftdi_elan_gone_away(pdev);
-                return -ENOMEM;
-        } else {
-                int retval = 0;
-                struct u132 *u132 = hcd_to_u132(hcd);
-                hcd->rsrc_start = 0;
-                mutex_lock(&u132_module_lock);
-                list_add_tail(&u132->u132_list, &u132_static_list);
-                u132->sequence_num = ++u132_instances;
-                mutex_unlock(&u132_module_lock);
-                u132_u132_init_kref(u132);
-                u132_initialise(u132, pdev);
-                hcd->product_desc = "ELAN U132 Host Controller";
-                retval = usb_add_hcd(hcd, 0, 0);
-                if (retval != 0) {
-                        dev_err(&u132->platform_dev->dev, "init error %d\n",
-                                retval);
-                        u132_u132_put_kref(u132);
-                        return retval;
-                } else {
-                        u132_monitor_queue_work(u132, 100);
-                        return 0;
-                }
-        }
+       struct usb_hcd *hcd;
+       int retval;
+       u32 control;
+       u32 rh_a = -1;
+       u32 num_ports;
+
+       msleep(100);
+       if (u132_exiting > 0)
+               return -ENODEV;
+
+       retval = ftdi_write_pcimem(pdev, intrdisable, OHCI_INTR_MIE);
+       if (retval)
+               return retval;
+       retval = ftdi_read_pcimem(pdev, control, &control);
+       if (retval)
+               return retval;
+       retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a);
+       if (retval)
+               return retval;
+       num_ports = rh_a & RH_A_NDP;    /* refuse to confuse usbcore */
+       if (pdev->dev.dma_mask)
+               return -EINVAL;
+
+       hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, pdev->dev.bus_id);
+       if (!hcd) {
+               printk(KERN_ERR "failed to create the usb hcd struct for U132\n"
+                       );
+               ftdi_elan_gone_away(pdev);
+               return -ENOMEM;
+       } else {
+               int retval = 0;
+               struct u132 *u132 = hcd_to_u132(hcd);
+               hcd->rsrc_start = 0;
+               mutex_lock(&u132_module_lock);
+               list_add_tail(&u132->u132_list, &u132_static_list);
+               u132->sequence_num = ++u132_instances;
+               mutex_unlock(&u132_module_lock);
+               u132_u132_init_kref(u132);
+               u132_initialise(u132, pdev);
+               hcd->product_desc = "ELAN U132 Host Controller";
+               retval = usb_add_hcd(hcd, 0, 0);
+               if (retval != 0) {
+                       dev_err(&u132->platform_dev->dev, "init error %d\n",
+                               retval);
+                       u132_u132_put_kref(u132);
+                       return retval;
+               } else {
+                       u132_monitor_queue_work(u132, 100);
+                       return 0;
+               }
+       }
 }
 
 
@@ -3203,61 +3151,58 @@ static int __devinit u132_probe(struct platform_device *pdev)
 */
 static int u132_suspend(struct platform_device *pdev, pm_message_t state)
 {
-        struct usb_hcd *hcd = platform_get_drvdata(pdev);
-        struct u132 *u132 = hcd_to_u132(hcd);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                return -ENODEV;
-        } else if (u132->going > 0) {
-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
-                return -ESHUTDOWN;
-        } else {
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+       struct u132 *u132 = hcd_to_u132(hcd);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               return -ENODEV;
+       } else if (u132->going > 0) {
+               dev_err(&u132->platform_dev->dev, "device is being removed\n");
+               return -ESHUTDOWN;
+       } else {
                int retval = 0, ports;
 
                switch (state.event) {
                case PM_EVENT_FREEZE:
-                        retval = u132_bus_suspend(hcd);
+                       retval = u132_bus_suspend(hcd);
                        break;
                case PM_EVENT_SUSPEND:
                case PM_EVENT_HIBERNATE:
                        ports = MAX_U132_PORTS;
-                        while (ports-- > 0) {
-                                port_power(u132, ports, 0);
-                        }
+                       while (ports-- > 0) {
+                               port_power(u132, ports, 0);
+                       }
                        break;
                }
-                if (retval == 0)
-                        pdev->dev.power.power_state = state;
-                return retval;
-        }
+               return retval;
+       }
 }
 
 static int u132_resume(struct platform_device *pdev)
 {
-        struct usb_hcd *hcd = platform_get_drvdata(pdev);
-        struct u132 *u132 = hcd_to_u132(hcd);
-        if (u132->going > 1) {
-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-                        , u132->going);
-                return -ENODEV;
-        } else if (u132->going > 0) {
-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
-                return -ESHUTDOWN;
-        } else {
-                int retval = 0;
-                if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
-                        int ports = MAX_U132_PORTS;
-                        while (ports-- > 0) {
-                                port_power(u132, ports, 1);
-                        }
-                        retval = 0;
-                } else {
-                        pdev->dev.power.power_state = PMSG_ON;
-                        retval = u132_bus_resume(hcd);
-                }
-                return retval;
-        }
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+       struct u132 *u132 = hcd_to_u132(hcd);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+               return -ENODEV;
+       } else if (u132->going > 0) {
+               dev_err(&u132->platform_dev->dev, "device is being removed\n");
+               return -ESHUTDOWN;
+       } else {
+               int retval = 0;
+               if (!u132->port[0].power) {
+                       int ports = MAX_U132_PORTS;
+                       while (ports-- > 0) {
+                               port_power(u132, ports, 1);
+                       }
+                       retval = 0;
+               } else {
+                       retval = u132_bus_resume(hcd);
+               }
+               return retval;
+       }
 }
 
 #else
@@ -3270,47 +3215,48 @@ static int u132_resume(struct platform_device *pdev)
 * the platform_driver struct is static because it is per type of module
 */
 static struct platform_driver u132_platform_driver = {
-        .probe = u132_probe,
-        .remove = __devexit_p(u132_remove),
-        .suspend = u132_suspend,
-        .resume = u132_resume,
-        .driver = {
-                   .name = (char *)hcd_name,
-                   .owner = THIS_MODULE,
-                   },
+       .probe = u132_probe,
+       .remove = __devexit_p(u132_remove),
+       .suspend = u132_suspend,
+       .resume = u132_resume,
+       .driver = {
+                  .name = (char *)hcd_name,
+                  .owner = THIS_MODULE,
+                  },
 };
 static int __init u132_hcd_init(void)
 {
-        int retval;
-        INIT_LIST_HEAD(&u132_static_list);
-        u132_instances = 0;
-        u132_exiting = 0;
-        mutex_init(&u132_module_lock);
-        if (usb_disabled())
-                return -ENODEV;
-        printk(KERN_INFO "driver %s built at %s on %s\n", hcd_name, __TIME__,
-                __DATE__);
-        workqueue = create_singlethread_workqueue("u132");
-        retval = platform_driver_register(&u132_platform_driver);
-        return retval;
+       int retval;
+       INIT_LIST_HEAD(&u132_static_list);
+       u132_instances = 0;
+       u132_exiting = 0;
+       mutex_init(&u132_module_lock);
+       if (usb_disabled())
+               return -ENODEV;
+       printk(KERN_INFO "driver %s built at %s on %s\n", hcd_name, __TIME__,
+               __DATE__);
+       workqueue = create_singlethread_workqueue("u132");
+       retval = platform_driver_register(&u132_platform_driver);
+       return retval;
 }
 
 
 module_init(u132_hcd_init);
 static void __exit u132_hcd_exit(void)
 {
-        struct u132 *u132;
-        struct u132 *temp;
-        mutex_lock(&u132_module_lock);
-        u132_exiting += 1;
-        mutex_unlock(&u132_module_lock);
-        list_for_each_entry_safe(u132, temp, &u132_static_list, u132_list) {
-                platform_device_unregister(u132->platform_dev);
-        } platform_driver_unregister(&u132_platform_driver);
-        printk(KERN_INFO "u132-hcd driver deregistered\n");
-        wait_event(u132_hcd_wait, u132_instances == 0);
-        flush_workqueue(workqueue);
-        destroy_workqueue(workqueue);
+       struct u132 *u132;
+       struct u132 *temp;
+       mutex_lock(&u132_module_lock);
+       u132_exiting += 1;
+       mutex_unlock(&u132_module_lock);
+       list_for_each_entry_safe(u132, temp, &u132_static_list, u132_list) {
+               platform_device_unregister(u132->platform_dev);
+       }
+       platform_driver_unregister(&u132_platform_driver);
+       printk(KERN_INFO "u132-hcd driver deregistered\n");
+       wait_event(u132_hcd_wait, u132_instances == 0);
+       flush_workqueue(workqueue);
+       destroy_workqueue(workqueue);
 }
 
 
index ec987897b8ededd485ac67a0a877a144cb24b39c..d3e0d8aa398078f7c5c15313f19f656202dcafaa 100644 (file)
@@ -262,20 +262,12 @@ __acquires(uhci->lock)
 {
        int auto_stop;
        int int_enable, egsm_enable;
+       struct usb_device *rhdev = uhci_to_hcd(uhci)->self.root_hub;
 
        auto_stop = (new_state == UHCI_RH_AUTO_STOPPED);
-       dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev,
-                       "%s%s\n", __FUNCTION__,
+       dev_dbg(&rhdev->dev, "%s%s\n", __func__,
                        (auto_stop ? " (auto-stop)" : ""));
 
-       /* If we get a suspend request when we're already auto-stopped
-        * then there's nothing to do.
-        */
-       if (uhci->rh_state == UHCI_RH_AUTO_STOPPED) {
-               uhci->rh_state = new_state;
-               return;
-       }
-
        /* Enable resume-detect interrupts if they work.
         * Then enter Global Suspend mode if _it_ works, still configured.
         */
@@ -285,8 +277,10 @@ __acquires(uhci->lock)
        if (remote_wakeup_is_broken(uhci))
                egsm_enable = 0;
        if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable ||
-                       !device_may_wakeup(
-                               &uhci_to_hcd(uhci)->self.root_hub->dev))
+#ifdef CONFIG_PM
+                       (!auto_stop && !rhdev->do_remote_wakeup) ||
+#endif
+                       (auto_stop && !device_may_wakeup(&rhdev->dev)))
                uhci->working_RD = int_enable = 0;
 
        outw(int_enable, uhci->io_addr + USBINTR);
@@ -308,8 +302,7 @@ __acquires(uhci->lock)
                        return;
        }
        if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))
-               dev_warn(&uhci_to_hcd(uhci)->self.root_hub->dev,
-                       "Controller not stopped yet!\n");
+               dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n");
 
        uhci_get_current_frame_number(uhci);
 
@@ -342,7 +335,7 @@ __releases(uhci->lock)
 __acquires(uhci->lock)
 {
        dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev,
-                       "%s%s\n", __FUNCTION__,
+                       "%s%s\n", __func__,
                        uhci->rh_state == UHCI_RH_AUTO_STOPPED ?
                                " (auto-start)" : "");
 
@@ -737,12 +730,12 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
        return rc;
 }
 
-static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
+static int uhci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
        int rc = 0;
 
-       dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
+       dev_dbg(uhci_dev(uhci), "%s\n", __func__);
 
        spin_lock_irq(&uhci->lock);
        if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
@@ -774,11 +767,11 @@ done:
        return rc;
 }
 
-static int uhci_resume(struct usb_hcd *hcd)
+static int uhci_pci_resume(struct usb_hcd *hcd)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
-       dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
+       dev_dbg(uhci_dev(uhci), "%s\n", __func__);
 
        /* Since we aren't in D3 any more, it's safe to set this flag
         * even if the controller was dead.
@@ -872,8 +865,8 @@ static const struct hc_driver uhci_driver = {
        .reset =                uhci_init,
        .start =                uhci_start,
 #ifdef CONFIG_PM
-       .suspend =              uhci_suspend,
-       .resume =               uhci_resume,
+       .pci_suspend =          uhci_pci_suspend,
+       .pci_resume =           uhci_pci_resume,
        .bus_suspend =          uhci_rh_suspend,
        .bus_resume =           uhci_rh_resume,
 #endif
index 60379b17bbc144a910a47b5021549f03cacc77f6..db645936eedd3b5f8f5aff71a9eee85a12223757 100644 (file)
@@ -1171,7 +1171,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
                                /* Some debugging code */
                                dev_dbg(&urb->dev->dev,
                                                "%s: failed with status %x\n",
-                                               __FUNCTION__, status);
+                                               __func__, status);
 
                                if (debug > 1 && errbuf) {
                                        /* Print the chain for debugging */
index 7595dfb38e3b18361f82ffbc914e300e34c76245..33350f9dd34f302f86d916a40a0cb627c636bf1b 100644 (file)
@@ -5,8 +5,8 @@ comment "USB Imaging devices"
        depends on USB
 
 config USB_MDC800
-       tristate "USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)"
-       depends on USB && EXPERIMENTAL
+       tristate "USB Mustek MDC800 Digital Camera support"
+       depends on USB
        ---help---
          Say Y here if you want to connect this type of still camera to
          your computer's USB port. This driver can be used with gphoto 0.4.3
index bc207e3c21f51f193bd6de504b8add1761670cd8..885867a86de81b6948b1e7671e059903047b535e 100644 (file)
@@ -185,7 +185,7 @@ static struct usb_driver mts_usb_driver = {
        printk( KERN_DEBUG MTS_NAME x )
 
 #define MTS_DEBUG_GOT_HERE() \
-       MTS_DEBUG("got to %s:%d (%s)\n", __FILE__, (int)__LINE__, __PRETTY_FUNCTION__ )
+       MTS_DEBUG("got to %s:%d (%s)\n", __FILE__, (int)__LINE__, __func__ )
 #define MTS_DEBUG_INT() \
        do { MTS_DEBUG_GOT_HERE(); \
             MTS_DEBUG("transfer = 0x%x context = 0x%x\n",(int)transfer,(int)context ); \
@@ -794,7 +794,6 @@ static int mts_usb_probe(struct usb_interface *intf,
 
        new_desc->usb_dev = dev;
        new_desc->usb_intf = intf;
-       init_MUTEX(&new_desc->lock);
 
        /* endpoints */
        new_desc->ep_out = ep_out;
index d5d62a93905885900ed64ca6596da41f55ea5942..ccce318f20a0af4496691f0792f839bf33762ee3 100644 (file)
@@ -39,7 +39,6 @@ struct mts_desc {
        u8 ep_image;
 
        struct Scsi_Host * host;
-       struct semaphore lock;
 
        struct urb *urb;
        struct mts_transfer_context context;
index 9c7eb6144d02d3f8852a3c1abdb6a79a2f8a690a..a53db1d4e07adefd539c9ac0d3bde8f5b4e586da 100644 (file)
@@ -33,8 +33,8 @@ config USB_EMI26
          module will be called emi26.
 
 config USB_ADUTUX
-       tristate "ADU devices from Ontrak Control Systems (EXPERIMENTAL)"
-       depends on USB && EXPERIMENTAL
+       tristate "ADU devices from Ontrak Control Systems"
+       depends on USB
        help
          Say Y if you want to use an ADU device from Ontrak Control
          Systems.
@@ -43,8 +43,8 @@ config USB_ADUTUX
          will be called adutux.
 
 config USB_AUERSWALD
-       tristate "USB Auerswald ISDN support (EXPERIMENTAL)"
-       depends on USB && EXPERIMENTAL
+       tristate "USB Auerswald ISDN support"
+       depends on USB
        help
          Say Y here if you want to connect an Auerswald USB ISDN Device
          to your computer's USB port.
@@ -53,8 +53,8 @@ config USB_AUERSWALD
          module will be called auerswald.
 
 config USB_RIO500
-       tristate "USB Diamond Rio500 support (EXPERIMENTAL)"
-       depends on USB && EXPERIMENTAL
+       tristate "USB Diamond Rio500 support"
+       depends on USB
        help
          Say Y here if you want to connect a USB Rio500 mp3 player to your
          computer's USB port. Please read <file:Documentation/usb/rio.txt>
@@ -64,8 +64,8 @@ config USB_RIO500
          module will be called rio500.
 
 config USB_LEGOTOWER
-       tristate "USB Lego Infrared Tower support (EXPERIMENTAL)"
-       depends on USB && EXPERIMENTAL
+       tristate "USB Lego Infrared Tower support"
+       depends on USB
        help
          Say Y here if you want to connect a USB Lego Infrared Tower to your
          computer's USB port.
@@ -259,8 +259,8 @@ config USB_IOWARRIOR
          module will be called iowarrior.
 
 config USB_TEST
-       tristate "USB testing driver (DEVELOPMENT)"
-       depends on USB && USB_DEVICEFS && EXPERIMENTAL
+       tristate "USB testing driver"
+       depends on USB && USB_DEVICEFS
        help
          This driver is for testing host controller software.  It is used
          with specialized device firmware for regression and stress testing,
index 5a2c44e4c1f774a3122db6c02a88274ae1d60f5a..965f6eaea6a0ace3ddb1014fa687ab6850cb3dd0 100644 (file)
@@ -147,10 +147,10 @@ static void adu_abort_transfers(struct adu_device *dev)
 {
        unsigned long flags;
 
-       dbg(2," %s : enter", __FUNCTION__);
+       dbg(2," %s : enter", __func__);
 
        if (dev->udev == NULL) {
-               dbg(1," %s : udev is null", __FUNCTION__);
+               dbg(1," %s : udev is null", __func__);
                goto exit;
        }
 
@@ -172,12 +172,12 @@ static void adu_abort_transfers(struct adu_device *dev)
                spin_unlock_irqrestore(&dev->buflock, flags);
 
 exit:
-       dbg(2," %s : leave", __FUNCTION__);
+       dbg(2," %s : leave", __func__);
 }
 
 static void adu_delete(struct adu_device *dev)
 {
-       dbg(2, "%s enter", __FUNCTION__);
+       dbg(2, "%s enter", __func__);
 
        /* free data structures */
        usb_free_urb(dev->interrupt_in_urb);
@@ -188,7 +188,7 @@ static void adu_delete(struct adu_device *dev)
        kfree(dev->interrupt_out_buffer);
        kfree(dev);
 
-       dbg(2, "%s : leave", __FUNCTION__);
+       dbg(2, "%s : leave", __func__);
 }
 
 static void adu_interrupt_in_callback(struct urb *urb)
@@ -196,8 +196,8 @@ static void adu_interrupt_in_callback(struct urb *urb)
        struct adu_device *dev = urb->context;
        int status = urb->status;
 
-       dbg(4," %s : enter, status %d", __FUNCTION__, status);
-       adu_debug_data(5, __FUNCTION__, urb->actual_length,
+       dbg(4," %s : enter, status %d", __func__, status);
+       adu_debug_data(5, __func__, urb->actual_length,
                       urb->transfer_buffer);
 
        spin_lock(&dev->buflock);
@@ -206,7 +206,7 @@ static void adu_interrupt_in_callback(struct urb *urb)
                if ((status != -ENOENT) && (status != -ECONNRESET) &&
                        (status != -ESHUTDOWN)) {
                        dbg(1," %s : nonzero status received: %d",
-                           __FUNCTION__, status);
+                           __func__, status);
                }
                goto exit;
        }
@@ -220,10 +220,10 @@ static void adu_interrupt_in_callback(struct urb *urb)
                                dev->interrupt_in_buffer, urb->actual_length);
 
                        dev->read_buffer_length += urb->actual_length;
-                       dbg(2," %s reading  %d ", __FUNCTION__,
+                       dbg(2," %s reading  %d ", __func__,
                            urb->actual_length);
                } else {
-                       dbg(1," %s : read_buffer overflow", __FUNCTION__);
+                       dbg(1," %s : read_buffer overflow", __func__);
                }
        }
 
@@ -232,9 +232,9 @@ exit:
        spin_unlock(&dev->buflock);
        /* always wake up so we recover from errors */
        wake_up_interruptible(&dev->read_wait);
-       adu_debug_data(5, __FUNCTION__, urb->actual_length,
+       adu_debug_data(5, __func__, urb->actual_length,
                       urb->transfer_buffer);
-       dbg(4," %s : leave, status %d", __FUNCTION__, status);
+       dbg(4," %s : leave, status %d", __func__, status);
 }
 
 static void adu_interrupt_out_callback(struct urb *urb)
@@ -242,14 +242,14 @@ static void adu_interrupt_out_callback(struct urb *urb)
        struct adu_device *dev = urb->context;
        int status = urb->status;
 
-       dbg(4," %s : enter, status %d", __FUNCTION__, status);
-       adu_debug_data(5,__FUNCTION__, urb->actual_length, urb->transfer_buffer);
+       dbg(4," %s : enter, status %d", __func__, status);
+       adu_debug_data(5,__func__, urb->actual_length, urb->transfer_buffer);
 
        if (status != 0) {
                if ((status != -ENOENT) &&
                    (status != -ECONNRESET)) {
                        dbg(1, " %s :nonzero status received: %d",
-                           __FUNCTION__, status);
+                           __func__, status);
                }
                goto exit;
        }
@@ -260,9 +260,9 @@ static void adu_interrupt_out_callback(struct urb *urb)
        spin_unlock(&dev->buflock);
 exit:
 
-       adu_debug_data(5, __FUNCTION__, urb->actual_length,
+       adu_debug_data(5, __func__, urb->actual_length,
                       urb->transfer_buffer);
-       dbg(4," %s : leave, status %d", __FUNCTION__, status);
+       dbg(4," %s : leave, status %d", __func__, status);
 }
 
 static int adu_open(struct inode *inode, struct file *file)
@@ -272,19 +272,19 @@ static int adu_open(struct inode *inode, struct file *file)
        int subminor;
        int retval;
 
-       dbg(2,"%s : enter", __FUNCTION__);
+       dbg(2,"%s : enter", __func__);
 
        subminor = iminor(inode);
 
        if ((retval = mutex_lock_interruptible(&adutux_mutex))) {
-               dbg(2, "%s : mutex lock failed", __FUNCTION__);
+               dbg(2, "%s : mutex lock failed", __func__);
                goto exit_no_lock;
        }
 
        interface = usb_find_interface(&adu_driver, subminor);
        if (!interface) {
                err("%s - error, can't find device for minor %d",
-                   __FUNCTION__, subminor);
+                   __func__, subminor);
                retval = -ENODEV;
                goto exit_no_device;
        }
@@ -302,7 +302,7 @@ static int adu_open(struct inode *inode, struct file *file)
        }
 
        ++dev->open_count;
-       dbg(2,"%s : open count %d", __FUNCTION__, dev->open_count);
+       dbg(2,"%s : open count %d", __func__, dev->open_count);
 
        /* save device in the file's private structure */
        file->private_data = dev;
@@ -332,23 +332,23 @@ static int adu_open(struct inode *inode, struct file *file)
 exit_no_device:
        mutex_unlock(&adutux_mutex);
 exit_no_lock:
-       dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval);
+       dbg(2,"%s : leave, return value %d ", __func__, retval);
        return retval;
 }
 
 static void adu_release_internal(struct adu_device *dev)
 {
-       dbg(2," %s : enter", __FUNCTION__);
+       dbg(2," %s : enter", __func__);
 
        /* decrement our usage count for the device */
        --dev->open_count;
-       dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
+       dbg(2," %s : open count %d", __func__, dev->open_count);
        if (dev->open_count <= 0) {
                adu_abort_transfers(dev);
                dev->open_count = 0;
        }
 
-       dbg(2," %s : leave", __FUNCTION__);
+       dbg(2," %s : leave", __func__);
 }
 
 static int adu_release(struct inode *inode, struct file *file)
@@ -356,17 +356,17 @@ static int adu_release(struct inode *inode, struct file *file)
        struct adu_device *dev;
        int retval = 0;
 
-       dbg(2," %s : enter", __FUNCTION__);
+       dbg(2," %s : enter", __func__);
 
        if (file == NULL) {
-               dbg(1," %s : file is NULL", __FUNCTION__);
+               dbg(1," %s : file is NULL", __func__);
                retval = -ENODEV;
                goto exit;
        }
 
        dev = file->private_data;
        if (dev == NULL) {
-               dbg(1," %s : object is NULL", __FUNCTION__);
+               dbg(1," %s : object is NULL", __func__);
                retval = -ENODEV;
                goto exit;
        }
@@ -374,7 +374,7 @@ static int adu_release(struct inode *inode, struct file *file)
        mutex_lock(&adutux_mutex); /* not interruptible */
 
        if (dev->open_count <= 0) {
-               dbg(1," %s : device not opened", __FUNCTION__);
+               dbg(1," %s : device not opened", __func__);
                retval = -ENODEV;
                goto exit;
        }
@@ -388,7 +388,7 @@ static int adu_release(struct inode *inode, struct file *file)
 
 exit:
        mutex_unlock(&adutux_mutex);
-       dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
+       dbg(2," %s : leave, return value %d", __func__, retval);
        return retval;
 }
 
@@ -405,10 +405,10 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
        unsigned long flags;
        DECLARE_WAITQUEUE(wait, current);
 
-       dbg(2," %s : enter, count = %Zd, file=%p", __FUNCTION__, count, file);
+       dbg(2," %s : enter, count = %Zd, file=%p", __func__, count, file);
 
        dev = file->private_data;
-       dbg(2," %s : dev=%p", __FUNCTION__, dev);
+       dbg(2," %s : dev=%p", __func__, dev);
 
        if (mutex_lock_interruptible(&dev->mtx))
                return -ERESTARTSYS;
@@ -422,16 +422,16 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
 
        /* verify that some data was requested */
        if (count == 0) {
-               dbg(1," %s : read request of 0 bytes", __FUNCTION__);
+               dbg(1," %s : read request of 0 bytes", __func__);
                goto exit;
        }
 
        timeout = COMMAND_TIMEOUT;
-       dbg(2," %s : about to start looping", __FUNCTION__);
+       dbg(2," %s : about to start looping", __func__);
        while (bytes_to_read) {
                int data_in_secondary = dev->secondary_tail - dev->secondary_head;
                dbg(2," %s : while, data_in_secondary=%d, status=%d",
-                   __FUNCTION__, data_in_secondary,
+                   __func__, data_in_secondary,
                    dev->interrupt_in_urb->status);
 
                if (data_in_secondary) {
@@ -456,7 +456,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
                                /* we secure access to the primary */
                                char *tmp;
                                dbg(2," %s : swap, read_buffer_length = %d",
-                                   __FUNCTION__, dev->read_buffer_length);
+                                   __func__, dev->read_buffer_length);
                                tmp = dev->read_buffer_secondary;
                                dev->read_buffer_secondary = dev->read_buffer_primary;
                                dev->read_buffer_primary = tmp;
@@ -471,10 +471,10 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
                                if (!dev->read_urb_finished) {
                                        /* somebody is doing IO */
                                        spin_unlock_irqrestore(&dev->buflock, flags);
-                                       dbg(2," %s : submitted already", __FUNCTION__);
+                                       dbg(2," %s : submitted already", __func__);
                                } else {
                                        /* we must initiate input */
-                                       dbg(2," %s : initiate input", __FUNCTION__);
+                                       dbg(2," %s : initiate input", __func__);
                                        dev->read_urb_finished = 0;
                                        spin_unlock_irqrestore(&dev->buflock, flags);
 
@@ -492,7 +492,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
                                                if (retval == -ENOMEM) {
                                                        retval = bytes_read ? bytes_read : -ENOMEM;
                                                }
-                                               dbg(2," %s : submit failed", __FUNCTION__);
+                                               dbg(2," %s : submit failed", __func__);
                                                goto exit;
                                        }
                                }
@@ -511,13 +511,13 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
                                remove_wait_queue(&dev->read_wait, &wait);
 
                                if (timeout <= 0) {
-                                       dbg(2," %s : timeout", __FUNCTION__);
+                                       dbg(2," %s : timeout", __func__);
                                        retval = bytes_read ? bytes_read : -ETIMEDOUT;
                                        goto exit;
                                }
 
                                if (signal_pending(current)) {
-                                       dbg(2," %s : signal pending", __FUNCTION__);
+                                       dbg(2," %s : signal pending", __func__);
                                        retval = bytes_read ? bytes_read : -EINTR;
                                        goto exit;
                                }
@@ -550,7 +550,7 @@ exit:
        /* unlock the device */
        mutex_unlock(&dev->mtx);
 
-       dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
+       dbg(2," %s : leave, return value %d", __func__, retval);
        return retval;
 }
 
@@ -565,7 +565,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
        unsigned long flags;
        int retval;
 
-       dbg(2," %s : enter, count = %Zd", __FUNCTION__, count);
+       dbg(2," %s : enter, count = %Zd", __func__, count);
 
        dev = file->private_data;
 
@@ -582,7 +582,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
 
        /* verify that we actually have some data to write */
        if (count == 0) {
-               dbg(1," %s : write request of 0 bytes", __FUNCTION__);
+               dbg(1," %s : write request of 0 bytes", __func__);
                goto exit;
        }
 
@@ -595,13 +595,13 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
 
                        mutex_unlock(&dev->mtx);
                        if (signal_pending(current)) {
-                               dbg(1," %s : interrupted", __FUNCTION__);
+                               dbg(1," %s : interrupted", __func__);
                                set_current_state(TASK_RUNNING);
                                retval = -EINTR;
                                goto exit_onqueue;
                        }
                        if (schedule_timeout(COMMAND_TIMEOUT) == 0) {
-                               dbg(1, "%s - command timed out.", __FUNCTION__);
+                               dbg(1, "%s - command timed out.", __func__);
                                retval = -ETIMEDOUT;
                                goto exit_onqueue;
                        }
@@ -612,18 +612,18 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
                                goto exit_nolock;
                        }
 
-                       dbg(4," %s : in progress, count = %Zd", __FUNCTION__, count);
+                       dbg(4," %s : in progress, count = %Zd", __func__, count);
                } else {
                        spin_unlock_irqrestore(&dev->buflock, flags);
                        set_current_state(TASK_RUNNING);
                        remove_wait_queue(&dev->write_wait, &waita);
-                       dbg(4," %s : sending, count = %Zd", __FUNCTION__, count);
+                       dbg(4," %s : sending, count = %Zd", __func__, count);
 
                        /* write the data into interrupt_out_buffer from userspace */
                        buffer_size = le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize);
                        bytes_to_write = count > buffer_size ? buffer_size : count;
                        dbg(4," %s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd",
-                           __FUNCTION__, buffer_size, count, bytes_to_write);
+                           __func__, buffer_size, count, bytes_to_write);
 
                        if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write) != 0) {
                                retval = -EFAULT;
@@ -661,7 +661,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
 exit:
        mutex_unlock(&dev->mtx);
 exit_nolock:
-       dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
+       dbg(2," %s : leave, return value %d", __func__, retval);
        return retval;
 
 exit_onqueue:
@@ -706,7 +706,7 @@ static int adu_probe(struct usb_interface *interface,
        int out_end_size;
        int i;
 
-       dbg(2," %s : enter", __FUNCTION__);
+       dbg(2," %s : enter", __func__);
 
        if (udev == NULL) {
                dev_err(&interface->dev, "udev is NULL.\n");
@@ -807,7 +807,7 @@ static int adu_probe(struct usb_interface *interface,
                dev_err(&interface->dev, "Could not retrieve serial number\n");
                goto error;
        }
-       dbg(2," %s : serial_number=%s", __FUNCTION__, dev->serial_number);
+       dbg(2," %s : serial_number=%s", __func__, dev->serial_number);
 
        /* we can register the device now, as it is ready */
        usb_set_intfdata(interface, dev);
@@ -828,7 +828,7 @@ static int adu_probe(struct usb_interface *interface,
                 udev->descriptor.idProduct, dev->serial_number,
                 (dev->minor - ADU_MINOR_BASE));
 exit:
-       dbg(2," %s : leave, return value %p (dev)", __FUNCTION__, dev);
+       dbg(2," %s : leave, return value %p (dev)", __func__, dev);
 
        return retval;
 
@@ -847,7 +847,7 @@ static void adu_disconnect(struct usb_interface *interface)
        struct adu_device *dev;
        int minor;
 
-       dbg(2," %s : enter", __FUNCTION__);
+       dbg(2," %s : enter", __func__);
 
        dev = usb_get_intfdata(interface);
 
@@ -861,7 +861,7 @@ static void adu_disconnect(struct usb_interface *interface)
        usb_set_intfdata(interface, NULL);
 
        /* if the device is not opened, then we clean up right now */
-       dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
+       dbg(2," %s : open count %d", __func__, dev->open_count);
        if (!dev->open_count)
                adu_delete(dev);
 
@@ -870,7 +870,7 @@ static void adu_disconnect(struct usb_interface *interface)
        dev_info(&interface->dev, "ADU device adutux%d now disconnected\n",
                 (minor - ADU_MINOR_BASE));
 
-       dbg(2," %s : leave", __FUNCTION__);
+       dbg(2," %s : leave", __func__);
 }
 
 /* usb specific object needed to register this driver with the usb subsystem */
@@ -885,7 +885,7 @@ static int __init adu_init(void)
 {
        int result;
 
-       dbg(2," %s : enter", __FUNCTION__);
+       dbg(2," %s : enter", __func__);
 
        /* register this driver with the USB subsystem */
        result = usb_register(&adu_driver);
@@ -899,17 +899,17 @@ static int __init adu_init(void)
        info("adutux is an experimental driver. Use at your own risk");
 
 exit:
-       dbg(2," %s : leave, return value %d", __FUNCTION__, result);
+       dbg(2," %s : leave, return value %d", __func__, result);
 
        return result;
 }
 
 static void __exit adu_exit(void)
 {
-       dbg(2," %s : enter", __FUNCTION__);
+       dbg(2," %s : enter", __func__);
        /* deregister this driver with the USB subsystem */
        usb_deregister(&adu_driver);
-       dbg(2," %s : leave", __FUNCTION__);
+       dbg(2," %s : leave", __func__);
 }
 
 module_init(adu_init);
index a5e4c3545c72a4194921cc3f1ec138b1dc5b465f..a076c24a312a53faa30af12e362128ac70fee2eb 100644 (file)
@@ -103,11 +103,11 @@ static void appledisplay_complete(struct urb *urb)
        case -ESHUTDOWN:
                /* This urb is terminated, clean up */
                dbg("%s - urb shuttingdown with status: %d",
-                       __FUNCTION__, status);
+                       __func__, status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d",
-                       __FUNCTION__, status);
+                       __func__, status);
                goto exit;
        }
 
@@ -131,7 +131,7 @@ exit:
        retval = usb_submit_urb(pdata->urb, GFP_ATOMIC);
        if (retval) {
                err("%s - usb_submit_urb failed with result %d",
-                       __FUNCTION__, retval);
+                       __func__, retval);
        }
 }
 
index df7e1ecc810a18acf4f41d8e6d11746fc88873b5..093938697426c3d2209b73754fa4341b519d672f 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/init.h>
 #include <linux/wait.h>
 #include <linux/usb.h>
+#include <linux/mutex.h>
 
 /*-------------------------------------------------------------------*/
 /* Debug support                                                    */
@@ -232,7 +233,7 @@ typedef struct auerscon
 /* USB device context */
 typedef struct
 {
-       struct semaphore        mutex;              /* protection in user context */
+       struct mutex    mutex;              /* protection in user context */
        char                    name[20];           /* name of the /dev/usb entry */
        unsigned int            dtindex;            /* index in the device table */
        struct usb_device *     usbdev;             /* USB device handle */
@@ -253,12 +254,12 @@ typedef struct
 /* character device context */
 typedef struct
 {
-       struct semaphore mutex;         /* protection in user context */
+       struct mutex mutex;             /* protection in user context */
        pauerswald_t auerdev;           /* context pointer of assigned device */
         auerbufctl_t bufctl;            /* controls the buffer chain */
         auerscon_t scontext;            /* service context */
        wait_queue_head_t readwait;     /* for synchronous reading */
-       struct semaphore readmutex;     /* protection against multiple reads */
+       struct mutex readmutex;         /* protection against multiple reads */
        pauerbuf_t readbuf;             /* buffer held for partial reading */
        unsigned int readoffset;        /* current offset in readbuf */
        unsigned int removed;           /* is != 0 if device is removed */
@@ -283,7 +284,7 @@ static void auerchain_complete (struct urb * urb)
         int result;
 
         /* get pointer to element and to chain */
-        pauerchainelement_t acep = (pauerchainelement_t) urb->context;
+       pauerchainelement_t acep = urb->context;
         pauerchain_t         acp = acep->chain;
 
         /* restore original entries in urb */
@@ -593,7 +594,7 @@ ac_fail:/* free the elements */
 /* completion handler for synchronous chained URBs */
 static void auerchain_blocking_completion (struct urb *urb)
 {
-       pauerchain_chs_t pchs = (pauerchain_chs_t)urb->context;
+       pauerchain_chs_t pchs = urb->context;
        pchs->done = 1;
        wmb();
        wake_up (&pchs->wqh);
@@ -846,7 +847,7 @@ static int auerswald_status_retry (int status)
 /* Completion of asynchronous write block */
 static void auerchar_ctrlwrite_complete (struct urb * urb)
 {
-       pauerbuf_t bp = (pauerbuf_t) urb->context;
+       pauerbuf_t bp =  urb->context;
        pauerswald_t cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));
        dbg ("auerchar_ctrlwrite_complete called");
 
@@ -859,7 +860,7 @@ static void auerchar_ctrlwrite_complete (struct urb * urb)
 /* Completion handler for dummy retry packet */
 static void auerswald_ctrlread_wretcomplete (struct urb * urb)
 {
-        pauerbuf_t bp = (pauerbuf_t) urb->context;
+       pauerbuf_t bp = urb->context;
         pauerswald_t cp;
        int ret;
        int status = urb->status;
@@ -903,7 +904,7 @@ static void auerswald_ctrlread_complete (struct urb * urb)
         unsigned int  serviceid;
         pauerswald_t  cp;
         pauerscon_t   scp;
-        pauerbuf_t    bp  = (pauerbuf_t) urb->context;
+       pauerbuf_t bp = urb->context;
        int status = urb->status;
        int ret;
 
@@ -980,9 +981,9 @@ static void auerswald_int_complete (struct urb * urb)
         int ret;
        int status = urb->status;
         pauerbuf_t   bp = NULL;
-        pauerswald_t cp = (pauerswald_t) urb->context;
+       pauerswald_t cp = urb->context;
 
-        dbg ("%s called", __FUNCTION__);
+        dbg ("%s called", __func__);
 
        switch (status) {
        case 0:
@@ -992,10 +993,10 @@ static void auerswald_int_complete (struct urb * urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, status);
+               dbg("%s - urb shutting down with status: %d", __func__, status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, status);
+               dbg("%s - nonzero urb status received: %d", __func__, status);
                goto exit;
        }
 
@@ -1080,7 +1081,7 @@ exit:
        ret = usb_submit_urb (urb, GFP_ATOMIC);
        if (ret)
                err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, ret);
+                    __func__, ret);
 }
 
 /* int memory deallocation
@@ -1376,7 +1377,7 @@ static int auerchar_open (struct inode *inode, struct file *file)
        if (cp == NULL) {
                return -ENODEV;
        }
-       if (down_interruptible (&cp->mutex)) {
+       if (mutex_lock_interruptible(&cp->mutex)) {
                return -ERESTARTSYS;
        }
 
@@ -1389,8 +1390,8 @@ static int auerchar_open (struct inode *inode, struct file *file)
        }
 
        /* Initialize device descriptor */
-       init_MUTEX( &ccp->mutex);
-       init_MUTEX( &ccp->readmutex);
+       mutex_init(&ccp->mutex);
+       mutex_init(&ccp->readmutex);
         auerbuf_init (&ccp->bufctl);
         ccp->scontext.id = AUH_UNASSIGNED;
         ccp->scontext.dispatch = auerchar_ctrlread_dispatch;
@@ -1405,7 +1406,7 @@ static int auerchar_open (struct inode *inode, struct file *file)
        cp->open_count++;
        ccp->auerdev = cp;
        dbg("open %s as /dev/%s", cp->dev_desc, cp->name);
-       up (&cp->mutex);
+       mutex_unlock(&cp->mutex);
 
        /* file IO stuff */
        file->f_pos = 0;
@@ -1413,7 +1414,7 @@ static int auerchar_open (struct inode *inode, struct file *file)
        return nonseekable_open(inode, file);
 
        /* Error exit */
-ofail: up (&cp->mutex);
+ofail: mutex_unlock(&cp->mutex);
        auerchar_delete (ccp);
        return ret;
 }
@@ -1432,23 +1433,23 @@ static int auerchar_ioctl (struct inode *inode, struct file *file, unsigned int
         dbg ("ioctl");
 
        /* get the mutexes */
-       if (down_interruptible (&ccp->mutex)) {
+       if (mutex_lock_interruptible(&ccp->mutex)) {
                return -ERESTARTSYS;
        }
        cp = ccp->auerdev;
        if (!cp) {
-               up (&ccp->mutex);
+               mutex_unlock(&ccp->mutex);
                 return -ENODEV;
        }
-       if (down_interruptible (&cp->mutex)) {
-               up(&ccp->mutex);
+       if (mutex_lock_interruptible(&cp->mutex)) {
+               mutex_unlock(&ccp->mutex);
                return -ERESTARTSYS;
        }
 
        /* Check for removal */
        if (!cp->usbdev) {
-               up(&cp->mutex);
-               up(&ccp->mutex);
+               mutex_unlock(&cp->mutex);
+               mutex_unlock(&ccp->mutex);
                 return -ENODEV;
        }
 
@@ -1550,8 +1551,8 @@ static int auerchar_ioctl (struct inode *inode, struct file *file, unsigned int
                break;
         }
        /* release the mutexes */
-       up(&cp->mutex);
-       up(&ccp->mutex);
+       mutex_unlock(&cp->mutex);
+       mutex_unlock(&ccp->mutex);
        return ret;
 }
 
@@ -1574,18 +1575,18 @@ static ssize_t auerchar_read (struct file *file, char __user *buf, size_t count,
                return 0;
 
        /* get the mutex */
-       if (down_interruptible (&ccp->mutex))
+       if (mutex_lock_interruptible(&ccp->mutex))
                return -ERESTARTSYS;
 
        /* Can we expect to read something? */
        if (ccp->scontext.id == AUH_UNASSIGNED) {
-               up (&ccp->mutex);
+               mutex_unlock(&ccp->mutex);
                 return -EIO;
        }
 
        /* only one reader per device allowed */
-       if (down_interruptible (&ccp->readmutex)) {
-               up (&ccp->mutex);
+       if (mutex_lock_interruptible(&ccp->readmutex)) {
+               mutex_unlock(&ccp->mutex);
                return -ERESTARTSYS;
        }
 
@@ -1602,8 +1603,8 @@ doreadbuf:
                if (count) {
                        if (copy_to_user (buf, bp->bufp+ccp->readoffset, count)) {
                                dbg ("auerswald_read: copy_to_user failed");
-                               up (&ccp->readmutex);
-                               up (&ccp->mutex);
+                               mutex_unlock(&ccp->readmutex);
+                               mutex_unlock(&ccp->mutex);
                                return -EFAULT;
                        }
                }
@@ -1617,8 +1618,8 @@ doreadbuf:
                }
                /* return with number of bytes read */
                if (count) {
-                       up (&ccp->readmutex);
-                       up (&ccp->mutex);
+                       mutex_unlock(&ccp->readmutex);
+                       mutex_unlock(&ccp->mutex);
                        return count;
                }
        }
@@ -1654,29 +1655,29 @@ doreadlist:
                 dbg ("No read buffer available, returning -EAGAIN");
                set_current_state (TASK_RUNNING);
                remove_wait_queue (&ccp->readwait, &wait);
-               up (&ccp->readmutex);
-               up (&ccp->mutex);
+               mutex_unlock(&ccp->readmutex);
+               mutex_unlock(&ccp->mutex);
                return -EAGAIN;  /* nonblocking, no data available */
         }
 
        /* yes, we should wait! */
-       up (&ccp->mutex); /* allow other operations while we wait */
+       mutex_unlock(&ccp->mutex); /* allow other operations while we wait */
        schedule();
        remove_wait_queue (&ccp->readwait, &wait);
        if (signal_pending (current)) {
                /* waked up by a signal */
-               up (&ccp->readmutex);
+               mutex_unlock(&ccp->readmutex);
                return -ERESTARTSYS;
        }
 
        /* Anything left to read? */
        if ((ccp->scontext.id == AUH_UNASSIGNED) || ccp->removed) {
-               up (&ccp->readmutex);
+               mutex_unlock(&ccp->readmutex);
                return -EIO;
        }
 
-       if (down_interruptible (&ccp->mutex)) {
-               up (&ccp->readmutex);
+       if (mutex_lock_interruptible(&ccp->mutex)) {
+               mutex_unlock(&ccp->readmutex);
                return -ERESTARTSYS;
        }
 
@@ -1707,27 +1708,27 @@ static ssize_t auerchar_write (struct file *file, const char __user *buf, size_t
 
 write_again:
        /* get the mutex */
-       if (down_interruptible (&ccp->mutex))
+       if (mutex_lock_interruptible(&ccp->mutex))
                return -ERESTARTSYS;
 
        /* Can we expect to write something? */
        if (ccp->scontext.id == AUH_UNASSIGNED) {
-               up (&ccp->mutex);
+               mutex_unlock(&ccp->mutex);
                 return -EIO;
        }
 
        cp = ccp->auerdev;
        if (!cp) {
-               up (&ccp->mutex);
+               mutex_unlock(&ccp->mutex);
                return -ERESTARTSYS;
        }
-       if (down_interruptible (&cp->mutex)) {
-               up (&ccp->mutex);
+       if (mutex_lock_interruptible(&cp->mutex)) {
+               mutex_unlock(&ccp->mutex);
                return -ERESTARTSYS;
        }
        if (!cp->usbdev) {
-               up (&cp->mutex);
-               up (&ccp->mutex);
+               mutex_unlock(&cp->mutex);
+               mutex_unlock(&ccp->mutex);
                return -EIO;
        }
        /* Prepare for sleep */
@@ -1750,8 +1751,8 @@ write_again:
 
        /* are there any buffers left? */
        if (!bp) {
-               up (&cp->mutex);
-               up (&ccp->mutex);
+               mutex_unlock(&cp->mutex);
+               mutex_unlock(&ccp->mutex);
 
                /* NONBLOCK: don't wait */
                if (file->f_flags & O_NONBLOCK) {
@@ -1783,8 +1784,8 @@ write_again:
                auerbuf_releasebuf (bp);
                /* Wake up all processes waiting for a buffer */
                wake_up (&cp->bufferwait);
-               up (&cp->mutex);
-               up (&ccp->mutex);
+               mutex_unlock(&cp->mutex);
+               mutex_unlock(&ccp->mutex);
                return -EFAULT;
        }
 
@@ -1803,18 +1804,18 @@ write_again:
                    auerchar_ctrlwrite_complete, bp);
        /* up we go */
        ret = auerchain_submit_urb (&cp->controlchain, bp->urbp);
-       up (&cp->mutex);
+       mutex_unlock(&cp->mutex);
        if (ret) {
                dbg ("auerchar_write: nonzero result of auerchain_submit_urb %d", ret);
                auerbuf_releasebuf (bp);
                /* Wake up all processes waiting for a buffer */
                wake_up (&cp->bufferwait);
-               up (&ccp->mutex);
+               mutex_unlock(&ccp->mutex);
                return -EIO;
        }
        else {
                dbg ("auerchar_write: Write OK");
-               up (&ccp->mutex);
+               mutex_unlock(&ccp->mutex);
                return len;
        }
 }
@@ -1827,24 +1828,24 @@ static int auerchar_release (struct inode *inode, struct file *file)
        pauerswald_t cp;
        dbg("release");
 
-       down(&ccp->mutex);
+       mutex_lock(&ccp->mutex);
        cp = ccp->auerdev;
        if (cp) {
-               down(&cp->mutex);
+               mutex_lock(&cp->mutex);
                /* remove an open service */
                auerswald_removeservice (cp, &ccp->scontext);
                /* detach from device */
                if ((--cp->open_count <= 0) && (cp->usbdev == NULL)) {
                        /* usb device waits for removal */
-                       up (&cp->mutex);
+                       mutex_unlock(&cp->mutex);
                        auerswald_delete (cp);
                } else {
-                       up (&cp->mutex);
+                       mutex_unlock(&cp->mutex);
                }
                cp = NULL;
                ccp->auerdev = NULL;
        }
-       up (&ccp->mutex);
+       mutex_unlock(&ccp->mutex);
        auerchar_delete (ccp);
 
        return 0;
@@ -1917,7 +1918,7 @@ static int auerswald_probe (struct usb_interface *intf,
        }
 
        /* Initialize device descriptor */
-       init_MUTEX (&cp->mutex);
+       mutex_init(&cp->mutex);
        cp->usbdev = usbdev;
        auerchain_init (&cp->controlchain);
         auerbuf_init (&cp->bufctl);
@@ -2042,7 +2043,7 @@ static void auerswald_disconnect (struct usb_interface *intf)
        /* give back our USB minor number */
        usb_deregister_dev(intf, &auerswald_class);
 
-       down (&cp->mutex);
+       mutex_lock(&cp->mutex);
        info ("device /dev/%s now disconnecting", cp->name);
 
        /* Stop the interrupt endpoint */
@@ -2057,16 +2058,18 @@ static void auerswald_disconnect (struct usb_interface *intf)
 
        if (cp->open_count == 0) {
                /* nobody is using this device. So we can clean up now */
-               up (&cp->mutex);/* up() is possible here because no other task
-                                  can open the device (see above). I don't want
-                                  to kfree() a locked mutex. */
+               mutex_unlock(&cp->mutex);
+               /* mutex_unlock() is possible here because no other task
+                  can open the device (see above). I don't want
+                  to kfree() a locked mutex. */
+
                auerswald_delete (cp);
        } else {
                /* device is used. Remove the pointer to the
                   usb device (it's not valid any more). The last
                   release() will do the clean up */
                cp->usbdev = NULL;
-               up (&cp->mutex);
+               mutex_unlock(&cp->mutex);
                /* Terminate waiting writers */
                wake_up (&cp->bufferwait);
                /* Inform all waiting readers */
index 4a09b87bdd2835b20528da8748e2ea5bb5224454..4b9dc81b845353ca7695db0ff4057250d83903bf 100644 (file)
@@ -70,8 +70,8 @@ static int emi26_writememory (struct usb_device *dev, int address, unsigned char
 static int emi26_set_reset (struct usb_device *dev, unsigned char reset_bit)
 {
        int response;
-       info("%s - %d", __FUNCTION__, reset_bit);
-       /* printk(KERN_DEBUG "%s - %d", __FUNCTION__, reset_bit); */
+       info("%s - %d", __func__, reset_bit);
+       /* printk(KERN_DEBUG "%s - %d", __func__, reset_bit); */
        response = emi26_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0);
        if (response < 0) {
                err("emi26: set_reset (%d) failed", reset_bit);
@@ -91,7 +91,7 @@ static int emi26_load_firmware (struct usb_device *dev)
 
        buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL);
        if (!buf) {
-               err( "%s - error loading firmware: error = %d", __FUNCTION__, -ENOMEM);
+               err( "%s - error loading firmware: error = %d", __func__, -ENOMEM);
                err = -ENOMEM;
                goto wraperr;
        }
@@ -99,7 +99,7 @@ static int emi26_load_firmware (struct usb_device *dev)
        /* Assert reset (stop the CPU in the EMI) */
        err = emi26_set_reset(dev,1);
        if (err < 0) {
-               err( "%s - error loading firmware: error = %d", __FUNCTION__, err);
+               err( "%s - error loading firmware: error = %d", __func__, err);
                goto wraperr;
        }
 
@@ -107,7 +107,7 @@ static int emi26_load_firmware (struct usb_device *dev)
        for (i=0; g_Loader[i].type == 0; i++) {
                err = emi26_writememory(dev, g_Loader[i].address, g_Loader[i].data, g_Loader[i].length, ANCHOR_LOAD_INTERNAL);
                if (err < 0) {
-                       err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+                       err("%s - error loading firmware: error = %d", __func__, err);
                        goto wraperr;
                }
        }
@@ -115,7 +115,7 @@ static int emi26_load_firmware (struct usb_device *dev)
        /* De-assert reset (let the CPU run) */
        err = emi26_set_reset(dev,0);
        if (err < 0) {
-               err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+               err("%s - error loading firmware: error = %d", __func__, err);
                goto wraperr;
        }
        msleep(250);    /* let device settle */
@@ -135,7 +135,7 @@ static int emi26_load_firmware (struct usb_device *dev)
                }
                err = emi26_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA);
                if (err < 0) {
-                       err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+                       err("%s - error loading firmware: error = %d", __func__, err);
                        goto wraperr;
                }
        } while (i > 0);
@@ -143,7 +143,7 @@ static int emi26_load_firmware (struct usb_device *dev)
        /* Assert reset (stop the CPU in the EMI) */
        err = emi26_set_reset(dev,1);
        if (err < 0) {
-               err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+               err("%s - error loading firmware: error = %d", __func__, err);
                goto wraperr;
        }
 
@@ -151,7 +151,7 @@ static int emi26_load_firmware (struct usb_device *dev)
        for (i=0; g_Loader[i].type == 0; i++) {
                err = emi26_writememory(dev, g_Loader[i].address, g_Loader[i].data, g_Loader[i].length, ANCHOR_LOAD_INTERNAL);
                if (err < 0) {
-                       err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+                       err("%s - error loading firmware: error = %d", __func__, err);
                        goto wraperr;
                }
        }
@@ -160,7 +160,7 @@ static int emi26_load_firmware (struct usb_device *dev)
        /* De-assert reset (let the CPU run) */
        err = emi26_set_reset(dev,0);
        if (err < 0) {
-               err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+               err("%s - error loading firmware: error = %d", __func__, err);
                goto wraperr;
        }
 
@@ -169,7 +169,7 @@ static int emi26_load_firmware (struct usb_device *dev)
                if (!INTERNAL_RAM(g_Firmware[i].address)) {
                        err = emi26_writememory(dev, g_Firmware[i].address, g_Firmware[i].data, g_Firmware[i].length, ANCHOR_LOAD_EXTERNAL);
                        if (err < 0) {
-                               err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+                               err("%s - error loading firmware: error = %d", __func__, err);
                                goto wraperr;
                        }
                }
@@ -178,7 +178,7 @@ static int emi26_load_firmware (struct usb_device *dev)
        /* Assert reset (stop the CPU in the EMI) */
        err = emi26_set_reset(dev,1);
        if (err < 0) {
-               err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+               err("%s - error loading firmware: error = %d", __func__, err);
                goto wraperr;
        }
 
@@ -186,7 +186,7 @@ static int emi26_load_firmware (struct usb_device *dev)
                if (INTERNAL_RAM(g_Firmware[i].address)) {
                        err = emi26_writememory(dev, g_Firmware[i].address, g_Firmware[i].data, g_Firmware[i].length, ANCHOR_LOAD_INTERNAL);
                        if (err < 0) {
-                               err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+                               err("%s - error loading firmware: error = %d", __func__, err);
                                goto wraperr;
                        }
                }
@@ -195,7 +195,7 @@ static int emi26_load_firmware (struct usb_device *dev)
        /* De-assert reset (let the CPU run) */
        err = emi26_set_reset(dev,0);
        if (err < 0) {
-               err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+               err("%s - error loading firmware: error = %d", __func__, err);
                goto wraperr;
        }
        msleep(250);    /* let device settle */
@@ -221,7 +221,7 @@ static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *i
 {
        struct usb_device *dev = interface_to_usbdev(intf);
 
-       info("%s start", __FUNCTION__); 
+       info("%s start", __func__);
 
        emi26_load_firmware(dev);
 
index d1362415922cfffedc6a330a08bdc83a6f2ef85c..1a2b79ac5e1071749c8ecc11f66d9687182bb27b 100644 (file)
@@ -78,7 +78,7 @@ static int emi62_writememory (struct usb_device *dev, int address, unsigned char
 static int emi62_set_reset (struct usb_device *dev, unsigned char reset_bit)
 {
        int response;
-       info("%s - %d", __FUNCTION__, reset_bit);
+       info("%s - %d", __func__, reset_bit);
        
        response = emi62_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0);
        if (response < 0) {
@@ -100,7 +100,7 @@ static int emi62_load_firmware (struct usb_device *dev)
        dev_dbg(&dev->dev, "load_firmware\n");
        buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL);
        if (!buf) {
-               err( "%s - error loading firmware: error = %d", __FUNCTION__, -ENOMEM);
+               err( "%s - error loading firmware: error = %d", __func__, -ENOMEM);
                err = -ENOMEM;
                goto wraperr;
        }
@@ -108,7 +108,7 @@ static int emi62_load_firmware (struct usb_device *dev)
        /* Assert reset (stop the CPU in the EMI) */
        err = emi62_set_reset(dev,1);
        if (err < 0) {
-               err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+               err("%s - error loading firmware: error = %d", __func__, err);
                goto wraperr;
        }
 
@@ -116,7 +116,7 @@ static int emi62_load_firmware (struct usb_device *dev)
        for (i=0; g_emi62_loader[i].type == 0; i++) {
                err = emi62_writememory(dev, g_emi62_loader[i].address, g_emi62_loader[i].data, g_emi62_loader[i].length, ANCHOR_LOAD_INTERNAL);
                if (err < 0) {
-                       err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+                       err("%s - error loading firmware: error = %d", __func__, err);
                        goto wraperr;
                }
        }
@@ -124,7 +124,7 @@ static int emi62_load_firmware (struct usb_device *dev)
        /* De-assert reset (let the CPU run) */
        err = emi62_set_reset(dev,0);
        if (err < 0) {
-               err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+               err("%s - error loading firmware: error = %d", __func__, err);
                goto wraperr;
        }
        msleep(250);    /* let device settle */
@@ -144,7 +144,7 @@ static int emi62_load_firmware (struct usb_device *dev)
                }
                err = emi62_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA);
                if (err < 0) {
-                       err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+                       err("%s - error loading firmware: error = %d", __func__, err);
                        goto wraperr;
                }
        } while (i > 0);
@@ -152,7 +152,7 @@ static int emi62_load_firmware (struct usb_device *dev)
        /* Assert reset (stop the CPU in the EMI) */
        err = emi62_set_reset(dev,1);
        if (err < 0) {
-               err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+               err("%s - error loading firmware: error = %d", __func__, err);
                goto wraperr;
        }
 
@@ -160,7 +160,7 @@ static int emi62_load_firmware (struct usb_device *dev)
        for (i=0; g_emi62_loader[i].type == 0; i++) {
                err = emi62_writememory(dev, g_emi62_loader[i].address, g_emi62_loader[i].data, g_emi62_loader[i].length, ANCHOR_LOAD_INTERNAL);
                if (err < 0) {
-                       err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+                       err("%s - error loading firmware: error = %d", __func__, err);
                        goto wraperr;
                }
        }
@@ -168,7 +168,7 @@ static int emi62_load_firmware (struct usb_device *dev)
        /* De-assert reset (let the CPU run) */
        err = emi62_set_reset(dev,0);
        if (err < 0) {
-               err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+               err("%s - error loading firmware: error = %d", __func__, err);
                goto wraperr;
        }
        msleep(250);    /* let device settle */
@@ -181,7 +181,7 @@ static int emi62_load_firmware (struct usb_device *dev)
                if (!INTERNAL_RAM(g_HexSpdifFw62[i].address)) {
                        err = emi62_writememory(dev, g_HexSpdifFw62[i].address, g_HexSpdifFw62[i].data, g_HexSpdifFw62[i].length, ANCHOR_LOAD_EXTERNAL);
                        if (err < 0) {
-                               err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+                               err("%s - error loading firmware: error = %d", __func__, err);
                                goto wraperr;
                        }
                }
@@ -191,7 +191,7 @@ static int emi62_load_firmware (struct usb_device *dev)
                if (!INTERNAL_RAM(g_HexMidiFw62[i].address)) {
                        err = emi62_writememory(dev, g_HexMidiFw62[i].address, g_HexMidiFw62[i].data, g_HexMidiFw62[i].length, ANCHOR_LOAD_EXTERNAL);
                        if (err < 0) {
-                               err("%s - error loading firmware: error = %d\n", __FUNCTION__, err);
+                               err("%s - error loading firmware: error = %d\n", __func__, err);
                                goto wraperr;
                                return err;
                        }
@@ -201,7 +201,7 @@ static int emi62_load_firmware (struct usb_device *dev)
        /* Assert reset (stop the CPU in the EMI) */
        err = emi62_set_reset(dev,1);
        if (err < 0) {
-               err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+               err("%s - error loading firmware: error = %d", __func__, err);
                goto wraperr;
        }
 
@@ -211,7 +211,7 @@ static int emi62_load_firmware (struct usb_device *dev)
                if (INTERNAL_RAM(g_HexSpdifFw62[i].address)) {
                        err = emi62_writememory(dev, g_HexSpdifFw62[i].address, g_HexSpdifFw62[i].data, g_HexSpdifFw62[i].length, ANCHOR_LOAD_INTERNAL);
                        if (err < 0) {
-                               err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+                               err("%s - error loading firmware: error = %d", __func__, err);
                                goto wraperr;
                        }
                }
@@ -221,7 +221,7 @@ static int emi62_load_firmware (struct usb_device *dev)
                if (INTERNAL_RAM(g_HexMidiFw62[i].address)) {
                        err = emi62_writememory(dev, g_HexMidiFw62[i].address, g_HexMidiFw62[i].data, g_HexMidiFw62[i].length, ANCHOR_LOAD_INTERNAL);
                        if (err < 0) {
-                               err("%s - error loading firmware: error = %d\n", __FUNCTION__, err);
+                               err("%s - error loading firmware: error = %d\n", __func__, err);
                                goto wraperr;
                        }
                }
@@ -231,7 +231,7 @@ static int emi62_load_firmware (struct usb_device *dev)
        /* De-assert reset (let the CPU run) */
        err = emi62_set_reset(dev,0);
        if (err < 0) {
-               err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+               err("%s - error loading firmware: error = %d", __func__, err);
                goto wraperr;
        }
        msleep(250);    /* let device settle */
@@ -260,7 +260,7 @@ static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *i
        struct usb_device *dev = interface_to_usbdev(intf);
        dev_dbg(&intf->dev, "emi62_probe\n");
 
-       info("%s start", __FUNCTION__); 
+       info("%s start", __func__);
 
        emi62_load_firmware(dev);
 
index 148b7fe639b2166256230acd25b66ea37e24920d..ec88b3bfee465cfa9b18633345cfd075c93355a1 100644 (file)
@@ -746,7 +746,7 @@ static ssize_t ftdi_elan_read(struct file *file, char __user *buffer,
 
 static void ftdi_elan_write_bulk_callback(struct urb *urb)
 {
-        struct usb_ftdi *ftdi = (struct usb_ftdi *)urb->context;
+       struct usb_ftdi *ftdi = urb->context;
        int status = urb->status;
 
        if (status && !(status == -ENOENT || status == -ECONNRESET ||
index 801070502cc1b14faa0bd3769247154f2935736f..1cb54a28347f0fe332363df6c3dcac7d11770573 100644 (file)
@@ -154,7 +154,7 @@ MODULE_DEVICE_TABLE(usb, iowarrior_ids);
  */
 static void iowarrior_callback(struct urb *urb)
 {
-       struct iowarrior *dev = (struct iowarrior *)urb->context;
+       struct iowarrior *dev = urb->context;
        int intr_idx;
        int read_idx;
        int aux_idx;
@@ -218,7 +218,7 @@ exit:
        retval = usb_submit_urb(urb, GFP_ATOMIC);
        if (retval)
                dev_err(&dev->interface->dev, "%s - usb_submit_urb failed with result %d\n",
-                       __FUNCTION__, retval);
+                       __func__, retval);
 
 }
 
@@ -230,7 +230,7 @@ static void iowarrior_write_callback(struct urb *urb)
        struct iowarrior *dev;
        int status = urb->status;
 
-       dev = (struct iowarrior *)urb->context;
+       dev = urb->context;
        /* sync/async unlink faults aren't errors */
        if (status &&
            !(status == -ENOENT ||
@@ -453,7 +453,7 @@ static ssize_t iowarrior_write(struct file *file,
        default:
                /* what do we have here ? An unsupported Product-ID ? */
                dev_err(&dev->interface->dev, "%s - not supported for product=0x%x\n",
-                       __FUNCTION__, dev->product_id);
+                       __func__, dev->product_id);
                retval = -EFAULT;
                goto exit;
                break;
@@ -604,7 +604,7 @@ static int iowarrior_open(struct inode *inode, struct file *file)
 
        interface = usb_find_interface(&iowarrior_driver, subminor);
        if (!interface) {
-               err("%s - error, can't find device for minor %d", __FUNCTION__,
+               err("%s - error, can't find device for minor %d", __func__,
                    subminor);
                return -ENODEV;
        }
index c730d20eec66cc6c3f4517626b74c696c4e15731..11580e81e2c633b0163214680342334105b64dc8 100644 (file)
@@ -231,7 +231,7 @@ static void ld_usb_interrupt_in_callback(struct urb *urb)
                        goto exit;
                } else {
                        dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n",
-                                __FUNCTION__, status);
+                                __func__, status);
                        spin_lock(&dev->rbsl);
                        goto resubmit; /* maybe we can recover */
                }
@@ -247,7 +247,7 @@ static void ld_usb_interrupt_in_callback(struct urb *urb)
                        memcpy(actual_buffer+1, dev->interrupt_in_buffer, urb->actual_length);
                        dev->ring_head = next_ring_head;
                        dbg_info(&dev->intf->dev, "%s: received %d bytes\n",
-                                __FUNCTION__, urb->actual_length);
+                                __func__, urb->actual_length);
                } else {
                        dev_warn(&dev->intf->dev,
                                 "Ring buffer overflow, %d bytes dropped\n",
@@ -286,7 +286,7 @@ static void ld_usb_interrupt_out_callback(struct urb *urb)
                        status == -ESHUTDOWN))
                dbg_info(&dev->intf->dev,
                         "%s - nonzero write interrupt status received: %d\n",
-                        __FUNCTION__, status);
+                        __func__, status);
 
        dev->interrupt_out_busy = 0;
        wake_up_interruptible(&dev->write_wait);
@@ -309,7 +309,7 @@ static int ld_usb_open(struct inode *inode, struct file *file)
 
        if (!interface) {
                err("%s - error, can't find device for minor %d\n",
-                    __FUNCTION__, subminor);
+                    __func__, subminor);
                return -ENODEV;
        }
 
@@ -556,7 +556,7 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
        bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size);
        if (bytes_to_write < count)
                dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n",count-bytes_to_write);
-       dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __FUNCTION__, count, bytes_to_write);
+       dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __func__, count, bytes_to_write);
 
        if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
                retval = -EFAULT;
index 6664043f4645bc0d13fa0ac51a3c6f017356cbbb..9370326a594027b92be5a84ac2b176f5e33b09f2 100644 (file)
@@ -31,7 +31,7 @@
  *   - imported into lejos project
  *   - changed wake_up to wake_up_interruptible
  *   - changed to use lego0 rather than tower0
- *   - changed dbg() to use __func__ rather than deprecated __FUNCTION__
+ *   - changed dbg() to use __func__ rather than deprecated __func__
  * 2003-01-12 - 0.53 david (david@csse.uwa.edu.au)
  *   - changed read and write to write everything or
  *     timeout (from a patch by Chris Riesen and Brett Thaeler driver)
@@ -49,7 +49,7 @@
  *   - added poll
  *   - forbid seeking
  *   - added nonblocking I/O
- *   - changed back __func__ to __FUNCTION__
+ *   - changed back __func__ to __func__
  *   - read and log tower firmware version
  *   - reset tower on probe, avoids failure of first write
  * 2004-03-09 - 0.7 Juergen Stuber <starblue@users.sourceforge.net>
@@ -309,7 +309,7 @@ static inline void lego_usb_tower_debug_data (int level, const char *function, i
  */
 static inline void tower_delete (struct lego_usb_tower *dev)
 {
-       dbg(2, "%s: enter", __FUNCTION__);
+       dbg(2, "%s: enter", __func__);
 
        tower_abort_transfers (dev);
 
@@ -321,7 +321,7 @@ static inline void tower_delete (struct lego_usb_tower *dev)
        kfree (dev->interrupt_out_buffer);
        kfree (dev);
 
-       dbg(2, "%s: leave", __FUNCTION__);
+       dbg(2, "%s: leave", __func__);
 }
 
 
@@ -337,7 +337,7 @@ static int tower_open (struct inode *inode, struct file *file)
        struct tower_reset_reply reset_reply;
        int result;
 
-       dbg(2, "%s: enter", __FUNCTION__);
+       dbg(2, "%s: enter", __func__);
 
        nonseekable_open(inode, file);
        subminor = iminor(inode);
@@ -346,7 +346,7 @@ static int tower_open (struct inode *inode, struct file *file)
 
        if (!interface) {
                err ("%s - error, can't find device for minor %d",
-                    __FUNCTION__, subminor);
+                    __func__, subminor);
                retval = -ENODEV;
                goto exit;
        }
@@ -424,7 +424,7 @@ unlock_exit:
        mutex_unlock(&dev->lock);
 
 exit:
-       dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval);
+       dbg(2, "%s: leave, return value %d ", __func__, retval);
 
        return retval;
 }
@@ -437,12 +437,12 @@ static int tower_release (struct inode *inode, struct file *file)
        struct lego_usb_tower *dev;
        int retval = 0;
 
-       dbg(2, "%s: enter", __FUNCTION__);
+       dbg(2, "%s: enter", __func__);
 
        dev = (struct lego_usb_tower *)file->private_data;
 
        if (dev == NULL) {
-               dbg(1, "%s: object is NULL", __FUNCTION__);
+               dbg(1, "%s: object is NULL", __func__);
                retval = -ENODEV;
                goto exit_nolock;
        }
@@ -454,7 +454,7 @@ static int tower_release (struct inode *inode, struct file *file)
        }
 
        if (dev->open_count != 1) {
-               dbg(1, "%s: device not opened exactly once", __FUNCTION__);
+               dbg(1, "%s: device not opened exactly once", __func__);
                retval = -ENODEV;
                goto unlock_exit;
        }
@@ -480,7 +480,7 @@ unlock_exit:
 exit:
        mutex_unlock(&open_disc_mutex);
 exit_nolock:
-       dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
+       dbg(2, "%s: leave, return value %d", __func__, retval);
        return retval;
 }
 
@@ -491,10 +491,10 @@ exit_nolock:
  */
 static void tower_abort_transfers (struct lego_usb_tower *dev)
 {
-       dbg(2, "%s: enter", __FUNCTION__);
+       dbg(2, "%s: enter", __func__);
 
        if (dev == NULL) {
-               dbg(1, "%s: dev is null", __FUNCTION__);
+               dbg(1, "%s: dev is null", __func__);
                goto exit;
        }
 
@@ -509,7 +509,7 @@ static void tower_abort_transfers (struct lego_usb_tower *dev)
                usb_kill_urb(dev->interrupt_out_urb);
 
 exit:
-       dbg(2, "%s: leave", __FUNCTION__);
+       dbg(2, "%s: leave", __func__);
 }
 
 
@@ -542,7 +542,7 @@ static unsigned int tower_poll (struct file *file, poll_table *wait)
        struct lego_usb_tower *dev;
        unsigned int mask = 0;
 
-       dbg(2, "%s: enter", __FUNCTION__);
+       dbg(2, "%s: enter", __func__);
 
        dev = file->private_data;
 
@@ -557,7 +557,7 @@ static unsigned int tower_poll (struct file *file, poll_table *wait)
                mask |= POLLOUT | POLLWRNORM;
        }
 
-       dbg(2, "%s: leave, mask = %d", __FUNCTION__, mask);
+       dbg(2, "%s: leave, mask = %d", __func__, mask);
 
        return mask;
 }
@@ -583,7 +583,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
        int retval = 0;
        unsigned long timeout = 0;
 
-       dbg(2, "%s: enter, count = %Zd", __FUNCTION__, count);
+       dbg(2, "%s: enter, count = %Zd", __func__, count);
 
        dev = (struct lego_usb_tower *)file->private_data;
 
@@ -602,7 +602,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
 
        /* verify that we actually have some data to read */
        if (count == 0) {
-               dbg(1, "%s: read request of 0 bytes", __FUNCTION__);
+               dbg(1, "%s: read request of 0 bytes", __func__);
                goto unlock_exit;
        }
 
@@ -658,7 +658,7 @@ unlock_exit:
        mutex_unlock(&dev->lock);
 
 exit:
-       dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
+       dbg(2, "%s: leave, return value %d", __func__, retval);
        return retval;
 }
 
@@ -672,7 +672,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
        size_t bytes_to_write;
        int retval = 0;
 
-       dbg(2, "%s: enter, count = %Zd", __FUNCTION__, count);
+       dbg(2, "%s: enter, count = %Zd", __func__, count);
 
        dev = (struct lego_usb_tower *)file->private_data;
 
@@ -691,7 +691,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
 
        /* verify that we actually have some data to write */
        if (count == 0) {
-               dbg(1, "%s: write request of 0 bytes", __FUNCTION__);
+               dbg(1, "%s: write request of 0 bytes", __func__);
                goto unlock_exit;
        }
 
@@ -709,7 +709,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
 
        /* write the data into interrupt_out_buffer from userspace */
        bytes_to_write = min_t(int, count, write_buffer_size);
-       dbg(4, "%s: count = %Zd, bytes_to_write = %Zd", __FUNCTION__, count, bytes_to_write);
+       dbg(4, "%s: count = %Zd, bytes_to_write = %Zd", __func__, count, bytes_to_write);
 
        if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write)) {
                retval = -EFAULT;
@@ -742,7 +742,7 @@ unlock_exit:
        mutex_unlock(&dev->lock);
 
 exit:
-       dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
+       dbg(2, "%s: leave, return value %d", __func__, retval);
 
        return retval;
 }
@@ -753,13 +753,13 @@ exit:
  */
 static void tower_interrupt_in_callback (struct urb *urb)
 {
-       struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context;
+       struct lego_usb_tower *dev = urb->context;
        int status = urb->status;
        int retval;
 
-       dbg(4, "%s: enter, status %d", __FUNCTION__, status);
+       dbg(4, "%s: enter, status %d", __func__, status);
 
-       lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
+       lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer);
 
        if (status) {
                if (status == -ENOENT ||
@@ -767,7 +767,7 @@ static void tower_interrupt_in_callback (struct urb *urb)
                    status == -ESHUTDOWN) {
                        goto exit;
                } else {
-                       dbg(1, "%s: nonzero status received: %d", __FUNCTION__, status);
+                       dbg(1, "%s: nonzero status received: %d", __func__, status);
                        goto resubmit; /* maybe we can recover */
                }
        }
@@ -780,9 +780,9 @@ static void tower_interrupt_in_callback (struct urb *urb)
                                urb->actual_length);
                        dev->read_buffer_length += urb->actual_length;
                        dev->read_last_arrival = jiffies;
-                       dbg(3, "%s: received %d bytes", __FUNCTION__, urb->actual_length);
+                       dbg(3, "%s: received %d bytes", __func__, urb->actual_length);
                } else {
-                       printk(KERN_WARNING "%s: read_buffer overflow, %d bytes dropped", __FUNCTION__, urb->actual_length);
+                       printk(KERN_WARNING "%s: read_buffer overflow, %d bytes dropped", __func__, urb->actual_length);
                }
                spin_unlock (&dev->read_buffer_lock);
        }
@@ -792,7 +792,7 @@ resubmit:
        if (dev->interrupt_in_running && dev->udev) {
                retval = usb_submit_urb (dev->interrupt_in_urb, GFP_ATOMIC);
                if (retval) {
-                       err("%s: usb_submit_urb failed (%d)", __FUNCTION__, retval);
+                       err("%s: usb_submit_urb failed (%d)", __func__, retval);
                }
        }
 
@@ -800,8 +800,8 @@ exit:
        dev->interrupt_in_done = 1;
        wake_up_interruptible (&dev->read_wait);
 
-       lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
-       dbg(4, "%s: leave, status %d", __FUNCTION__, status);
+       lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer);
+       dbg(4, "%s: leave, status %d", __func__, status);
 }
 
 
@@ -810,25 +810,25 @@ exit:
  */
 static void tower_interrupt_out_callback (struct urb *urb)
 {
-       struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context;
+       struct lego_usb_tower *dev = urb->context;
        int status = urb->status;
 
-       dbg(4, "%s: enter, status %d", __FUNCTION__, status);
-       lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
+       dbg(4, "%s: enter, status %d", __func__, status);
+       lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer);
 
        /* sync/async unlink faults aren't errors */
        if (status && !(status == -ENOENT ||
                        status == -ECONNRESET ||
                        status == -ESHUTDOWN)) {
                dbg(1, "%s - nonzero write bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
        }
 
        dev->interrupt_out_busy = 0;
        wake_up_interruptible(&dev->write_wait);
 
-       lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
-       dbg(4, "%s: leave, status %d", __FUNCTION__, status);
+       lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer);
+       dbg(4, "%s: leave, status %d", __func__, status);
 }
 
 
@@ -849,7 +849,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
        int retval = -ENOMEM;
        int result;
 
-       dbg(2, "%s: enter", __FUNCTION__);
+       dbg(2, "%s: enter", __func__);
 
        if (udev == NULL) {
                info ("udev is NULL.");
@@ -978,7 +978,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
 
 
 exit:
-       dbg(2, "%s: leave, return value 0x%.8lx (dev)", __FUNCTION__, (long) dev);
+       dbg(2, "%s: leave, return value 0x%.8lx (dev)", __func__, (long) dev);
 
        return retval;
 
@@ -998,7 +998,7 @@ static void tower_disconnect (struct usb_interface *interface)
        struct lego_usb_tower *dev;
        int minor;
 
-       dbg(2, "%s: enter", __FUNCTION__);
+       dbg(2, "%s: enter", __func__);
 
        dev = usb_get_intfdata (interface);
        mutex_lock(&open_disc_mutex);
@@ -1023,7 +1023,7 @@ static void tower_disconnect (struct usb_interface *interface)
 
        info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));
 
-       dbg(2, "%s: leave", __FUNCTION__);
+       dbg(2, "%s: leave", __func__);
 }
 
 
@@ -1036,7 +1036,7 @@ static int __init lego_usb_tower_init(void)
        int result;
        int retval = 0;
 
-       dbg(2, "%s: enter", __FUNCTION__);
+       dbg(2, "%s: enter", __func__);
 
        /* register this driver with the USB subsystem */
        result = usb_register(&tower_driver);
@@ -1049,7 +1049,7 @@ static int __init lego_usb_tower_init(void)
        info(DRIVER_DESC " " DRIVER_VERSION);
 
 exit:
-       dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
+       dbg(2, "%s: leave, return value %d", __func__, retval);
 
        return retval;
 }
@@ -1060,12 +1060,12 @@ exit:
  */
 static void __exit lego_usb_tower_exit(void)
 {
-       dbg(2, "%s: enter", __FUNCTION__);
+       dbg(2, "%s: enter", __func__);
 
        /* deregister this driver with the USB subsystem */
        usb_deregister (&tower_driver);
 
-       dbg(2, "%s: leave", __FUNCTION__);
+       dbg(2, "%s: leave", __func__);
 }
 
 module_init (lego_usb_tower_init);
index aa9bcceabe744fa213c073456f9cf5d5a6381f3a..24230c638b8e639b0c6ccef2d2bb3264a2f50116 100644 (file)
@@ -113,7 +113,7 @@ static int set_outputs(struct interfacekit *kit)
 
        buffer = kzalloc(4, GFP_KERNEL);
        if (!buffer) {
-               dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
+               dev_err(&kit->udev->dev, "%s - out of memory\n", __func__);
                return -ENOMEM;
        }
        buffer[0] = (u8)kit->outputs;
@@ -146,7 +146,7 @@ static int change_string(struct interfacekit *kit, const char *display, unsigned
        buffer = kmalloc(8, GFP_KERNEL);
        form_buffer = kmalloc(30, GFP_KERNEL);
        if ((!buffer) || (!form_buffer)) {
-               dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
+               dev_err(&kit->udev->dev, "%s - out of memory\n", __func__);
                goto exit;
        }
 
@@ -216,7 +216,7 @@ static ssize_t set_backlight(struct device *dev, struct device_attribute *attr,
        
        buffer = kzalloc(8, GFP_KERNEL);
        if (!buffer) {
-               dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
+               dev_err(&kit->udev->dev, "%s - out of memory\n", __func__);
                goto exit;
        }
 
index 2ad09b1f4848a57d9aac01f2bd46539590ec9377..f0113c17cc5afd1d0c6b01173161f57fabc5ea30 100644 (file)
@@ -61,7 +61,7 @@ static int set_motor(struct motorcontrol *mc, int motor)
 
        buffer = kzalloc(8, GFP_KERNEL);
        if (!buffer) {
-               dev_err(&mc->intf->dev, "%s - out of memory\n", __FUNCTION__);
+               dev_err(&mc->intf->dev, "%s - out of memory\n", __func__);
                return -ENOMEM;
        }
 
index 0d9de2f739301b6170635f4461f5dded1d9292dc..7d590c09434ad6e009e4a1cb4e4a1627ed97f914 100644 (file)
@@ -89,7 +89,7 @@ change_position_v30(struct phidget_servo *servo, int servo_no, int degrees,
        buffer = kmalloc(6, GFP_KERNEL);
        if (!buffer) {
                dev_err(&servo->udev->dev, "%s - out of memory\n",
-                       __FUNCTION__);
+                       __func__);
                return -ENOMEM;
        }
 
@@ -162,7 +162,7 @@ change_position_v20(struct phidget_servo *servo, int servo_no, int degrees,
        buffer = kmalloc(2, GFP_KERNEL);
        if (!buffer) {
                dev_err(&servo->udev->dev, "%s - out of memory\n",
-                       __FUNCTION__);
+                       __func__);
                return -ENOMEM;
        }
 
@@ -259,7 +259,7 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id)
 
        dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL);
        if (dev == NULL) {
-               dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__);
+               dev_err(&interface->dev, "%s - out of memory\n", __func__);
                rc = -ENOMEM;
                goto out;
        }
index 20777d01db62c4fdd705cde8307d5117e79c24e5..7f7021ee4189f4604ae971eec82dfe17a65267ce 100644 (file)
@@ -78,7 +78,7 @@ static int lcd_open(struct inode *inode, struct file *file)
        interface = usb_find_interface(&lcd_driver, subminor);
        if (!interface) {
                err ("USBLCD: %s - error, can't find device for minor %d",
-                    __FUNCTION__, subminor);
+                    __func__, subminor);
                return -ENODEV;
        }
 
@@ -185,7 +185,7 @@ static void lcd_write_bulk_callback(struct urb *urb)
        struct usb_lcd *dev;
        int status = urb->status;
 
-       dev = (struct usb_lcd *)urb->context;
+       dev = urb->context;
 
        /* sync/async unlink faults aren't errors */
        if (status &&
@@ -193,7 +193,7 @@ static void lcd_write_bulk_callback(struct urb *urb)
              status == -ECONNRESET ||
               status == -ESHUTDOWN)) {
                dbg("USBLCD: %s - nonzero write bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
        }
 
        /* free up our allocated buffer */
@@ -248,7 +248,7 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz
        /* 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);
+               err("USBLCD: %s - failed submitting write urb, error %d", __func__, retval);
                goto error_unanchor;
        }
        
index b6b5b2affad1deac8d670adea8f050593b6e8bc0..a51983854ca0625da79cbf97daa98b75090b4199 100644 (file)
@@ -201,7 +201,7 @@ found:
 
 static void simple_callback (struct urb *urb)
 {
-       complete ((struct completion *) urb->context);
+       complete(urb->context);
 }
 
 static struct urb *simple_alloc_urb (
@@ -1046,7 +1046,7 @@ static void unlink1_callback (struct urb *urb)
                status = usb_submit_urb (urb, GFP_ATOMIC);
        if (status) {
                urb->status = status;
-               complete ((struct completion *) urb->context);
+               complete(urb->context);
        }
 }
 
@@ -1136,7 +1136,7 @@ static int verify_not_halted (int ep, struct urb *urb)
                dbg ("ep %02x bogus status: %04x != 0", ep, status);
                return -EINVAL;
        }
-       retval = simple_io (urb, 1, 0, 0, __FUNCTION__);
+       retval = simple_io (urb, 1, 0, 0, __func__);
        if (retval != 0)
                return -EINVAL;
        return 0;
@@ -1158,7 +1158,7 @@ static int verify_halted (int ep, struct urb *urb)
                dbg ("ep %02x bogus status: %04x != 1", ep, status);
                return -EINVAL;
        }
-       retval = simple_io (urb, 1, 0, -EPIPE, __FUNCTION__);
+       retval = simple_io (urb, 1, 0, -EPIPE, __func__);
        if (retval != -EPIPE)
                return -EINVAL;
        retval = simple_io (urb, 1, 0, -EPIPE, "verify_still_halted");
@@ -1404,7 +1404,7 @@ static struct urb *iso_alloc_urb (
                return NULL;
        maxp = 0x7ff & le16_to_cpu(desc->wMaxPacketSize);
        maxp *= 1 + (0x3 & (le16_to_cpu(desc->wMaxPacketSize) >> 11));
-       packets = (bytes + maxp - 1) / maxp;
+       packets = DIV_ROUND_UP(bytes, maxp);
 
        urb = usb_alloc_urb (packets, GFP_KERNEL);
        if (!urb)
@@ -1564,7 +1564,8 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
        if (mutex_lock_interruptible(&dev->lock))
                return -ERESTARTSYS;
 
-       if (intf->dev.power.power_state.event != PM_EVENT_ON) {
+       /* FIXME: What if a system sleep starts while a test is running? */
+       if (!intf->is_active) {
                mutex_unlock(&dev->lock);
                return -EHOSTUNREACH;
        }
index 90c59535778d7c39218c602c1536c7e3e047a278..0f76ed5e16174a49e8369ade4acf0abd3d4573c3 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Makefile for USB Core files and filesystem
+# Makefile for USB monitor
 #
 
 usbmon-objs    := mon_main.o mon_stat.o mon_text.o mon_bin.o mon_dma.o
index 1774ba5c4c3bf8944118d7b13c944f07370a1529..49145534e06ee5c92ed41934429942e3e34e819a 100644 (file)
@@ -1026,8 +1026,6 @@ mon_bin_poll(struct file *file, struct poll_table_struct *wait)
        return mask;
 }
 
-#if 0
-
 /*
  * open and close: just keep track of how many times the device is
  * mapped, to use the proper memory allocation function.
@@ -1063,13 +1061,13 @@ static int mon_bin_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        return 0;
 }
 
-struct vm_operations_struct mon_bin_vm_ops = {
+static struct vm_operations_struct mon_bin_vm_ops = {
        .open =     mon_bin_vma_open,
        .close =    mon_bin_vma_close,
        .fault =    mon_bin_vma_fault,
 };
 
-int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma)
+static int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma)
 {
        /* don't do anything here: "fault" will set up page table entries */
        vma->vm_ops = &mon_bin_vm_ops;
@@ -1079,8 +1077,6 @@ int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma)
        return 0;
 }
 
-#endif  /*  0  */
-
 static const struct file_operations mon_fops_binary = {
        .owner =        THIS_MODULE,
        .open =         mon_bin_open,
@@ -1090,6 +1086,7 @@ static const struct file_operations mon_fops_binary = {
        .poll =         mon_bin_poll,
        .ioctl =        mon_bin_ioctl,
        .release =      mon_bin_release,
+       .mmap =         mon_bin_mmap,
 };
 
 static int mon_bin_wait_event(struct file *file, struct mon_reader_bin *rp)
index b371ffd39d369b8c34615bc250587aaef8d19790..442d8076b201d10284c1928fdaa1a3891f5ae027 100644 (file)
@@ -129,8 +129,7 @@ static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error)
 
 /*
  */
-static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb,
-               int status)
+static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb, int status)
 {
        unsigned long flags;
        struct list_head *pos;
index f6d1491256c4453ebfb1b06f2a908b4c29d364fd..c7a595cd648ae2b2f473390b94d0f89b0fb2214f 100644 (file)
@@ -59,6 +59,9 @@ static ssize_t mon_stat_read(struct file *file, char __user *buf,
 
 static int mon_stat_release(struct inode *inode, struct file *file)
 {
+       struct snap *sp = file->private_data;
+       file->private_data = NULL;
+       kfree(sp);
        return 0;
 }
 
index c1e65dfd93538349f07b4d056bbdc2d25a0709a5..2cffec85ee7e6581d95f14971a2afc7fe1eadbce 100644 (file)
@@ -20,8 +20,8 @@ menuconfig USB_SERIAL
 if USB_SERIAL
 
 config USB_SERIAL_CONSOLE
-       bool "USB Serial Console device support (EXPERIMENTAL)"
-       depends on USB_SERIAL=y && EXPERIMENTAL
+       bool "USB Serial Console device support"
+       depends on USB_SERIAL=y
        ---help---
          If you say Y here, it will be possible to use a USB to serial
          converter port as the system console (the system console is the
@@ -44,13 +44,11 @@ config USB_SERIAL_CONSOLE
 
 config USB_EZUSB
        bool "Functions for loading firmware on EZUSB chips"
-       depends on USB_SERIAL
        help
            Say Y here if you need EZUSB device support.
 
 config USB_SERIAL_GENERIC
        bool "USB Generic Serial Driver"
-       depends on USB_SERIAL
        help
          Say Y here if you want to use the generic USB serial driver.  Please
          read <file:Documentation/usb/usb-serial.txt> for more information on
@@ -59,8 +57,7 @@ config USB_SERIAL_GENERIC
          properly.
 
 config USB_SERIAL_AIRCABLE
-       tristate "USB AIRcable Bluetooth Dongle Driver (EXPERIMENTAL)"
-       depends on USB_SERIAL && EXPERIMENTAL
+       tristate "USB AIRcable Bluetooth Dongle Driver"
        help
            Say Y here if you want to use USB AIRcable Bluetooth Dongle.
 
@@ -69,7 +66,6 @@ config USB_SERIAL_AIRCABLE
 
 config USB_SERIAL_AIRPRIME
        tristate "USB AirPrime CDMA Wireless Driver"
-       depends on USB_SERIAL
        help
          Say Y here if you want to use a AirPrime CDMA Wireless PC card.
 
@@ -77,8 +73,7 @@ config USB_SERIAL_AIRPRIME
          module will be called airprime.
 
 config USB_SERIAL_ARK3116
-       tristate "USB ARK Micro 3116 USB Serial Driver (EXPERIMENTAL)"
-       depends on USB_SERIAL && EXPERIMENTAL
+       tristate "USB ARK Micro 3116 USB Serial Driver"
        help
          Say Y here if you want to use a ARK Micro 3116 USB to Serial
          device.
@@ -88,7 +83,6 @@ config USB_SERIAL_ARK3116
 
 config USB_SERIAL_BELKIN
        tristate "USB Belkin and Peracom Single Port Serial Driver"
-       depends on USB_SERIAL
        help
          Say Y here if you want to use a Belkin USB Serial single port
          adaptor (F5U103 is one of the model numbers) or the Peracom single
@@ -99,7 +93,6 @@ config USB_SERIAL_BELKIN
 
 config USB_SERIAL_CH341
        tristate "USB Winchiphead CH341 Single Port Serial Driver"
-       depends on USB_SERIAL
        help
          Say Y here if you want to use a Winchiphead CH341 single port
          USB to serial adapter.
@@ -109,7 +102,6 @@ config USB_SERIAL_CH341
 
 config USB_SERIAL_WHITEHEAT
        tristate "USB ConnectTech WhiteHEAT Serial Driver"
-       depends on USB_SERIAL
        select USB_EZUSB
        help
          Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
@@ -120,7 +112,6 @@ config USB_SERIAL_WHITEHEAT
 
 config USB_SERIAL_DIGI_ACCELEPORT
        tristate "USB Digi International AccelePort USB Serial Driver"
-       depends on USB_SERIAL
        ---help---
          Say Y here if you want to use Digi AccelePort USB 2 or 4 devices,
          2 port (plus parallel port) and 4 port USB serial converters.  The
@@ -135,7 +126,6 @@ config USB_SERIAL_DIGI_ACCELEPORT
 
 config USB_SERIAL_CP2101
        tristate "USB CP2101 UART Bridge Controller"
-       depends on USB_SERIAL && EXPERIMENTAL
        help
          Say Y here if you want to use a CP2101/CP2102 based USB to RS232
          converter.
@@ -145,7 +135,6 @@ config USB_SERIAL_CP2101
 
 config USB_SERIAL_CYPRESS_M8
        tristate "USB Cypress M8 USB Serial Driver"
-       depends on USB_SERIAL && EXPERIMENTAL
        help
          Say Y here if you want to use a device that contains the Cypress
          USB to Serial microcontroller, such as the DeLorme Earthmate GPS.
@@ -160,7 +149,6 @@ config USB_SERIAL_CYPRESS_M8
 
 config USB_SERIAL_EMPEG
        tristate "USB Empeg empeg-car Mark I/II Driver"
-       depends on USB_SERIAL
        help
          Say Y here if you want to connect to your Empeg empeg-car Mark I/II
          mp3 player via USB.  The driver uses a single ttyUSB{0,1,2,...}
@@ -171,8 +159,7 @@ config USB_SERIAL_EMPEG
          module will be called empeg.
 
 config USB_SERIAL_FTDI_SIO
-       tristate "USB FTDI Single Port Serial Driver (EXPERIMENTAL)"
-       depends on USB_SERIAL && EXPERIMENTAL
+       tristate "USB FTDI Single Port Serial Driver"
        ---help---
          Say Y here if you want to use a FTDI SIO single port USB to serial
          converter device. The implementation I have is called the USC-1000.
@@ -186,7 +173,6 @@ config USB_SERIAL_FTDI_SIO
 
 config USB_SERIAL_FUNSOFT
        tristate "USB Fundamental Software Dongle Driver"
-       depends on USB_SERIAL
        ---help---
          Say Y here if you want to use the Fundamental Software dongle.
 
@@ -195,7 +181,6 @@ config USB_SERIAL_FUNSOFT
 
 config USB_SERIAL_VISOR
        tristate "USB Handspring Visor / Palm m50x / Sony Clie Driver"
-       depends on USB_SERIAL
        help
          Say Y here if you want to connect to your HandSpring Visor, Palm
          m500 or m505 through its USB docking station. See
@@ -207,7 +192,6 @@ config USB_SERIAL_VISOR
 
 config USB_SERIAL_IPAQ
        tristate "USB PocketPC PDA Driver"
-       depends on USB_SERIAL
        help
          Say Y here if you want to connect to your Compaq iPAQ, HP Jornada
          or any other PDA running Windows CE 3.0 or PocketPC 2002
@@ -218,8 +202,7 @@ config USB_SERIAL_IPAQ
          module will be called ipaq.
 
 config USB_SERIAL_IR
-       tristate "USB IR Dongle Serial Driver (EXPERIMENTAL)"
-       depends on USB_SERIAL && EXPERIMENTAL
+       tristate "USB IR Dongle Serial Driver"
        help
          Say Y here if you want to enable simple serial support for USB IrDA
          devices.  This is useful if you do not want to use the full IrDA
@@ -230,7 +213,6 @@ config USB_SERIAL_IR
 
 config USB_SERIAL_EDGEPORT
        tristate "USB Inside Out Edgeport Serial Driver"
-       depends on USB_SERIAL
        ---help---
          Say Y here if you want to use any of the following devices from
          Inside Out Networks (Digi):
@@ -256,7 +238,6 @@ config USB_SERIAL_EDGEPORT
 
 config USB_SERIAL_EDGEPORT_TI
        tristate "USB Inside Out Edgeport Serial Driver (TI devices)"
-       depends on USB_SERIAL
        help
          Say Y here if you want to use any of the devices from Inside Out
          Networks (Digi) that are not supported by the io_edgeport driver.
@@ -267,7 +248,6 @@ config USB_SERIAL_EDGEPORT_TI
 
 config USB_SERIAL_GARMIN
        tristate "USB Garmin GPS driver"
-       depends on USB_SERIAL
        help
          Say Y here if you want to connect to your Garmin GPS.
          Should work with most Garmin GPS devices which have a native USB port.
@@ -279,8 +259,7 @@ config USB_SERIAL_GARMIN
          module will be called garmin_gps.
 
 config USB_SERIAL_IPW
-        tristate "USB IPWireless (3G UMTS TDD) Driver (EXPERIMENTAL)"
-       depends on USB_SERIAL && EXPERIMENTAL
+        tristate "USB IPWireless (3G UMTS TDD) Driver"
        help
          Say Y here if you want to use a IPWireless USB modem such as
          the ones supplied by Axity3G/Sentech South Africa.
@@ -289,8 +268,7 @@ config USB_SERIAL_IPW
          module will be called ipw.
 
 config USB_SERIAL_IUU
-       tristate "USB Infinity USB Unlimited Phoenix Driver (Experimental)"
-       depends on USB_SERIAL && EXPERIMENTAL
+       tristate "USB Infinity USB Unlimited Phoenix Driver"
        help
          Say Y here if you want to use a IUU in phoenix mode and get
          an extra ttyUSBx device. More information available on
@@ -301,7 +279,6 @@ config USB_SERIAL_IUU
 
 config USB_SERIAL_KEYSPAN_PDA
        tristate "USB Keyspan PDA Single Port Serial Driver"
-       depends on USB_SERIAL
        select USB_EZUSB
        help
          Say Y here if you want to use a Keyspan PDA single port USB to
@@ -313,7 +290,6 @@ config USB_SERIAL_KEYSPAN_PDA
 
 config USB_SERIAL_KEYSPAN
        tristate "USB Keyspan USA-xxx Serial Driver"
-       depends on USB_SERIAL
        select USB_EZUSB
        ---help---
          Say Y here if you want to use Keyspan USB to serial converter
@@ -405,8 +381,7 @@ config USB_SERIAL_KEYSPAN_USA49WLC
          Say Y here to include firmware for the USA-49WLC converter.
 
 config USB_SERIAL_KLSI
-       tristate "USB KL5KUSB105 (Palmconnect) Driver (EXPERIMENTAL)"
-       depends on USB_SERIAL && EXPERIMENTAL
+       tristate "USB KL5KUSB105 (Palmconnect) Driver"
        ---help---
          Say Y here if you want to use a KL5KUSB105 - based single port
          serial adapter. The most widely known -- and currently the only
@@ -422,7 +397,6 @@ config USB_SERIAL_KLSI
 
 config USB_SERIAL_KOBIL_SCT
         tristate "USB KOBIL chipcard reader"
-        depends on USB_SERIAL
         ---help---
           Say Y here if you want to use one of the following KOBIL USB chipcard
           readers:
@@ -440,7 +414,6 @@ config USB_SERIAL_KOBIL_SCT
 
 config USB_SERIAL_MCT_U232
        tristate "USB MCT Single Port Serial Driver"
-       depends on USB_SERIAL
        ---help---
          Say Y here if you want to use a USB Serial single port adapter from
          Magic Control Technology Corp. (U232 is one of the model numbers).
@@ -453,7 +426,6 @@ config USB_SERIAL_MCT_U232
 
 config USB_SERIAL_MOS7720
        tristate "USB Moschip 7720 Serial Driver"
-       depends on USB_SERIAL
        ---help---
          Say Y here if you want to use USB Serial single and double
          port adapters from Moschip Semiconductor Tech.
@@ -463,7 +435,6 @@ config USB_SERIAL_MOS7720
 
 config USB_SERIAL_MOS7840
        tristate "USB Moschip 7840/7820 USB Serial Driver"
-       depends on USB_SERIAL
        ---help---
          Say Y here if you want to use a MCS7840 Quad-Serial or MCS7820
          Dual-Serial port device from MosChip Semiconductor.
@@ -478,14 +449,12 @@ config USB_SERIAL_MOS7840
 
 config USB_SERIAL_NAVMAN
        tristate "USB Navman GPS device"
-       depends on USB_SERIAL
        help
          To compile this driver as a module, choose M here: the
          module will be called navman.
 
 config USB_SERIAL_PL2303
        tristate "USB Prolific 2303 Single Port Serial Driver"
-       depends on USB_SERIAL
        help
          Say Y here if you want to use the PL2303 USB Serial single port
          adapter from Prolific.
@@ -494,8 +463,7 @@ config USB_SERIAL_PL2303
          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
+       tristate "USB Ours Technology Inc. OTi-6858 USB To RS232 Bridge Controller"
        help
          Say Y here if you want to use the OTi-6858 single port USB to serial
           converter device.
@@ -503,9 +471,17 @@ config USB_SERIAL_OTI6858
          To compile this driver as a module, choose M here: the
          module will be called oti6858.
 
+config USB_SERIAL_SPCP8X5
+       tristate "USB SPCP8x5 USB To Serial Driver"
+       help
+         Say Y here if you want to use the spcp8x5 converter chip.  This is
+         commonly found in some Z-Wave USB devices.
+
+         To compile this driver as a module, choose M here: the
+         module will be called spcp8x5.
+
 config USB_SERIAL_HP4X
         tristate "USB HP4x Calculators support"
-        depends on USB_SERIAL
         help
           Say Y here if you want to use an Hewlett-Packard 4x Calculator.
 
@@ -513,8 +489,7 @@ config USB_SERIAL_HP4X
           module will be called hp4x.
 
 config USB_SERIAL_SAFE
-       tristate "USB Safe Serial (Encapsulated) Driver (EXPERIMENTAL)"
-       depends on USB_SERIAL && EXPERIMENTAL
+       tristate "USB Safe Serial (Encapsulated) Driver"
 
 config USB_SERIAL_SAFE_PADDED
        bool "USB Secure Encapsulated Driver - Padded"
@@ -522,7 +497,6 @@ config USB_SERIAL_SAFE_PADDED
 
 config USB_SERIAL_SIERRAWIRELESS
        tristate "USB Sierra Wireless Driver"
-       depends on USB_SERIAL
        help
          Say M here if you want to use a Sierra Wireless device (if
          using an PC 5220 or AC580 please use the Airprime driver
@@ -533,7 +507,6 @@ config USB_SERIAL_SIERRAWIRELESS
 
 config USB_SERIAL_TI
        tristate "USB TI 3410/5052 Serial Driver"
-       depends on USB_SERIAL
        help
          Say Y here if you want to use the TI USB 3410 or 5052
          serial devices.
@@ -542,8 +515,7 @@ config USB_SERIAL_TI
          module will be called ti_usb_3410_5052.
 
 config USB_SERIAL_CYBERJACK
-       tristate "USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)"
-       depends on USB_SERIAL && EXPERIMENTAL
+       tristate "USB REINER SCT cyberJack pinpad/e-com chipcard reader"
        ---help---
          Say Y here if you want to use a cyberJack pinpad/e-com USB chipcard
          reader. This is an interface to ISO 7816 compatible contact-based
@@ -556,7 +528,6 @@ config USB_SERIAL_CYBERJACK
 
 config USB_SERIAL_XIRCOM
        tristate "USB Xircom / Entregra Single Port Serial Driver"
-       depends on USB_SERIAL
        select USB_EZUSB
        help
          Say Y here if you want to use a Xircom or Entregra single port USB to
@@ -568,7 +539,6 @@ config USB_SERIAL_XIRCOM
 
 config USB_SERIAL_OPTION
        tristate "USB driver for GSM and CDMA modems"
-       depends on USB_SERIAL
        help
          Say Y here if you have a GSM or CDMA modem that's connected to USB.
 
@@ -586,8 +556,7 @@ config USB_SERIAL_OPTION
          it might be accessible via the FTDI_SIO driver.
 
 config USB_SERIAL_OMNINET
-       tristate "USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)"
-       depends on USB_SERIAL && EXPERIMENTAL
+       tristate "USB ZyXEL omni.net LCD Plus Driver"
        help
          Say Y here if you want to use a ZyXEL omni.net LCD ISDN TA.
 
@@ -596,7 +565,6 @@ config USB_SERIAL_OMNINET
 
 config USB_SERIAL_DEBUG
        tristate "USB Debugging Device"
-       depends on USB_SERIAL
        help
          Say Y here if you have a USB debugging device used to receive
          debugging data from another machine.  The most common of these
index 0db109a54d10b621242f1ca489f23362ed2a3528..756859510d8c2cfff713b6ff13b7f0076b5bf057 100644 (file)
@@ -30,8 +30,8 @@ obj-$(CONFIG_USB_SERIAL_GARMIN)                       += garmin_gps.o
 obj-$(CONFIG_USB_SERIAL_HP4X)                  += hp4x.o
 obj-$(CONFIG_USB_SERIAL_IPAQ)                  += ipaq.o
 obj-$(CONFIG_USB_SERIAL_IPW)                   += ipw.o
-obj-$(CONFIG_USB_SERIAL_IUU)                   += iuu_phoenix.o
 obj-$(CONFIG_USB_SERIAL_IR)                    += ir-usb.o
+obj-$(CONFIG_USB_SERIAL_IUU)                   += iuu_phoenix.o
 obj-$(CONFIG_USB_SERIAL_KEYSPAN)               += keyspan.o
 obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA)           += keyspan_pda.o
 obj-$(CONFIG_USB_SERIAL_KLSI)                  += kl5kusb105.o
@@ -46,6 +46,7 @@ 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
+obj-$(CONFIG_USB_SERIAL_SPCP8X5)               += spcp8x5.o
 obj-$(CONFIG_USB_SERIAL_TI)                    += ti_usb_3410_5052.o
 obj-$(CONFIG_USB_SERIAL_VISOR)                 += visor.o
 obj-$(CONFIG_USB_SERIAL_WHITEHEAT)             += whiteheat.o
index 1cd29cd6bd00c46f524db37a8f21da42be9598f9..a238817762adad0c448903e90f7267233739015c 100644 (file)
@@ -210,7 +210,7 @@ static void aircable_send(struct usb_serial_port *port)
        struct aircable_private *priv = usb_get_serial_port_data(port);
        unsigned char* buf;
        u16 *dbuf;
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
        if (port->write_urb_busy)
                return;
 
@@ -220,7 +220,7 @@ static void aircable_send(struct usb_serial_port *port)
 
        buf = kzalloc(count + HCI_HEADER_LENGTH, GFP_ATOMIC);
        if (!buf) {
-               err("%s- kzalloc(%d) failed.", __FUNCTION__,
+               err("%s- kzalloc(%d) failed.", __func__,
                    count + HCI_HEADER_LENGTH);
                return;
        }
@@ -236,7 +236,7 @@ static void aircable_send(struct usb_serial_port *port)
 
        kfree(buf);
        port->write_urb_busy = 1;
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+       usb_serial_debug_data(debug, &port->dev, __func__,
                              count + HCI_HEADER_LENGTH,
                              port->write_urb->transfer_buffer);
        port->write_urb->transfer_buffer_length = count + HCI_HEADER_LENGTH;
@@ -246,7 +246,7 @@ static void aircable_send(struct usb_serial_port *port)
        if (result) {
                dev_err(&port->dev,
                        "%s - failed submitting write urb, error %d\n",
-                       __FUNCTION__, result);
+                       __func__, result);
                port->write_urb_busy = 0;
        }
 
@@ -275,7 +275,7 @@ static void aircable_read(struct work_struct *work)
 
        if (!tty) {
                schedule_work(&priv->rx_work);
-               err("%s - No tty available", __FUNCTION__);
+               err("%s - No tty available", __func__);
                return ;
        }
 
@@ -286,7 +286,7 @@ static void aircable_read(struct work_struct *work)
 
        tty_prepare_flip_string(tty, &data, count);
        if (!data){
-               err("%s- kzalloc(%d) failed.", __FUNCTION__, count);
+               err("%s- kzalloc(%d) failed.", __func__, count);
                return;
        }
 
@@ -332,7 +332,7 @@ static int aircable_attach (struct usb_serial *serial)
 
        priv = kzalloc(sizeof(struct aircable_private), GFP_KERNEL);
        if (!priv){
-               err("%s- kmalloc(%Zd) failed.", __FUNCTION__,
+               err("%s- kmalloc(%Zd) failed.", __func__,
                        sizeof(struct aircable_private));
                return -ENOMEM;
        }
@@ -366,7 +366,7 @@ static void aircable_shutdown(struct usb_serial *serial)
        struct usb_serial_port *port = serial->port[0];
        struct aircable_private *priv = usb_get_serial_port_data(port);
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        if (priv) {
                serial_buf_free(priv->tx_buf);
@@ -388,12 +388,12 @@ static int aircable_write(struct usb_serial_port *port,
        struct aircable_private *priv = usb_get_serial_port_data(port);
        int temp;
 
-       dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
+       dbg("%s - port %d, %d bytes", __func__, port->number, count);
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, source);
+       usb_serial_debug_data(debug, &port->dev, __func__, count, source);
 
        if (!count){
-               dbg("%s - write request of 0 bytes", __FUNCTION__);
+               dbg("%s - write request of 0 bytes", __func__);
                return count;
        }
 
@@ -414,7 +414,7 @@ static void aircable_write_bulk_callback(struct urb *urb)
        int status = urb->status;
        int result;
 
-       dbg("%s - urb status: %d", __FUNCTION__ , status);
+       dbg("%s - urb status: %d", __func__ , status);
 
        /* This has been taken from cypress_m8.c cypress_write_int_callback */
        switch (status) {
@@ -426,21 +426,21 @@ 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__, status);
+                           __func__, 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 - Overflow in write", __func__);
                        dbg("%s - nonzero write bulk status received: %d",
-                           __FUNCTION__, status);
+                           __func__, status);
                        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(&urb->dev->dev,
                                        "%s - failed resubmitting write urb, error %d\n",
-                                       __FUNCTION__, result);
+                                       __func__, result);
                        else
                                return;
        }
@@ -460,17 +460,17 @@ static void aircable_read_bulk_callback(struct urb *urb)
        unsigned char *temp;
        int status = urb->status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (status) {
-               dbg("%s - urb status = %d", __FUNCTION__, status);
+               dbg("%s - urb status = %d", __func__, status);
                if (!port->open_count) {
-                       dbg("%s - port is closed, exiting.", __FUNCTION__);
+                       dbg("%s - port is closed, exiting.", __func__);
                        return;
                }
                if (status == -EPROTO) {
                        dbg("%s - caught -EPROTO, resubmitting the urb",
-                           __FUNCTION__);
+                           __func__);
                        usb_fill_bulk_urb(port->read_urb, port->serial->dev,
                                          usb_rcvbulkpipe(port->serial->dev,
                                                          port->bulk_in_endpointAddress),
@@ -482,14 +482,14 @@ static void aircable_read_bulk_callback(struct urb *urb)
                        if (result)
                                dev_err(&urb->dev->dev,
                                        "%s - failed resubmitting read urb, error %d\n",
-                                       __FUNCTION__, result);
+                                       __func__, result);
                        return;
                }
-               dbg("%s - unable to handle the error, exiting.", __FUNCTION__);
+               dbg("%s - unable to handle the error, exiting.", __func__);
                return;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+       usb_serial_debug_data(debug, &port->dev, __func__,
                                urb->actual_length,urb->transfer_buffer);
 
        tty = port->tty;
@@ -538,7 +538,7 @@ static void aircable_read_bulk_callback(struct urb *urb)
                if (result)
                        dev_err(&urb->dev->dev,
                                "%s - failed resubmitting read urb, error %d\n",
-                               __FUNCTION__, result);
+                               __func__, result);
        }
 
        return;
@@ -550,7 +550,7 @@ static void aircable_throttle(struct usb_serial_port *port)
        struct aircable_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->rx_lock, flags);
        priv->rx_flags |= THROTTLED;
@@ -564,7 +564,7 @@ static void aircable_unthrottle(struct usb_serial_port *port)
        int actually_throttled;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->rx_lock, flags);
        actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
index f156dba0300f77168f7774199e988074bd249e8a..725b6b94c2740c2f0c58743caeca428c11cccc28 100644 (file)
@@ -53,7 +53,7 @@ static int airprime_send_setup(struct usb_serial_port *port)
        struct usb_serial *serial = port->serial;
        struct airprime_private *priv;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        if (port->number != 0)
                return 0;
@@ -83,14 +83,14 @@ static void airprime_read_bulk_callback(struct urb *urb)
        int result;
        int status = urb->status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (status) {
                dbg("%s - nonzero read bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        }
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+       usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
 
        tty = port->tty;
        if (tty && urb->actual_length) {
@@ -101,7 +101,7 @@ static void airprime_read_bulk_callback(struct urb *urb)
        result = usb_submit_urb (urb, GFP_ATOMIC);
        if (result)
                dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
-                       __FUNCTION__, result);
+                       __func__, result);
        return;
 }
 
@@ -112,14 +112,14 @@ static void airprime_write_bulk_callback(struct urb *urb)
        int status = urb->status;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, 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);
+                   __func__, status);
        spin_lock_irqsave(&priv->lock, flags);
        --priv->outstanding_urbs;
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -136,7 +136,7 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
        int i;
        int result = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /* initialize our private data structure if it isn't already created */
        if (!priv) {
@@ -157,7 +157,7 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
                buffer = kmalloc(buffer_size, GFP_KERNEL);
                if (!buffer) {
                        dev_err(&port->dev, "%s - out of memory.\n",
-                               __FUNCTION__);
+                               __func__);
                        result = -ENOMEM;
                        goto errout;
                }
@@ -165,7 +165,7 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
                if (!urb) {
                        kfree(buffer);
                        dev_err(&port->dev, "%s - no more urbs?\n",
-                               __FUNCTION__);
+                               __func__);
                        result = -ENOMEM;
                        goto errout;
                }
@@ -180,7 +180,7 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
                        kfree(buffer);
                        dev_err(&port->dev,
                                "%s - failed submitting read urb %d for port %d, error %d\n",
-                               __FUNCTION__, i, port->number, result);
+                               __func__, i, port->number, result);
                        goto errout;
                }
                /* remember this urb so we can kill it when the port is closed */
@@ -212,7 +212,7 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp)
        struct airprime_private *priv = usb_get_serial_port_data(port);
        int i;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        priv->rts_state = 0;
        priv->dtr_state = 0;
@@ -242,12 +242,12 @@ static int airprime_write(struct usb_serial_port *port,
        unsigned char *buffer;
        unsigned long flags;
        int status;
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
        if (priv->outstanding_urbs > NUM_WRITE_URBS) {
                spin_unlock_irqrestore(&priv->lock, flags);
-               dbg("%s - write limit hit\n", __FUNCTION__);
+               dbg("%s - write limit hit\n", __func__);
                return 0;
        }
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -264,7 +264,7 @@ static int airprime_write(struct usb_serial_port *port,
        }
        memcpy (buffer, buf, count);
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
+       usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
 
        usb_fill_bulk_urb(urb, serial->dev,
                          usb_sndbulkpipe(serial->dev,
@@ -277,7 +277,7 @@ static int airprime_write(struct usb_serial_port *port,
        if (status) {
                dev_err(&port->dev,
                        "%s - usb_submit_urb(write bulk) failed with status = %d\n",
-                       __FUNCTION__, status);
+                       __func__, status);
                count = status;
                kfree (buffer);
        } else {
@@ -306,9 +306,6 @@ static struct usb_serial_driver airprime_device = {
        },
        .usb_driver =           &airprime_driver,
        .id_table =             id_table,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          NUM_DONT_CARE,
-       .num_bulk_out =         NUM_DONT_CARE,
        .open =                 airprime_open,
        .close =                airprime_close,
        .write =                airprime_write,
@@ -331,7 +328,7 @@ static int __init airprime_init(void)
 
 static void __exit airprime_exit(void)
 {
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        usb_deregister(&airprime_driver);
        usb_serial_deregister(&airprime_device);
index fe2bfd67ba8e4717ef3b96657902663dbeedd22c..599ab2e548a7c3e483abc255471ee5b92838c90e 100644 (file)
@@ -173,7 +173,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
 
        config = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
        if (!priv->termios_initialized) {
@@ -192,6 +192,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
        buf = kmalloc(1, GFP_KERNEL);
        if (!buf) {
                dbg("error kmalloc");
+               *port->tty->termios = *old_termios;
                return;
        }
 
@@ -323,7 +324,7 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp)
        char *buf;
        int result = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        buf = kmalloc(1, GFP_KERNEL);
        if (!buf) {
@@ -395,7 +396,7 @@ static int ark3116_ioctl(struct usb_serial_port *port, struct file *file,
                        return -EFAULT;
                return 0;
        default:
-               dbg("%s cmd 0x%04x not supported", __FUNCTION__, cmd);
+               dbg("%s cmd 0x%04x not supported", __func__, cmd);
                break;
        }
 
@@ -447,9 +448,6 @@ static struct usb_serial_driver ark3116_device = {
        },
        .id_table =             id_table,
        .usb_driver =           &ark3116_driver,
-       .num_interrupt_in =     1,
-       .num_bulk_in =          1,
-       .num_bulk_out =         1,
        .num_ports =            1,
        .attach =               ark3116_attach,
        .set_termios =          ark3116_set_termios,
index df0a2b3b02943e76d40a89f832c498eea0e964ca..0a322fc53d6e23694e612eb9184e55d005caad31 100644 (file)
@@ -128,9 +128,6 @@ static struct usb_serial_driver belkin_device = {
        .description =          "Belkin / Peracom / GoHubs USB Serial Adapter",
        .usb_driver =           &belkin_driver,
        .id_table =             id_table_combined,
-       .num_interrupt_in =     1,
-       .num_bulk_in =          1,
-       .num_bulk_out =         1,
        .num_ports =            1,
        .open =                 belkin_sa_open,
        .close =                belkin_sa_close,
@@ -198,7 +195,7 @@ static void belkin_sa_shutdown (struct usb_serial *serial)
        struct belkin_sa_private *priv;
        int i;
        
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        /* stop reads and writes on all ports */
        for (i=0; i < serial->num_ports; ++i) {
@@ -213,7 +210,7 @@ static int  belkin_sa_open (struct usb_serial_port *port, struct file *filp)
 {
        int retval = 0;
 
-       dbg("%s port %d", __FUNCTION__, port->number);
+       dbg("%s port %d", __func__, port->number);
 
        /*Start reading from the device*/
        /* TODO: Look at possibility of submitting multiple URBs to device to
@@ -240,7 +237,7 @@ exit:
 
 static void belkin_sa_close (struct usb_serial_port *port, struct file *filp)
 {
-       dbg("%s port %d", __FUNCTION__, port->number);
+       dbg("%s port %d", __func__, port->number);
 
        /* shutdown our bulk reads and writes */
        usb_kill_urb(port->write_urb);
@@ -251,7 +248,7 @@ static void belkin_sa_close (struct usb_serial_port *port, struct file *filp)
 
 static void belkin_sa_read_int_callback (struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct belkin_sa_private *priv;
        unsigned char *data = urb->transfer_buffer;
        int retval;
@@ -267,15 +264,15 @@ static void belkin_sa_read_int_callback (struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                goto exit;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+       usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
 
        /* Handle known interrupt data */
        /* ignore data[0] and data[1] */
@@ -334,7 +331,7 @@ exit:
        retval = usb_submit_urb (urb, GFP_ATOMIC);
        if (retval)
                err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, retval);
+                    __func__, retval);
 }
 
 static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
@@ -481,7 +478,7 @@ static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file)
        unsigned long control_state;
        unsigned long flags;
        
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        spin_lock_irqsave(&priv->lock, flags);
        control_state = priv->control_state;
@@ -502,7 +499,7 @@ static int belkin_sa_tiocmset (struct usb_serial_port *port, struct file *file,
        int rts = 0;
        int dtr = 0;
        
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        spin_lock_irqsave(&priv->lock, flags);
        control_state = priv->control_state;
index 42582d49b69c8951391e6a0a03c48f15d3756662..d947d955bceb9504d9beae2d9877ddb41c105e28 100644 (file)
@@ -318,9 +318,6 @@ static struct usb_serial_driver ch341_device = {
        },
        .id_table         = id_table,
        .usb_driver       = &ch341_driver,
-       .num_interrupt_in = NUM_DONT_CARE,
-       .num_bulk_in      = 1,
-       .num_bulk_out     = 1,
        .num_ports        = 1,
        .open             = ch341_open,
        .set_termios      = ch341_set_termios,
index 66ce30c1b75bba3db5e91e61f8105f10ba2a30d2..201184c3fb87ebc271db45d244b44ab884745ef6 100644 (file)
@@ -67,7 +67,7 @@ static int usb_console_setup(struct console *co, char *options)
        struct tty_struct *tty = NULL;
        struct ktermios *termios = NULL, dummy;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        if (options) {
                baud = simple_strtoul(options, NULL, 10);
@@ -225,10 +225,10 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun
        if (count == 0)
                return;
 
-       dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
+       dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
 
        if (!port->open_count) {
-               dbg ("%s - port not opened", __FUNCTION__);
+               dbg ("%s - port not opened", __func__);
                return;
        }
 
@@ -248,7 +248,7 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun
                        retval = serial->type->write(port, buf, i);
                else
                        retval = usb_serial_generic_write(port, buf, i);
-               dbg("%s - return value : %d", __FUNCTION__, retval);
+               dbg("%s - return value : %d", __func__, retval);
                if (lf) {
                        /* append CR after LF */
                        unsigned char cr = 13;
@@ -256,7 +256,7 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun
                                retval = serial->type->write(port, &cr, 1);
                        else
                                retval = usb_serial_generic_write(port, &cr, 1);
-                       dbg("%s - return value : %d", __FUNCTION__, retval);
+                       dbg("%s - return value : %d", __func__, retval);
                }
                buf += i;
                count -= i;
index 324bb61d68ffed5c91b880215270e5d7dc89d66e..dc0ea08ed2315773b0f85fbcaf25848d83d69be9 100644 (file)
@@ -53,9 +53,11 @@ static void cp2101_shutdown(struct usb_serial*);
 static int debug;
 
 static struct usb_device_id id_table [] = {
+       { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
        { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
        { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
        { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */
+       { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */
        { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
        { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
        { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
@@ -71,6 +73,7 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
        { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
        { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
+       { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */
        { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
        { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
        { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */
@@ -106,9 +109,6 @@ static struct usb_serial_driver cp2101_device = {
        },
        .usb_driver             = &cp2101_driver,
        .id_table               = id_table,
-       .num_interrupt_in       = 0,
-       .num_bulk_in            = NUM_DONT_CARE,
-       .num_bulk_out           = NUM_DONT_CARE,
        .num_ports              = 1,
        .open                   = cp2101_open,
        .close                  = cp2101_close,
@@ -193,7 +193,7 @@ static int cp2101_get_config(struct usb_serial_port* port, u8 request,
 
        buf = kcalloc(length, sizeof(__le32), GFP_KERNEL);
        if (!buf) {
-               dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
+               dev_err(&port->dev, "%s - out of memory.\n", __func__);
                return -ENOMEM;
        }
 
@@ -214,7 +214,7 @@ static int cp2101_get_config(struct usb_serial_port* port, u8 request,
        if (result != size) {
                dev_err(&port->dev, "%s - Unable to send config request, "
                                "request=0x%x size=%d result=%d\n",
-                               __FUNCTION__, request, size, result);
+                               __func__, request, size, result);
                return -EPROTO;
        }
 
@@ -240,7 +240,7 @@ static int cp2101_set_config(struct usb_serial_port* port, u8 request,
        buf = kmalloc(length * sizeof(__le32), GFP_KERNEL);
        if (!buf) {
                dev_err(&port->dev, "%s - out of memory.\n",
-                               __FUNCTION__);
+                               __func__);
                return -ENOMEM;
        }
 
@@ -265,7 +265,7 @@ static int cp2101_set_config(struct usb_serial_port* port, u8 request,
        if ((size > 2 && result != size) || result < 0) {
                dev_err(&port->dev, "%s - Unable to send request, "
                                "request=0x%x size=%d result=%d\n",
-                               __FUNCTION__, request, size, result);
+                               __func__, request, size, result);
                return -EPROTO;
        }
 
@@ -293,11 +293,11 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp)
        struct usb_serial *serial = port->serial;
        int result;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (cp2101_set_config_single(port, CP2101_UART, UART_ENABLE)) {
                dev_err(&port->dev, "%s - Unable to enable UART\n",
-                               __FUNCTION__);
+                               __func__);
                return -EPROTO;
        }
 
@@ -312,7 +312,7 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp)
        result = usb_submit_urb(port->read_urb, GFP_KERNEL);
        if (result) {
                dev_err(&port->dev, "%s - failed resubmitting read urb, "
-                               "error %d\n", __FUNCTION__, result);
+                               "error %d\n", __func__, result);
                return result;
        }
 
@@ -329,7 +329,7 @@ static void cp2101_cleanup (struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (serial->dev) {
                /* shutdown any bulk reads that might be going on */
@@ -342,10 +342,10 @@ static void cp2101_cleanup (struct usb_serial_port *port)
 
 static void cp2101_close (struct usb_serial_port *port, struct file * filp)
 {
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /* shutdown our urbs */
-       dbg("%s - shutting down urbs", __FUNCTION__);
+       dbg("%s - shutting down urbs", __func__);
        usb_kill_urb(port->write_urb);
        usb_kill_urb(port->read_urb);
 
@@ -367,10 +367,10 @@ static void cp2101_get_termios (struct usb_serial_port *port)
        int baud;
        int bits;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (!port->tty || !port->tty->termios) {
-               dbg("%s - no tty structures", __FUNCTION__);
+               dbg("%s - no tty structures", __func__);
                return;
        }
 
@@ -379,7 +379,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
        if (baud)
                baud = BAUD_RATE_GEN_FREQ / baud;
 
-       dbg("%s - baud rate = %d", __FUNCTION__, baud);
+       dbg("%s - baud rate = %d", __func__, baud);
 
        tty_encode_baud_rate(port->tty, baud, baud);
        cflag = port->tty->termios->c_cflag;
@@ -388,24 +388,24 @@ static void cp2101_get_termios (struct usb_serial_port *port)
        cflag &= ~CSIZE;
        switch(bits & BITS_DATA_MASK) {
                case BITS_DATA_5:
-                       dbg("%s - data bits = 5", __FUNCTION__);
+                       dbg("%s - data bits = 5", __func__);
                        cflag |= CS5;
                        break;
                case BITS_DATA_6:
-                       dbg("%s - data bits = 6", __FUNCTION__);
+                       dbg("%s - data bits = 6", __func__);
                        cflag |= CS6;
                        break;
                case BITS_DATA_7:
-                       dbg("%s - data bits = 7", __FUNCTION__);
+                       dbg("%s - data bits = 7", __func__);
                        cflag |= CS7;
                        break;
                case BITS_DATA_8:
-                       dbg("%s - data bits = 8", __FUNCTION__);
+                       dbg("%s - data bits = 8", __func__);
                        cflag |= CS8;
                        break;
                case BITS_DATA_9:
                        dbg("%s - data bits = 9 (not supported, "
-                                       "using 8 data bits)", __FUNCTION__);
+                                       "using 8 data bits)", __func__);
                        cflag |= CS8;
                        bits &= ~BITS_DATA_MASK;
                        bits |= BITS_DATA_8;
@@ -413,7 +413,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
                        break;
                default:
                        dbg("%s - Unknown number of data bits, "
-                                       "using 8", __FUNCTION__);
+                                       "using 8", __func__);
                        cflag |= CS8;
                        bits &= ~BITS_DATA_MASK;
                        bits |= BITS_DATA_8;
@@ -423,35 +423,35 @@ static void cp2101_get_termios (struct usb_serial_port *port)
 
        switch(bits & BITS_PARITY_MASK) {
                case BITS_PARITY_NONE:
-                       dbg("%s - parity = NONE", __FUNCTION__);
+                       dbg("%s - parity = NONE", __func__);
                        cflag &= ~PARENB;
                        break;
                case BITS_PARITY_ODD:
-                       dbg("%s - parity = ODD", __FUNCTION__);
+                       dbg("%s - parity = ODD", __func__);
                        cflag |= (PARENB|PARODD);
                        break;
                case BITS_PARITY_EVEN:
-                       dbg("%s - parity = EVEN", __FUNCTION__);
+                       dbg("%s - parity = EVEN", __func__);
                        cflag &= ~PARODD;
                        cflag |= PARENB;
                        break;
                case BITS_PARITY_MARK:
                        dbg("%s - parity = MARK (not supported, "
-                                       "disabling parity)", __FUNCTION__);
+                                       "disabling parity)", __func__);
                        cflag &= ~PARENB;
                        bits &= ~BITS_PARITY_MASK;
                        cp2101_set_config(port, CP2101_BITS, &bits, 2);
                        break;
                case BITS_PARITY_SPACE:
                        dbg("%s - parity = SPACE (not supported, "
-                                       "disabling parity)", __FUNCTION__);
+                                       "disabling parity)", __func__);
                        cflag &= ~PARENB;
                        bits &= ~BITS_PARITY_MASK;
                        cp2101_set_config(port, CP2101_BITS, &bits, 2);
                        break;
                default:
                        dbg("%s - Unknown parity mode, "
-                                       "disabling parity", __FUNCTION__);
+                                       "disabling parity", __func__);
                        cflag &= ~PARENB;
                        bits &= ~BITS_PARITY_MASK;
                        cp2101_set_config(port, CP2101_BITS, &bits, 2);
@@ -461,21 +461,21 @@ static void cp2101_get_termios (struct usb_serial_port *port)
        cflag &= ~CSTOPB;
        switch(bits & BITS_STOP_MASK) {
                case BITS_STOP_1:
-                       dbg("%s - stop bits = 1", __FUNCTION__);
+                       dbg("%s - stop bits = 1", __func__);
                        break;
                case BITS_STOP_1_5:
                        dbg("%s - stop bits = 1.5 (not supported, "
-                                       "using 1 stop bit)", __FUNCTION__);
+                                       "using 1 stop bit)", __func__);
                        bits &= ~BITS_STOP_MASK;
                        cp2101_set_config(port, CP2101_BITS, &bits, 2);
                        break;
                case BITS_STOP_2:
-                       dbg("%s - stop bits = 2", __FUNCTION__);
+                       dbg("%s - stop bits = 2", __func__);
                        cflag |= CSTOPB;
                        break;
                default:
                        dbg("%s - Unknown number of stop bits, "
-                                       "using 1 stop bit", __FUNCTION__);
+                                       "using 1 stop bit", __func__);
                        bits &= ~BITS_STOP_MASK;
                        cp2101_set_config(port, CP2101_BITS, &bits, 2);
                        break;
@@ -483,10 +483,10 @@ static void cp2101_get_termios (struct usb_serial_port *port)
 
        cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16);
        if (modem_ctl[0] & 0x0008) {
-               dbg("%s - flow control = CRTSCTS", __FUNCTION__);
+               dbg("%s - flow control = CRTSCTS", __func__);
                cflag |= CRTSCTS;
        } else {
-               dbg("%s - flow control = NONE", __FUNCTION__);
+               dbg("%s - flow control = NONE", __func__);
                cflag &= ~CRTSCTS;
        }
 
@@ -500,10 +500,10 @@ static void cp2101_set_termios (struct usb_serial_port *port,
        int baud=0, bits;
        unsigned int modem_ctl[4];
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (!port->tty || !port->tty->termios) {
-               dbg("%s - no tty structures", __FUNCTION__);
+               dbg("%s - no tty structures", __func__);
                return;
        }
        port->tty->termios->c_cflag &= ~CMSPAR;
@@ -542,7 +542,7 @@ static void cp2101_set_termios (struct usb_serial_port *port,
                }
 
                if (baud) {
-                       dbg("%s - Setting baud rate to %d baud", __FUNCTION__,
+                       dbg("%s - Setting baud rate to %d baud", __func__,
                                        baud);
                        if (cp2101_set_config_single(port, CP2101_BAUDRATE,
                                                (BAUD_RATE_GEN_FREQ / baud))) {
@@ -562,23 +562,23 @@ static void cp2101_set_termios (struct usb_serial_port *port,
                switch (cflag & CSIZE) {
                        case CS5:
                                bits |= BITS_DATA_5;
-                               dbg("%s - data bits = 5", __FUNCTION__);
+                               dbg("%s - data bits = 5", __func__);
                                break;
                        case CS6:
                                bits |= BITS_DATA_6;
-                               dbg("%s - data bits = 6", __FUNCTION__);
+                               dbg("%s - data bits = 6", __func__);
                                break;
                        case CS7:
                                bits |= BITS_DATA_7;
-                               dbg("%s - data bits = 7", __FUNCTION__);
+                               dbg("%s - data bits = 7", __func__);
                                break;
                        case CS8:
                                bits |= BITS_DATA_8;
-                               dbg("%s - data bits = 8", __FUNCTION__);
+                               dbg("%s - data bits = 8", __func__);
                                break;
                        /*case CS9:
                                bits |= BITS_DATA_9;
-                               dbg("%s - data bits = 9", __FUNCTION__);
+                               dbg("%s - data bits = 9", __func__);
                                break;*/
                        default:
                                dev_err(&port->dev, "cp2101 driver does not "
@@ -598,10 +598,10 @@ static void cp2101_set_termios (struct usb_serial_port *port,
                if (cflag & PARENB) {
                        if (cflag & PARODD) {
                                bits |= BITS_PARITY_ODD;
-                               dbg("%s - parity = ODD", __FUNCTION__);
+                               dbg("%s - parity = ODD", __func__);
                        } else {
                                bits |= BITS_PARITY_EVEN;
-                               dbg("%s - parity = EVEN", __FUNCTION__);
+                               dbg("%s - parity = EVEN", __func__);
                        }
                }
                if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
@@ -614,10 +614,10 @@ static void cp2101_set_termios (struct usb_serial_port *port,
                bits &= ~BITS_STOP_MASK;
                if (cflag & CSTOPB) {
                        bits |= BITS_STOP_2;
-                       dbg("%s - stop bits = 2", __FUNCTION__);
+                       dbg("%s - stop bits = 2", __func__);
                } else {
                        bits |= BITS_STOP_1;
-                       dbg("%s - stop bits = 1", __FUNCTION__);
+                       dbg("%s - stop bits = 1", __func__);
                }
                if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
                        dev_err(&port->dev, "Number of stop bits requested "
@@ -627,23 +627,23 @@ static void cp2101_set_termios (struct usb_serial_port *port,
        if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
                cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16);
                dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x",
-                               __FUNCTION__, modem_ctl[0], modem_ctl[1],
+                               __func__, modem_ctl[0], modem_ctl[1],
                                modem_ctl[2], modem_ctl[3]);
 
                if (cflag & CRTSCTS) {
                        modem_ctl[0] &= ~0x7B;
                        modem_ctl[0] |= 0x09;
                        modem_ctl[1] = 0x80;
-                       dbg("%s - flow control = CRTSCTS", __FUNCTION__);
+                       dbg("%s - flow control = CRTSCTS", __func__);
                } else {
                        modem_ctl[0] &= ~0x7B;
                        modem_ctl[0] |= 0x01;
                        modem_ctl[1] |= 0x40;
-                       dbg("%s - flow control = NONE", __FUNCTION__);
+                       dbg("%s - flow control = NONE", __func__);
                }
 
                dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x",
-                               __FUNCTION__, modem_ctl[0], modem_ctl[1],
+                               __func__, modem_ctl[0], modem_ctl[1],
                                modem_ctl[2], modem_ctl[3]);
                cp2101_set_config(port, CP2101_MODEMCTL, modem_ctl, 16);
        }
@@ -655,7 +655,7 @@ static int cp2101_tiocmset (struct usb_serial_port *port, struct file *file,
 {
        int control = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (set & TIOCM_RTS) {
                control |= CONTROL_RTS;
@@ -674,7 +674,7 @@ static int cp2101_tiocmset (struct usb_serial_port *port, struct file *file,
                control |= CONTROL_WRITE_DTR;
        }
 
-       dbg("%s - control = 0x%.4x", __FUNCTION__, control);
+       dbg("%s - control = 0x%.4x", __func__, control);
 
        return cp2101_set_config(port, CP2101_CONTROL, &control, 2);
 
@@ -684,7 +684,7 @@ static int cp2101_tiocmget (struct usb_serial_port *port, struct file *file)
 {
        int control, result;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        cp2101_get_config(port, CP2101_CONTROL, &control, 1);
 
@@ -695,7 +695,7 @@ static int cp2101_tiocmget (struct usb_serial_port *port, struct file *file)
                |((control & CONTROL_RING)? TIOCM_RI  : 0)
                |((control & CONTROL_DCD) ? TIOCM_CD  : 0);
 
-       dbg("%s - control = 0x%.2x", __FUNCTION__, control);
+       dbg("%s - control = 0x%.2x", __func__, control);
 
        return result;
 }
@@ -704,12 +704,12 @@ static void cp2101_break_ctl (struct usb_serial_port *port, int break_state)
 {
        int state;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
        if (break_state == 0)
                state = BREAK_OFF;
        else
                state = BREAK_ON;
-       dbg("%s - turning break %s", __FUNCTION__,
+       dbg("%s - turning break %s", __func__,
                        state==BREAK_OFF ? "off" : "on");
        cp2101_set_config(port, CP2101_BREAK, &state, 2);
 }
@@ -725,7 +725,7 @@ static void cp2101_shutdown (struct usb_serial *serial)
 {
        int i;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /* Stop reads and writes on all ports */
        for (i=0; i < serial->num_ports; ++i) {
index 8d9b045aa7e84b1e90f8f5431d088320466079b7..c164e2cf2752169e65a063e861557cf1d107ba60 100644 (file)
@@ -90,9 +90,6 @@ static struct usb_serial_driver cyberjack_device = {
        .description =          "Reiner SCT Cyberjack USB card reader",
        .usb_driver =           &cyberjack_driver,
        .id_table =             id_table,
-       .num_interrupt_in =     1,
-       .num_bulk_in =          1,
-       .num_bulk_out =         1,
        .num_ports =            1,
        .attach =               cyberjack_startup,
        .shutdown =             cyberjack_shutdown,
@@ -119,7 +116,7 @@ static int cyberjack_startup (struct usb_serial *serial)
        struct cyberjack_private *priv;
        int i;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /* allocate the private data structure */
        priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL);
@@ -142,7 +139,7 @@ static int cyberjack_startup (struct usb_serial *serial)
                                        GFP_KERNEL);
                if (result)
                        err(" usb_submit_urb(read int) failed");
-               dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
+               dbg("%s - usb_submit_urb(int urb)", __func__);
        }
 
        return( 0 );
@@ -152,9 +149,9 @@ static void cyberjack_shutdown (struct usb_serial *serial)
 {
        int i;
        
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
-       for (i=0; i < serial->num_ports; ++i) {
+       for (i = 0; i < serial->num_ports; ++i) {
                usb_kill_urb(serial->port[i]->interrupt_in_urb);
                /* My special items, the standard routines free my urbs */
                kfree(usb_get_serial_port_data(serial->port[i]));
@@ -168,9 +165,9 @@ static int  cyberjack_open (struct usb_serial_port *port, struct file *filp)
        unsigned long flags;
        int result = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
-       dbg("%s - usb_clear_halt", __FUNCTION__ );
+       dbg("%s - usb_clear_halt", __func__ );
        usb_clear_halt(port->serial->dev, port->write_urb->pipe);
 
        /* force low_latency on so that our tty_push actually forces
@@ -191,7 +188,7 @@ static int  cyberjack_open (struct usb_serial_port *port, struct file *filp)
 
 static void cyberjack_close (struct usb_serial_port *port, struct file *filp)
 {
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (port->serial->dev) {
                /* shutdown any bulk reads that might be going on */
@@ -208,17 +205,17 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
        int result;
        int wrexpected;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (count == 0) {
-               dbg("%s - write request of 0 bytes", __FUNCTION__);
-               return (0);
+               dbg("%s - write request of 0 bytes", __func__);
+               return 0;
        }
 
        spin_lock_bh(&port->lock);
        if (port->write_urb_busy) {
                spin_unlock_bh(&port->lock);
-               dbg("%s - already writing", __FUNCTION__);
+               dbg("%s - already writing", __func__);
                return 0;
        }
        port->write_urb_busy = 1;
@@ -226,24 +223,24 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
 
        spin_lock_irqsave(&priv->lock, flags);
 
-       if( (count+priv->wrfilled)>sizeof(priv->wrbuf) ) {
+       if( (count+priv->wrfilled) > sizeof(priv->wrbuf) ) {
                /* To much data for buffer. Reset buffer. */
-               priv->wrfilled=0;
-               spin_unlock_irqrestore(&priv->lock, flags);
+               priv->wrfilled = 0;
                port->write_urb_busy = 0;
-               return (0);
+               spin_unlock_irqrestore(&priv->lock, flags);
+               return 0;
        }
 
        /* Copy data */
        memcpy (priv->wrbuf+priv->wrfilled, buf, count);
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count,
+       usb_serial_debug_data(debug, &port->dev, __func__, count,
                priv->wrbuf+priv->wrfilled);
        priv->wrfilled += count;
 
        if( priv->wrfilled >= 3 ) {
                wrexpected = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
-               dbg("%s - expected data: %d", __FUNCTION__, wrexpected);
+               dbg("%s - expected data: %d", __func__, wrexpected);
        } else {
                wrexpected = sizeof(priv->wrbuf);
        }
@@ -252,7 +249,7 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
                /* We have enough data to begin transmission */
                int length;
 
-               dbg("%s - transmitting data (frame 1)", __FUNCTION__);
+               dbg("%s - transmitting data (frame 1)", __func__);
                length = (wrexpected > port->bulk_out_size) ? port->bulk_out_size : wrexpected;
 
                memcpy (port->write_urb->transfer_buffer, priv->wrbuf, length );
@@ -270,23 +267,23 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
                /* send the data out the bulk port */
                result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
                if (result) {
-                       err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
+                       err("%s - failed submitting write urb, error %d", __func__, result);
                        /* Throw away data. No better idea what to do with it. */
-                       priv->wrfilled=0;
-                       priv->wrsent=0;
+                       priv->wrfilled = 0;
+                       priv->wrsent = 0;
                        spin_unlock_irqrestore(&priv->lock, flags);
                        port->write_urb_busy = 0;
                        return 0;
                }
 
-               dbg("%s - priv->wrsent=%d", __FUNCTION__,priv->wrsent);
-               dbg("%s - priv->wrfilled=%d", __FUNCTION__,priv->wrfilled);
+               dbg("%s - priv->wrsent=%d", __func__,priv->wrsent);
+               dbg("%s - priv->wrfilled=%d", __func__,priv->wrfilled);
 
                if( priv->wrsent>=priv->wrfilled ) {
-                       dbg("%s - buffer cleaned", __FUNCTION__);
+                       dbg("%s - buffer cleaned", __func__);
                        memset( priv->wrbuf, 0, sizeof(priv->wrbuf) );
-                       priv->wrfilled=0;
-                       priv->wrsent=0;
+                       priv->wrfilled = 0;
+                       priv->wrsent = 0;
                }
        }
 
@@ -297,27 +294,28 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
 
 static int cyberjack_write_room( struct usb_serial_port *port )
 {
+       /* FIXME: .... */
        return CYBERJACK_LOCAL_BUF_SIZE;
 }
 
 static void cyberjack_read_int_callback( struct urb *urb )
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *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);
+       dbg("%s - port %d", __func__, port->number);
 
        /* the urb might have been killed. */
        if (status)
                return;
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+       usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
 
        /* React only to interrupts signaling a bulk_in transfer */
-       if( (urb->actual_length==4) && (data[0]==0x01) ) {
+       if( (urb->actual_length == 4) && (data[0] == 0x01) ) {
                short old_rdtodo;
 
                /* This is a announcement of coming bulk_ins. */
@@ -336,7 +334,7 @@ static void cyberjack_read_int_callback( struct urb *urb )
                /* "+=" is probably more fault tollerant than "=" */
                priv->rdtodo += size;
 
-               dbg("%s - rdtodo: %d", __FUNCTION__, priv->rdtodo);
+               dbg("%s - rdtodo: %d", __func__, priv->rdtodo);
 
                spin_unlock(&priv->lock);
 
@@ -344,8 +342,8 @@ static void cyberjack_read_int_callback( struct urb *urb )
                        port->read_urb->dev = port->serial->dev;
                        result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
                        if( result )
-                               err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
-                       dbg("%s - usb_submit_urb(read urb)", __FUNCTION__);
+                               err("%s - failed resubmitting read urb, error %d", __func__, result);
+                       dbg("%s - usb_submit_urb(read urb)", __func__);
                }
        }
 
@@ -354,12 +352,12 @@ resubmit:
        result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
        if (result)
                err(" usb_submit_urb(read int) failed");
-       dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
+       dbg("%s - usb_submit_urb(int urb)", __func__);
 }
 
 static void cyberjack_read_bulk_callback (struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct cyberjack_private *priv = usb_get_serial_port_data(port);
        struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
@@ -367,18 +365,18 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
        int result;
        int status = urb->status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+       usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
        if (status) {
                dbg("%s - nonzero read bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        }
 
        tty = port->tty;
        if (!tty) {
-               dbg("%s - ignoring since device not open\n", __FUNCTION__);
+               dbg("%s - ignoring since device not open\n", __func__);
                return;
        }
        if (urb->actual_length) {
@@ -397,30 +395,30 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
 
        spin_unlock(&priv->lock);
 
-       dbg("%s - rdtodo: %d", __FUNCTION__, todo);
+       dbg("%s - rdtodo: %d", __func__, todo);
 
        /* Continue to read if we have still urbs to do. */
        if( todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/ ) {
                port->read_urb->dev = port->serial->dev;
                result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
                if (result)
-                       err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
-               dbg("%s - usb_submit_urb(read urb)", __FUNCTION__);
+                       err("%s - failed resubmitting read urb, error %d", __func__, result);
+               dbg("%s - usb_submit_urb(read urb)", __func__);
        }
 }
 
 static void cyberjack_write_bulk_callback (struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct cyberjack_private *priv = usb_get_serial_port_data(port);
        int status = urb->status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        port->write_urb_busy = 0;
        if (status) {
                dbg("%s - nonzero write bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        }
 
@@ -430,7 +428,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
        if( priv->wrfilled ) {
                int length, blksize, result;
 
-               dbg("%s - transmitting data (frame n)", __FUNCTION__);
+               dbg("%s - transmitting data (frame n)", __func__);
 
                length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ?
                        port->bulk_out_size : (priv->wrfilled - priv->wrsent);
@@ -451,23 +449,23 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
                /* send the data out the bulk port */
                result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
                if (result) {
-                       err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
+                       err("%s - failed submitting write urb, error %d", __func__, result);
                        /* Throw away data. No better idea what to do with it. */
-                       priv->wrfilled=0;
-                       priv->wrsent=0;
+                       priv->wrfilled = 0;
+                       priv->wrsent = 0;
                        goto exit;
                }
 
-               dbg("%s - priv->wrsent=%d", __FUNCTION__,priv->wrsent);
-               dbg("%s - priv->wrfilled=%d", __FUNCTION__,priv->wrfilled);
+               dbg("%s - priv->wrsent=%d", __func__,priv->wrsent);
+               dbg("%s - priv->wrfilled=%d", __func__,priv->wrfilled);
 
                blksize = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
 
                if( (priv->wrsent>=priv->wrfilled) || (priv->wrsent>=blksize) ) {
-                       dbg("%s - buffer cleaned", __FUNCTION__);
+                       dbg("%s - buffer cleaned", __func__);
                        memset( priv->wrbuf, 0, sizeof(priv->wrbuf) );
-                       priv->wrfilled=0;
-                       priv->wrsent=0;
+                       priv->wrfilled = 0;
+                       priv->wrsent = 0;
                }
        }
 
index 779d07851a4d820a4e32c372ed2e745798c82a27..32121794808dd5f964ca61143503bc92b6b5b016 100644 (file)
@@ -122,6 +122,11 @@ static struct usb_driver cypress_driver = {
        .no_dynamic_id =        1,
 };
 
+enum packet_format {
+       packet_format_1,  /* b0:status, b1:payload count */
+       packet_format_2   /* b0[7:3]:status, b0[2:0]:payload count */
+};
+
 struct cypress_private {
        spinlock_t lock;                   /* private lock */
        int chiptype;                      /* identifier of device, for quirks/etc */
@@ -139,8 +144,9 @@ struct cypress_private {
        __u8 current_status;               /* received from last read - info on dsr,cts,cd,ri,etc */
        __u8 current_config;               /* stores the current configuration byte */
        __u8 rx_flags;                     /* throttling - used from whiteheat/ftdi_sio */
+       enum packet_format pkt_fmt;        /* format to use for packet send / receive */
+       int get_cfg_unsafe;                /* If true, the CYPRESS_GET_CONFIG is unsafe */
        int baud_rate;                     /* stores current baud rate in integer form */
-       int cbr_mask;                      /* stores current baud rate in masked form */
        int isthrottled;                   /* if throttled, discard reads */
        wait_queue_head_t delta_msr_wait;  /* used for TIOCMIWAIT */
        char prev_status, diff_status;     /* used for TIOCMIWAIT */
@@ -176,9 +182,6 @@ static void cypress_unthrottle              (struct usb_serial_port *port);
 static void cypress_set_dead           (struct usb_serial_port *port);
 static void cypress_read_int_callback  (struct urb *urb);
 static void cypress_write_int_callback (struct urb *urb);
-/* baud helper functions */
-static int      mask_to_rate           (unsigned mask);
-static unsigned  rate_to_mask          (int rate);
 /* write buffer functions */
 static struct cypress_buf *cypress_buf_alloc(unsigned int size);
 static void              cypress_buf_free(struct cypress_buf *cb);
@@ -197,10 +200,6 @@ static struct usb_serial_driver cypress_earthmate_device = {
        .description =                  "DeLorme Earthmate USB",
        .usb_driver =                   &cypress_driver,
        .id_table =                     id_table_earthmate,
-       .num_interrupt_in =             1,
-       .num_interrupt_out =            1,
-       .num_bulk_in =                  NUM_DONT_CARE,
-       .num_bulk_out =                 NUM_DONT_CARE,
        .num_ports =                    1,
        .attach =                       cypress_earthmate_startup,
        .shutdown =                     cypress_shutdown,
@@ -227,10 +226,6 @@ static struct usb_serial_driver cypress_hidcom_device = {
        .description =                  "HID->COM RS232 Adapter",
        .usb_driver =                   &cypress_driver,
        .id_table =                     id_table_cyphidcomrs232,
-       .num_interrupt_in =             1,
-       .num_interrupt_out =            1,
-       .num_bulk_in =                  NUM_DONT_CARE,
-       .num_bulk_out =                 NUM_DONT_CARE,
        .num_ports =                    1,
        .attach =                       cypress_hidcom_startup,
        .shutdown =                     cypress_shutdown,
@@ -257,10 +252,6 @@ static struct usb_serial_driver cypress_ca42v2_device = {
        .description =                  "Nokia CA-42 V2 Adapter",
        .usb_driver =                   &cypress_driver,
        .id_table =                     id_table_nokiaca42v2,
-       .num_interrupt_in =             1,
-       .num_interrupt_out =            1,
-       .num_bulk_in =                  NUM_DONT_CARE,
-       .num_bulk_out =                 NUM_DONT_CARE,
        .num_ports =                    1,
        .attach =                       cypress_ca42v2_startup,
        .shutdown =                     cypress_shutdown,
@@ -284,16 +275,62 @@ static struct usb_serial_driver cypress_ca42v2_device = {
  *****************************************************************************/
 
 
+static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate)
+{
+       struct cypress_private *priv;
+       priv = usb_get_serial_port_data(port);
+
+       /*
+        * The general purpose firmware for the Cypress M8 allows for
+        * a maximum speed of 57600bps (I have no idea whether DeLorme
+        * chose to use the general purpose firmware or not), if you
+        * need to modify this speed setting for your own project
+        * please add your own chiptype and modify the code likewise.
+        * The Cypress HID->COM device will work successfully up to
+        * 115200bps (but the actual throughput is around 3kBps).
+        */
+       if (port->serial->dev->speed == USB_SPEED_LOW) {
+               /*
+                * Mike Isely <isely@pobox.com> 2-Feb-2008: The
+                * Cypress app note that describes this mechanism
+                * states the the low-speed part can't handle more
+                * than 800 bytes/sec, in which case 4800 baud is the
+                * safest speed for a part like that.
+                */
+               if (new_rate > 4800) {
+                       dbg("%s - failed setting baud rate, device incapable "
+                           "speed %d", __func__, new_rate);
+                       return -1;
+               }
+       }
+       switch (priv->chiptype) {
+       case CT_EARTHMATE:
+               if (new_rate <= 600) {
+                       /* 300 and 600 baud rates are supported under
+                        * the generic firmware, but are not used with
+                        * NMEA and SiRF protocols */
+                       dbg("%s - failed setting baud rate, unsupported speed "
+                           "of %d on Earthmate GPS", __func__, new_rate);
+                       return -1;
+               }
+               break;
+       default:
+               break;
+       }
+       return new_rate;
+}
+
+
 /* This function can either set or retrieve the current serial line settings */
-static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_mask, int data_bits, int stop_bits,
+static int cypress_serial_control (struct usb_serial_port *port, speed_t baud_rate, int data_bits, int stop_bits,
                                   int parity_enable, int parity_type, int reset, int cypress_request_type)
 {
        int new_baudrate = 0, retval = 0, tries = 0;
        struct cypress_private *priv;
-       __u8 feature_buffer[8];
+       __u8 feature_buffer[5];
        unsigned long flags;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
        
        priv = usb_get_serial_port_data(port);
 
@@ -302,58 +339,23 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
 
        switch(cypress_request_type) {
                case CYPRESS_SET_CONFIG:
-
-                       /*
-                        * The general purpose firmware for the Cypress M8 allows for a maximum speed
-                        * of 57600bps (I have no idea whether DeLorme chose to use the general purpose
-                        * firmware or not), if you need to modify this speed setting for your own
-                        * project please add your own chiptype and modify the code likewise.  The
-                        * Cypress HID->COM device will work successfully up to 115200bps (but the
-                        * actual throughput is around 3kBps).
-                        */
-                       if (baud_mask != priv->cbr_mask) {
-                               dbg("%s - baud rate is changing", __FUNCTION__);
-                               if ( priv->chiptype == CT_EARTHMATE ) {
-                                       /* 300 and 600 baud rates are supported under the generic firmware,
-                                        * but are not used with NMEA and SiRF protocols */
-                                       
-                                       if ( (baud_mask == B300) || (baud_mask == B600) ) {
-                                               err("%s - failed setting baud rate, unsupported speed",
-                                                   __FUNCTION__);
-                                               new_baudrate = priv->baud_rate;
-                                       } else if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
-                                               err("%s - failed setting baud rate, unsupported speed",
-                                                   __FUNCTION__);
-                                               new_baudrate = priv->baud_rate;
-                                       }
-                               } else if (priv->chiptype == CT_CYPHIDCOM) {
-                                       if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
-                                               err("%s - failed setting baud rate, unsupported speed",
-                                                   __FUNCTION__);
-                                               new_baudrate = priv->baud_rate;
-                                       }
-                               } else if (priv->chiptype == CT_CA42V2) {
-                                       if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
-                                               err("%s - failed setting baud rate, unsupported speed",
-                                                   __FUNCTION__);
-                                               new_baudrate = priv->baud_rate;
-                                       }
-                               } else if (priv->chiptype == CT_GENERIC) {
-                                       if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
-                                               err("%s - failed setting baud rate, unsupported speed",
-                                                   __FUNCTION__);
-                                               new_baudrate = priv->baud_rate;
-                                       }
-                               } else {
-                                       info("%s - please define your chiptype", __FUNCTION__);
-                                       new_baudrate = priv->baud_rate;
-                               }
-                       } else {  /* baud rate not changing, keep the old */
+                       new_baudrate = priv->baud_rate;
+                       /* 0 means 'Hang up' so doesn't change the true bit rate */
+                       if (baud_rate == 0)
                                new_baudrate = priv->baud_rate;
+                       /* Change of speed ? */
+                       else if (baud_rate != priv->baud_rate) {
+                               dbg("%s - baud rate is changing", __func__);
+                               retval = analyze_baud_rate(port, baud_rate);
+                               if (retval >=  0) {
+                                       new_baudrate = retval;
+                                       dbg("%s - New baud rate set to %d",
+                                           __func__, new_baudrate);
+                               }
                        }
-                       dbg("%s - baud rate is being sent as %d", __FUNCTION__, new_baudrate);
+                       dbg("%s - baud rate is being sent as %d", __func__, new_baudrate);
                        
-                       memset(feature_buffer, 0, 8);
+                       memset(feature_buffer, 0, sizeof(feature_buffer));
                        /* fill the feature_buffer with new configuration */
                        *((u_int32_t *)feature_buffer) = new_baudrate;
 
@@ -365,48 +367,65 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
                        /* 1 bit gap */
                        feature_buffer[4] |= (reset << 7);   /* assign reset at end of byte, 1 bit space */
                                
-                       dbg("%s - device is being sent this feature report:", __FUNCTION__);
-                       dbg("%s - %02X - %02X - %02X - %02X - %02X", __FUNCTION__, feature_buffer[0], feature_buffer[1],
+                       dbg("%s - device is being sent this feature report:", __func__);
+                       dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__, feature_buffer[0], feature_buffer[1],
                            feature_buffer[2], feature_buffer[3], feature_buffer[4]);
                        
                        do {
-                       retval = usb_control_msg (port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
-                                                 HID_REQ_SET_REPORT, USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
-                                                         0x0300, 0, feature_buffer, 8, 500);
+                               retval = usb_control_msg(port->serial->dev,
+                                               usb_sndctrlpipe(port->serial->dev, 0),
+                                               HID_REQ_SET_REPORT,
+                                               USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
+                                               0x0300, 0, feature_buffer,
+                                               sizeof(feature_buffer), 500);
 
                                if (tries++ >= 3)
                                        break;
 
-                       } while (retval != 8 && retval != -ENODEV);
+                       } while (retval != sizeof(feature_buffer) &&
+                                retval != -ENODEV);
 
-                       if (retval != 8) {
-                               err("%s - failed sending serial line settings - %d", __FUNCTION__, retval);
+                       if (retval != sizeof(feature_buffer)) {
+                               err("%s - failed sending serial line settings - %d", __func__, retval);
                                cypress_set_dead(port);
                        } else {
                                spin_lock_irqsave(&priv->lock, flags);
                                priv->baud_rate = new_baudrate;
-                               priv->cbr_mask = baud_mask;
                                priv->current_config = feature_buffer[4];
                                spin_unlock_irqrestore(&priv->lock, flags);
+                               /* If we asked for a speed change encode it */
+                               if (baud_rate)
+                                       tty_encode_baud_rate(port->tty,
+                                                       new_baudrate, new_baudrate);
                        }
                break;
                case CYPRESS_GET_CONFIG:
-                       dbg("%s - retreiving serial line settings", __FUNCTION__);
+                       if (priv->get_cfg_unsafe) {
+                               /* Not implemented for this device,
+                                  and if we try to do it we're likely
+                                  to crash the hardware. */
+                               return -ENOTTY;
+                       }
+                       dbg("%s - retreiving serial line settings", __func__);
                        /* set initial values in feature buffer */
-                       memset(feature_buffer, 0, 8);
+                       memset(feature_buffer, 0, sizeof(feature_buffer));
 
                        do {
-                       retval = usb_control_msg (port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0),
-                                                 HID_REQ_GET_REPORT, USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
-                                                         0x0300, 0, feature_buffer, 8, 500);
-                               
+                               retval = usb_control_msg(port->serial->dev,
+                                               usb_rcvctrlpipe(port->serial->dev, 0),
+                                               HID_REQ_GET_REPORT,
+                                               USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
+                                               0x0300, 0, feature_buffer,
+                                               sizeof(feature_buffer), 500);
+
                                if (tries++ >= 3)
                                        break;
 
-                       } while (retval != 5 && retval != -ENODEV);
+                       } while (retval != sizeof(feature_buffer) &&
+                                retval != -ENODEV);
 
-                       if (retval != 5) {
-                               err("%s - failed to retrieve serial line settings - %d", __FUNCTION__, retval);
+                       if (retval != sizeof(feature_buffer)) {
+                               err("%s - failed to retrieve serial line settings - %d", __func__, retval);
                                cypress_set_dead(port);
                                return retval;
                        } else {
@@ -415,9 +434,6 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
                                /* store the config in one byte, and later use bit masks to check values */
                                priv->current_config = feature_buffer[4];
                                priv->baud_rate = *((u_int32_t *)feature_buffer);
-                               
-                               if ( (priv->cbr_mask = rate_to_mask(priv->baud_rate)) == 0x40)
-                                       dbg("%s - failed setting the baud mask (not defined)", __FUNCTION__);
                                spin_unlock_irqrestore(&priv->lock, flags);
                        }
        }
@@ -447,51 +463,6 @@ static void cypress_set_dead(struct usb_serial_port *port)
 }
 
 
-/* given a baud mask, it will return integer baud on success */
-static int mask_to_rate (unsigned mask)
-{
-       int rate;
-
-       switch (mask) {
-               case B0: rate = 0; break;
-               case B300: rate = 300; break;
-               case B600: rate = 600; break;
-               case B1200: rate = 1200; break;
-               case B2400: rate = 2400; break;
-               case B4800: rate = 4800; break;
-               case B9600: rate = 9600; break;
-               case B19200: rate = 19200; break;
-               case B38400: rate = 38400; break;
-               case B57600: rate = 57600; break;
-               case B115200: rate = 115200; break;
-               default: rate = -1;
-       }
-
-       return rate;
-}
-
-
-static unsigned rate_to_mask (int rate)
-{
-       unsigned mask;
-
-       switch (rate) {
-               case 0: mask = B0; break;
-               case 300: mask = B300; break;
-               case 600: mask = B600; break;
-               case 1200: mask = B1200; break;
-               case 2400: mask = B2400; break;
-               case 4800: mask = B4800; break;
-               case 9600: mask = B9600; break;
-               case 19200: mask = B19200; break;
-               case 38400: mask = B38400; break;
-               case 57600: mask = B57600; break;
-               case 115200: mask = B115200; break;
-               default: mask = 0x40;
-       }
-
-       return mask;
-}
 /*****************************************************************************
  * Cypress serial driver functions
  *****************************************************************************/
@@ -502,7 +473,7 @@ static int generic_startup (struct usb_serial *serial)
        struct cypress_private *priv;
        struct usb_serial_port *port = serial->port[0];
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL);
        if (!priv)
@@ -523,17 +494,27 @@ static int generic_startup (struct usb_serial *serial)
        priv->line_control = 0;
        priv->termios_initialized = 0;
        priv->rx_flags = 0;
-       priv->cbr_mask = B300;
+       /* Default packet format setting is determined by packet size.
+          Anything with a size larger then 9 must have a separate
+          count field since the 3 bit count field is otherwise too
+          small.  Otherwise we can use the slightly more compact
+          format.  This is in accordance with the cypress_m8 serial
+          converter app note. */
+       if (port->interrupt_out_size > 9) {
+               priv->pkt_fmt = packet_format_1;
+       } else {
+               priv->pkt_fmt = packet_format_2;
+       }
        if (interval > 0) {
                priv->write_urb_interval = interval;
                priv->read_urb_interval = interval;
                dbg("%s - port %d read & write intervals forced to %d",
-                   __FUNCTION__,port->number,interval);
+                   __func__,port->number,interval);
        } else {
                priv->write_urb_interval = port->interrupt_out_urb->interval;
                priv->read_urb_interval = port->interrupt_in_urb->interval;
                dbg("%s - port %d intervals: read=%d write=%d",
-                   __FUNCTION__,port->number,
+                   __func__,port->number,
                    priv->read_urb_interval,priv->write_urb_interval);
        }
        usb_set_serial_port_data(port, priv);
@@ -545,17 +526,30 @@ static int generic_startup (struct usb_serial *serial)
 static int cypress_earthmate_startup (struct usb_serial *serial)
 {
        struct cypress_private *priv;
+       struct usb_serial_port *port = serial->port[0];
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        if (generic_startup(serial)) {
-               dbg("%s - Failed setting up port %d", __FUNCTION__,
-                               serial->port[0]->number);
+               dbg("%s - Failed setting up port %d", __func__,
+                               port->number);
                return 1;
        }
 
-       priv = usb_get_serial_port_data(serial->port[0]);
+       priv = usb_get_serial_port_data(port);
        priv->chiptype = CT_EARTHMATE;
+       /* All Earthmate devices use the separated-count packet
+          format!  Idiotic. */
+       priv->pkt_fmt = packet_format_1;
+       if (serial->dev->descriptor.idProduct != PRODUCT_ID_EARTHMATEUSB) {
+               /* The old original USB Earthmate seemed able to
+                  handle GET_CONFIG requests; everything they've
+                  produced since that time crashes if this command is
+                  attempted :-( */
+               dbg("%s - Marking this device as unsafe for GET_CONFIG "
+                   "commands", __func__);
+               priv->get_cfg_unsafe = !0;
+       }
 
        return 0;
 } /* cypress_earthmate_startup */
@@ -565,10 +559,10 @@ static int cypress_hidcom_startup (struct usb_serial *serial)
 {
        struct cypress_private *priv;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        if (generic_startup(serial)) {
-               dbg("%s - Failed setting up port %d", __FUNCTION__,
+               dbg("%s - Failed setting up port %d", __func__,
                                serial->port[0]->number);
                return 1;
        }
@@ -584,10 +578,10 @@ static int cypress_ca42v2_startup (struct usb_serial *serial)
 {
        struct cypress_private *priv;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        if (generic_startup(serial)) {
-               dbg("%s - Failed setting up port %d", __FUNCTION__,
+               dbg("%s - Failed setting up port %d", __func__,
                                serial->port[0]->number);
                return 1;
        }
@@ -603,7 +597,7 @@ static void cypress_shutdown (struct usb_serial *serial)
 {
        struct cypress_private *priv;
 
-       dbg ("%s - port %d", __FUNCTION__, serial->port[0]->number);
+       dbg ("%s - port %d", __func__, serial->port[0]->number);
 
        /* all open ports are closed at this point */
 
@@ -624,7 +618,7 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
        unsigned long flags;
        int result = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (!priv->comm_is_ok)
                return -EIO;
@@ -652,16 +646,16 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
        result = cypress_write(port, NULL, 0);
 
        if (result) {
-               dev_err(&port->dev, "%s - failed setting the control lines - error %d\n", __FUNCTION__, result);
+               dev_err(&port->dev, "%s - failed setting the control lines - error %d\n", __func__, result);
                return result;
        } else
-               dbg("%s - success setting the control lines", __FUNCTION__);    
+               dbg("%s - success setting the control lines", __func__);
 
        cypress_set_termios(port, &priv->tmp_termios);
 
        /* setup the port and start reading from the device */
        if(!port->interrupt_in_urb){
-               err("%s - interrupt_in_urb is empty!", __FUNCTION__);
+               err("%s - interrupt_in_urb is empty!", __func__);
                return(-1);
        }
 
@@ -672,7 +666,7 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
        result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 
        if (result){
-               dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
+               dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
                cypress_set_dead(port);
        }
 
@@ -688,7 +682,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
        long timeout;
        wait_queue_t wait;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /* wait for data to drain from buffer */
        spin_lock_irq(&priv->lock);
@@ -726,7 +720,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
                timeout = 2*HZ;
        schedule_timeout_interruptible(timeout);
 
-       dbg("%s - stopping urbs", __FUNCTION__);
+       dbg("%s - stopping urbs", __func__);
        usb_kill_urb (port->interrupt_in_urb);
        usb_kill_urb (port->interrupt_out_urb);
 
@@ -755,7 +749,7 @@ static int cypress_write(struct usb_serial_port *port, const unsigned char *buf,
        struct cypress_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
        
-       dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
+       dbg("%s - port %d, %d bytes", __func__, port->number, count);
 
        /* line control commands, which need to be executed immediately,
           are not put into the buffer for obvious reasons.
@@ -788,12 +782,12 @@ static void cypress_send(struct usb_serial_port *port)
        if (!priv->comm_is_ok)
                return;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
-       dbg("%s - interrupt out size is %d", __FUNCTION__, port->interrupt_out_size);
+       dbg("%s - port %d", __func__, port->number);
+       dbg("%s - interrupt out size is %d", __func__, port->interrupt_out_size);
        
        spin_lock_irqsave(&priv->lock, flags);
        if (priv->write_urb_in_use) {
-               dbg("%s - can't write, urb in use", __FUNCTION__);
+               dbg("%s - can't write, urb in use", __func__);
                spin_unlock_irqrestore(&priv->lock, flags);
                return;
        }
@@ -803,21 +797,18 @@ static void cypress_send(struct usb_serial_port *port)
        memset(port->interrupt_out_urb->transfer_buffer, 0, port->interrupt_out_size);
 
        spin_lock_irqsave(&priv->lock, flags);
-       switch (port->interrupt_out_size) {
-               case 32:
-                       /* this is for the CY7C64013... */
-                       offset = 2;
-                       port->interrupt_out_buffer[0] = priv->line_control;
-                       break;
-               case 8:
-                       /* this is for the CY7C63743... */
-                       offset = 1;
-                       port->interrupt_out_buffer[0] = priv->line_control;
-                       break;
-               default:
-                       dbg("%s - wrong packet size", __FUNCTION__);
-                       spin_unlock_irqrestore(&priv->lock, flags);
-                       return;
+       switch (priv->pkt_fmt) {
+       default:
+       case packet_format_1:
+               /* this is for the CY7C64013... */
+               offset = 2;
+               port->interrupt_out_buffer[0] = priv->line_control;
+               break;
+       case packet_format_2:
+               /* this is for the CY7C63743... */
+               offset = 1;
+               port->interrupt_out_buffer[0] = priv->line_control;
+               break;
        }
 
        if (priv->line_control & CONTROL_RESET)
@@ -825,7 +816,7 @@ static void cypress_send(struct usb_serial_port *port)
 
        if (priv->cmd_ctrl) {
                priv->cmd_count++;
-               dbg("%s - line control command being issued", __FUNCTION__);
+               dbg("%s - line control command being issued", __func__);
                spin_unlock_irqrestore(&priv->lock, flags);
                goto send;
        } else
@@ -838,15 +829,16 @@ static void cypress_send(struct usb_serial_port *port)
                return;
        }
 
-       switch (port->interrupt_out_size) {
-               case 32:
-                       port->interrupt_out_buffer[1] = count;
-                       break;
-               case 8:
-                       port->interrupt_out_buffer[0] |= count;
+       switch (priv->pkt_fmt) {
+       default:
+       case packet_format_1:
+               port->interrupt_out_buffer[1] = count;
+               break;
+       case packet_format_2:
+               port->interrupt_out_buffer[0] |= count;
        }
 
-       dbg("%s - count is %d", __FUNCTION__, count);
+       dbg("%s - count is %d", __func__, count);
 
 send:
        spin_lock_irqsave(&priv->lock, flags);
@@ -856,9 +848,10 @@ send:
        if (priv->cmd_ctrl)
                actual_size = 1;
        else
-               actual_size = count + (port->interrupt_out_size == 32 ? 2 : 1);
-       
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, port->interrupt_out_size,
+               actual_size = count +
+                             (priv->pkt_fmt == packet_format_1 ? 2 : 1);
+
+       usb_serial_debug_data(debug, &port->dev, __func__, port->interrupt_out_size,
                              port->interrupt_out_urb->transfer_buffer);
 
        usb_fill_int_urb(port->interrupt_out_urb, port->serial->dev,
@@ -867,7 +860,7 @@ send:
                cypress_write_int_callback, port, priv->write_urb_interval);
        result = usb_submit_urb (port->interrupt_out_urb, GFP_ATOMIC);
        if (result) {
-               dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__,
+               dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__,
                        result);
                priv->write_urb_in_use = 0;
                cypress_set_dead(port);
@@ -891,13 +884,13 @@ static int cypress_write_room(struct usb_serial_port *port)
        int room = 0;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
        room = cypress_buf_space_avail(priv->buf);
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       dbg("%s - returns %d", __FUNCTION__, room);
+       dbg("%s - returns %d", __func__, room);
        return room;
 }
 
@@ -909,7 +902,7 @@ static int cypress_tiocmget (struct usb_serial_port *port, struct file *file)
        unsigned int result = 0;
        unsigned long flags;
        
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
        control = priv->line_control;
@@ -923,7 +916,7 @@ static int cypress_tiocmget (struct usb_serial_port *port, struct file *file)
                | ((status & UART_RI)         ? TIOCM_RI  : 0)
                | ((status & UART_CD)         ? TIOCM_CD  : 0);
 
-       dbg("%s - result = %x", __FUNCTION__, result);
+       dbg("%s - result = %x", __func__, result);
 
        return result;
 }
@@ -935,7 +928,7 @@ static int cypress_tiocmset (struct usb_serial_port *port, struct file *file,
        struct cypress_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
        
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
        if (set & TIOCM_RTS)
@@ -946,9 +939,9 @@ static int cypress_tiocmset (struct usb_serial_port *port, struct file *file,
                priv->line_control &= ~CONTROL_RTS;
        if (clear & TIOCM_DTR)
                priv->line_control &= ~CONTROL_DTR;
+       priv->cmd_ctrl = 1;
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       priv->cmd_ctrl = 1;
        return cypress_write(port, NULL, 0);
 }
 
@@ -957,23 +950,9 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi
 {
        struct cypress_private *priv = usb_get_serial_port_data(port);
 
-       dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
+       dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
 
        switch (cmd) {
-               case TIOCGSERIAL:
-                       if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct ktermios))) {
-                               return -EFAULT;
-                       }
-                       return (0);
-                       break;
-               case TIOCSSERIAL:
-                       if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct ktermios))) {
-                               return -EFAULT;
-                       }
-                       /* here we need to call cypress_set_termios to invoke the new settings */
-                       cypress_set_termios(port, &priv->tmp_termios);
-                       return (0);
-                       break;
                /* This code comes from drivers/char/serial.c and ftdi_sio.c */
                case TIOCMIWAIT:
                        while (priv != NULL) {
@@ -1009,7 +988,7 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi
                        break;
        }
 
-       dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __FUNCTION__, cmd);
+       dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __func__, cmd);
 
        return -ENOIOCTLCMD;
 } /* cypress_ioctl */
@@ -1021,18 +1000,14 @@ static void cypress_set_termios (struct usb_serial_port *port,
        struct cypress_private *priv = usb_get_serial_port_data(port);
        struct tty_struct *tty;
        int data_bits, stop_bits, parity_type, parity_enable;
-       unsigned cflag, iflag, baud_mask;
+       unsigned cflag, iflag;
        unsigned long flags;
        __u8 oldlines;
        int linechange = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        tty = port->tty;
-       if ((!tty) || (!tty->termios)) {
-               dbg("%s - no tty structures", __FUNCTION__);
-               return;
-       }
 
        spin_lock_irqsave(&priv->lock, flags);
        if (!priv->termios_initialized) {
@@ -1040,40 +1015,37 @@ static void cypress_set_termios (struct usb_serial_port *port,
                        *(tty->termios) = tty_std_termios;
                        tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL |
                                CLOCAL;
+                       tty->termios->c_ispeed = 4800;
+                       tty->termios->c_ospeed = 4800;
                } else if (priv->chiptype == CT_CYPHIDCOM) {
                        *(tty->termios) = tty_std_termios;
                        tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL |
                                CLOCAL;
+                       tty->termios->c_ispeed = 9600;
+                       tty->termios->c_ospeed = 9600;
                } else if (priv->chiptype == CT_CA42V2) {
                        *(tty->termios) = tty_std_termios;
                        tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL |
                                CLOCAL;
+                       tty->termios->c_ispeed = 9600;
+                       tty->termios->c_ospeed = 9600;
                }
                priv->termios_initialized = 1;
        }
        spin_unlock_irqrestore(&priv->lock, flags);
 
+       /* Unsupported features need clearing */
+       tty->termios->c_cflag &= ~(CMSPAR|CRTSCTS);
+
        cflag = tty->termios->c_cflag;
        iflag = tty->termios->c_iflag;
 
        /* check if there are new settings */
        if (old_termios) {
-               if ((cflag != old_termios->c_cflag) ||
-                       (RELEVANT_IFLAG(iflag) !=
-                        RELEVANT_IFLAG(old_termios->c_iflag))) {
-                       dbg("%s - attempting to set new termios settings",
-                                       __FUNCTION__);
-                       /* should make a copy of this in case something goes
-                        * wrong in the function, we can restore it */
-                       spin_lock_irqsave(&priv->lock, flags);
-                       priv->tmp_termios = *(tty->termios);
-                       spin_unlock_irqrestore(&priv->lock, flags);
-               } else {
-                       dbg("%s - nothing to do, exiting", __FUNCTION__);
-                       return;
-               }
-       } else
-               return;
+               spin_lock_irqsave(&priv->lock, flags);
+               priv->tmp_termios = *(tty->termios);
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
 
        /* set number of data bits, parity, stop bits */
        /* when parity is disabled the parity type bit is ignored */
@@ -1104,7 +1076,7 @@ static void cypress_set_termios (struct usb_serial_port *port,
                                break;
                        default:
                                err("%s - CSIZE was set, but not CS5-CS8",
-                                               __FUNCTION__);
+                                               __func__);
                                data_bits = 3;
                }
        } else
@@ -1114,54 +1086,17 @@ static void cypress_set_termios (struct usb_serial_port *port,
        oldlines = priv->line_control;
        if ((cflag & CBAUD) == B0) {
                /* drop dtr and rts */
-               dbg("%s - dropping the lines, baud rate 0bps", __FUNCTION__);
-               baud_mask = B0;
+               dbg("%s - dropping the lines, baud rate 0bps", __func__);
                priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
-       } else {
-               baud_mask = (cflag & CBAUD);
-               switch(baud_mask) {
-                       case B300:
-                               dbg("%s - setting baud 300bps", __FUNCTION__);
-                               break;
-                       case B600:
-                               dbg("%s - setting baud 600bps", __FUNCTION__);
-                               break;
-                       case B1200:
-                               dbg("%s - setting baud 1200bps", __FUNCTION__);
-                               break;
-                       case B2400:
-                               dbg("%s - setting baud 2400bps", __FUNCTION__);
-                               break;
-                       case B4800:
-                               dbg("%s - setting baud 4800bps", __FUNCTION__);
-                               break;
-                       case B9600:
-                               dbg("%s - setting baud 9600bps", __FUNCTION__);
-                               break;
-                       case B19200:
-                               dbg("%s - setting baud 19200bps", __FUNCTION__);
-                               break;
-                       case B38400:
-                               dbg("%s - setting baud 38400bps", __FUNCTION__);
-                               break;
-                       case B57600:
-                               dbg("%s - setting baud 57600bps", __FUNCTION__);
-                               break;
-                       case B115200:
-                               dbg("%s - setting baud 115200bps", __FUNCTION__);
-                               break;
-                       default:
-                               dbg("%s - unknown masked baud rate", __FUNCTION__);
-               }
+       } else
                priv->line_control = (CONTROL_DTR | CONTROL_RTS);
-       }
        spin_unlock_irqrestore(&priv->lock, flags);
 
        dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, "
-                       "%d data_bits (+5)", __FUNCTION__, stop_bits,
+                       "%d data_bits (+5)", __func__, stop_bits,
                        parity_enable, parity_type, data_bits);
 
-       cypress_serial_control(port, baud_mask, data_bits, stop_bits,
+       cypress_serial_control(port, tty_get_baud_rate(tty), data_bits, stop_bits,
                        parity_enable, parity_type, 0, CYPRESS_SET_CONFIG);
 
        /* we perform a CYPRESS_GET_CONFIG so that the current settings are
@@ -1219,13 +1154,13 @@ static int cypress_chars_in_buffer(struct usb_serial_port *port)
        int chars = 0;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
        
        spin_lock_irqsave(&priv->lock, flags);
        chars = cypress_buf_data_avail(priv->buf);
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       dbg("%s - returns %d", __FUNCTION__, chars);
+       dbg("%s - returns %d", __func__, chars);
        return chars;
 }
 
@@ -1235,7 +1170,7 @@ static void cypress_throttle (struct usb_serial_port *port)
        struct cypress_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
        priv->rx_flags = THROTTLED;
@@ -1249,7 +1184,7 @@ static void cypress_unthrottle (struct usb_serial_port *port)
        int actually_throttled, result;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
        actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
@@ -1265,7 +1200,7 @@ static void cypress_unthrottle (struct usb_serial_port *port)
                result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
                if (result) {
                        dev_err(&port->dev, "%s - failed submitting read urb, "
-                                       "error %d\n", __FUNCTION__, result);
+                                       "error %d\n", __func__, result);
                        cypress_set_dead(port);
                }
        }
@@ -1274,7 +1209,7 @@ static void cypress_unthrottle (struct usb_serial_port *port)
 
 static void cypress_read_int_callback(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct cypress_private *priv = usb_get_serial_port_data(port);
        struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
@@ -1286,7 +1221,7 @@ static void cypress_read_int_callback(struct urb *urb)
        int i = 0;
        int status = urb->status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        switch (status) {
        case 0: /* success */
@@ -1302,14 +1237,14 @@ 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__, status);
+                       __func__, status);
                cypress_set_dead(port);
                return;
        }
 
        spin_lock_irqsave(&priv->lock, flags);
        if (priv->rx_flags & THROTTLED) {
-               dbg("%s - now throttling", __FUNCTION__);
+               dbg("%s - now throttling", __func__);
                priv->rx_flags |= ACTUALLY_THROTTLED;
                spin_unlock_irqrestore(&priv->lock, flags);
                return;
@@ -1318,48 +1253,48 @@ static void cypress_read_int_callback(struct urb *urb)
 
        tty = port->tty;
        if (!tty) {
-               dbg("%s - bad tty pointer - exiting", __FUNCTION__);
+               dbg("%s - bad tty pointer - exiting", __func__);
                return;
        }
 
        spin_lock_irqsave(&priv->lock, flags);
-       switch(urb->actual_length) {
-               case 32:
-                       /* This is for the CY7C64013... */
-                       priv->current_status = data[0] & 0xF8;
-                       bytes = data[1] + 2;
-                       i = 2;
-                       if (bytes > 2)
-                               havedata = 1;
-                       break;
-               case 8:
-                       /* This is for the CY7C63743... */
-                       priv->current_status = data[0] & 0xF8;
-                       bytes = (data[0] & 0x07) + 1;
-                       i = 1;
-                       if (bytes > 1)
-                               havedata = 1;
-                       break;
-               default:
-                       dbg("%s - wrong packet size - received %d bytes",
-                                       __FUNCTION__, urb->actual_length);
-                       spin_unlock_irqrestore(&priv->lock, flags);
-                       goto continue_read;
+       result = urb->actual_length;
+       switch (priv->pkt_fmt) {
+       default:
+       case packet_format_1:
+               /* This is for the CY7C64013... */
+               priv->current_status = data[0] & 0xF8;
+               bytes = data[1] + 2;
+               i = 2;
+               if (bytes > 2)
+                       havedata = 1;
+               break;
+       case packet_format_2:
+               /* This is for the CY7C63743... */
+               priv->current_status = data[0] & 0xF8;
+               bytes = (data[0] & 0x07) + 1;
+               i = 1;
+               if (bytes > 1)
+                       havedata = 1;
+               break;
        }
        spin_unlock_irqrestore(&priv->lock, flags);
+       if (result < bytes) {
+               dbg("%s - wrong packet size - received %d bytes but packet "
+                   "said %d bytes", __func__, result, bytes);
+               goto continue_read;
+       }
 
-       usb_serial_debug_data (debug, &port->dev, __FUNCTION__,
+       usb_serial_debug_data (debug, &port->dev, __func__,
                        urb->actual_length, data);
 
        spin_lock_irqsave(&priv->lock, flags);
        /* check to see if status has changed */
-       if (priv != NULL) {
-               if (priv->current_status != priv->prev_status) {
-                       priv->diff_status |= priv->current_status ^
-                               priv->prev_status;
-                       wake_up_interruptible(&priv->delta_msr_wait);
-                       priv->prev_status = priv->current_status;
-               }
+       if (priv->current_status != priv->prev_status) {
+               priv->diff_status |= priv->current_status ^
+                       priv->prev_status;
+               wake_up_interruptible(&priv->delta_msr_wait);
+               priv->prev_status = priv->current_status;
        }
        spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -1367,7 +1302,7 @@ static void cypress_read_int_callback(struct urb *urb)
         * though */
        if (tty && !(tty->termios->c_cflag & CLOCAL) &&
                        !(priv->current_status & UART_CD)) {
-               dbg("%s - calling hangup", __FUNCTION__);
+               dbg("%s - calling hangup", __func__);
                tty_hangup(tty);
                goto continue_read;
        }
@@ -1380,7 +1315,7 @@ static void cypress_read_int_callback(struct urb *urb)
        if (priv->current_status & CYP_ERROR) {
                spin_unlock_irqrestore(&priv->lock, flags);
                tty_flag = TTY_PARITY;
-               dbg("%s - Parity Error detected", __FUNCTION__);
+               dbg("%s - Parity Error detected", __func__);
        } else
                spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -1414,7 +1349,7 @@ continue_read:
                result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
                if (result) {
                        dev_err(&urb->dev->dev, "%s - failed resubmitting "
-                                       "read urb, error %d\n", __FUNCTION__,
+                                       "read urb, error %d\n", __func__,
                                        result);
                        cypress_set_dead(port);
                }
@@ -1426,12 +1361,12 @@ continue_read:
 
 static void cypress_write_int_callback(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *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);
+       dbg("%s - port %d", __func__, port->number);
 
        switch (status) {
                case 0:
@@ -1442,7 +1377,7 @@ static void cypress_write_int_callback(struct urb *urb)
                case -ESHUTDOWN:
                        /* this urb is terminated, clean up */
                        dbg("%s - urb shutting down with status: %d",
-                           __FUNCTION__, status);
+                           __func__, status);
                        priv->write_urb_in_use = 0;
                        return;
                case -EPIPE: /* no break needed; clear halt and resubmit */
@@ -1451,19 +1386,19 @@ static void cypress_write_int_callback(struct urb *urb)
                        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__, status);
+                           __func__, status);
                        port->interrupt_out_urb->transfer_buffer_length = 1;
                        port->interrupt_out_urb->dev = port->serial->dev;
                        result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
                        if (!result)
                                return;
                        dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n",
-                               __FUNCTION__, result);
+                               __func__, result);
                        cypress_set_dead(port);
                        break;
                default:
                        dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n",
-                               __FUNCTION__, status);
+                               __func__, status);
                        cypress_set_dead(port);
                        break;
        }
@@ -1668,7 +1603,7 @@ static int __init cypress_init(void)
 {
        int retval;
        
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
        
        retval = usb_serial_register(&cypress_earthmate_device);
        if (retval)
@@ -1699,7 +1634,7 @@ failed_em_register:
 
 static void __exit cypress_exit (void)
 {
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        usb_deregister (&cypress_driver);
        usb_serial_deregister (&cypress_earthmate_device);
index 5f9c6e46bee5712effaed0346d7ae5a31e305d60..d17d1645714fbb2ab9ee7cf391181b62e869275a 100644 (file)
@@ -508,9 +508,6 @@ static struct usb_serial_driver digi_acceleport_2_device = {
        .description =                  "Digi 2 port USB adapter",
        .usb_driver =                   &digi_driver,
        .id_table =                     id_table_2,
-       .num_interrupt_in =             0,
-       .num_bulk_in =                  4,
-       .num_bulk_out =                 4,
        .num_ports =                    3,
        .open =                         digi_open,
        .close =                        digi_close,
@@ -538,9 +535,6 @@ static struct usb_serial_driver digi_acceleport_4_device = {
        .description =                  "Digi 4 port USB adapter",
        .usb_driver =                   &digi_driver,
        .id_table =                     id_table_4,
-       .num_interrupt_in =             0,
-       .num_bulk_in =                  5,
-       .num_bulk_out =                 5,
        .num_ports =                    4,
        .open =                         digi_open,
        .close =                        digi_close,
@@ -665,7 +659,7 @@ static int digi_write_oob_command(struct usb_serial_port *port,
        }
        spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags);
        if (ret)
-               err("%s: usb_submit_urb failed, ret=%d", __FUNCTION__, ret);
+               err("%s: usb_submit_urb failed, ret=%d", __func__, ret);
        return ret;
 
 }
@@ -746,7 +740,7 @@ static int digi_write_inb_command(struct usb_serial_port *port,
 
        if (ret)
                err("%s: usb_submit_urb failed, ret=%d, port=%d",
-                       __FUNCTION__, ret, priv->dp_port_num);
+                       __func__, ret, priv->dp_port_num);
        return ret;
 }
 
@@ -810,7 +804,7 @@ static int digi_set_modem_signals(struct usb_serial_port *port,
        spin_unlock(&port_priv->dp_port_lock);
        spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags);
        if (ret)
-               err("%s: usb_submit_urb failed, ret=%d", __FUNCTION__, ret);
+               err("%s: usb_submit_urb failed, ret=%d", __func__, ret);
        return ret;
 }
 
@@ -903,7 +897,7 @@ static void digi_rx_unthrottle(struct usb_serial_port *port)
 
        if (ret)
                err("%s: usb_submit_urb failed, ret=%d, port=%d",
-                       __FUNCTION__, ret, priv->dp_port_num);
+                       __func__, ret, priv->dp_port_num);
 }
 
 
@@ -1113,7 +1107,7 @@ static int digi_tiocmget(struct usb_serial_port *port, struct file *file)
        unsigned int val;
        unsigned long flags;
 
-       dbg("%s: TOP: port=%d", __FUNCTION__, priv->dp_port_num);
+       dbg("%s: TOP: port=%d", __func__, priv->dp_port_num);
 
        spin_lock_irqsave(&priv->dp_port_lock, flags);
        val = priv->dp_modem_signals;
@@ -1129,7 +1123,7 @@ static int digi_tiocmset(struct usb_serial_port *port, struct file *file,
        unsigned int val;
        unsigned long flags;
 
-       dbg("%s: TOP: port=%d", __FUNCTION__, priv->dp_port_num);
+       dbg("%s: TOP: port=%d", __func__, priv->dp_port_num);
 
        spin_lock_irqsave(&priv->dp_port_lock, flags);
        val = (priv->dp_modem_signals & ~clear) | set;
@@ -1224,7 +1218,7 @@ static int digi_write(struct usb_serial_port *port, const unsigned char *buf, in
        spin_unlock_irqrestore(&priv->dp_port_lock, flags);
        if (ret < 0)
                err("%s: usb_submit_urb failed, ret=%d, port=%d",
-                       __FUNCTION__, ret, priv->dp_port_num);
+                       __func__, ret, priv->dp_port_num);
        dbg("digi_write: returning %d", ret);
        return ret;
 
@@ -1233,7 +1227,7 @@ static int digi_write(struct usb_serial_port *port, const unsigned char *buf, in
 static void digi_write_bulk_callback(struct urb *urb)
 {
 
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct usb_serial *serial;
        struct digi_port *priv;
        struct digi_serial *serial_priv;
@@ -1245,13 +1239,13 @@ static void digi_write_bulk_callback(struct urb *urb)
        /* 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__, status);
+                   __func__, 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__, status);
+                   __func__, status);
                return;
        }
 
@@ -1292,7 +1286,7 @@ static void digi_write_bulk_callback(struct urb *urb)
        spin_unlock(&priv->dp_port_lock);
        if (ret)
                err("%s: usb_submit_urb failed, ret=%d, port=%d",
-                       __FUNCTION__, ret, priv->dp_port_num);
+                       __func__, ret, priv->dp_port_num);
 }
 
 static int digi_write_room(struct usb_serial_port *port)
@@ -1521,7 +1515,7 @@ static int digi_startup_device(struct usb_serial *serial)
                port->write_urb->dev = port->serial->dev;
                if ((ret = usb_submit_urb(port->read_urb, GFP_KERNEL)) != 0) {
                        err("%s: usb_submit_urb failed, ret=%d, port=%d",
-                                       __FUNCTION__, ret, i);
+                                       __func__, ret, i);
                        break;
                }
        }
@@ -1611,7 +1605,7 @@ static void digi_shutdown(struct usb_serial *serial)
 
 static void digi_read_bulk_callback(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct digi_port *priv;
        struct digi_serial *serial_priv;
        int ret;
@@ -1622,20 +1616,20 @@ static void digi_read_bulk_callback(struct urb *urb)
        /* 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__, status);
+                   __func__, 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__, status);
+                       __func__, status);
                return;
        }
 
        /* do not resubmit urb if it has any status error */
        if (status) {
                err("%s: nonzero read bulk status: status=%d, port=%d",
-                   __FUNCTION__, status, priv->dp_port_num);
+                   __func__, status, priv->dp_port_num);
                return;
        }
 
@@ -1652,7 +1646,7 @@ static void digi_read_bulk_callback(struct urb *urb)
        urb->dev = port->serial->dev;
        if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
                err("%s: failed resubmitting urb, ret=%d, port=%d",
-                   __FUNCTION__, ret, priv->dp_port_num);
+                   __func__, ret, priv->dp_port_num);
        }
 
 }
@@ -1670,7 +1664,7 @@ static void digi_read_bulk_callback(struct urb *urb)
 static int digi_read_inb_callback(struct urb *urb)
 {
 
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct tty_struct *tty = port->tty;
        struct digi_port *priv = usb_get_serial_port_data(port);
        int opcode = ((unsigned char *)urb->transfer_buffer)[0];
@@ -1690,7 +1684,7 @@ static int digi_read_inb_callback(struct urb *urb)
        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__, status, priv->dp_port_num,
+                   "status=%d", __func__, status, priv->dp_port_num,
                    opcode, len, urb->actual_length, port_status);
                return -1;
        }
@@ -1739,9 +1733,9 @@ static int digi_read_inb_callback(struct urb *urb)
        spin_unlock(&priv->dp_port_lock);
 
        if (opcode == DIGI_CMD_RECEIVE_DISABLE)
-               dbg("%s: got RECEIVE_DISABLE", __FUNCTION__);
+               dbg("%s: got RECEIVE_DISABLE", __func__);
        else if (opcode != DIGI_CMD_RECEIVE_DATA)
-               dbg("%s: unknown opcode: %d", __FUNCTION__, opcode);
+               dbg("%s: unknown opcode: %d", __func__, opcode);
 
        return(throttled ? 1 : 0);
 
@@ -1760,7 +1754,7 @@ static int digi_read_inb_callback(struct urb *urb)
 static int digi_read_oob_callback(struct urb *urb)
 {
 
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct usb_serial *serial = port->serial;
        struct digi_port *priv = usb_get_serial_port_data(port);
        int opcode, line, status, val;
index a5c8e1e17ea5ff42c0280b7e0b444e42694ac390..c5ec309a3cb1434014a1f4f8df801d047099633f 100644 (file)
@@ -118,9 +118,6 @@ static struct usb_serial_driver empeg_device = {
        },
        .id_table =             id_table,
        .usb_driver =           &empeg_driver,
-       .num_interrupt_in =     0,
-       .num_bulk_in =          1,
-       .num_bulk_out =         1,
        .num_ports =            1,
        .open =                 empeg_open,
        .close =                empeg_close,
@@ -153,7 +150,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
        struct usb_serial *serial = port->serial;
        int result = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /* Force default termio settings */
        empeg_set_termios (port, NULL) ;
@@ -175,7 +172,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
        result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 
        if (result)
-               dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
+               dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
 
        return result;
 }
@@ -183,7 +180,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
 
 static void empeg_close (struct usb_serial_port *port, struct file * filp)
 {
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /* shutdown our bulk read */
        usb_kill_urb(port->read_urb);
@@ -203,7 +200,7 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
        int bytes_sent = 0;
        int transfer_size;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        while (count > 0) {
 
@@ -222,14 +219,14 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
                spin_unlock_irqrestore (&write_urb_pool_lock, flags);
 
                if (urb == NULL) {
-                       dbg("%s - no more free urbs", __FUNCTION__);
+                       dbg("%s - no more free urbs", __func__);
                        goto exit;
                }
 
                if (urb->transfer_buffer == NULL) {
                        urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
                        if (urb->transfer_buffer == NULL) {
-                               dev_err(&port->dev, "%s no more kernel memory...\n", __FUNCTION__);
+                               dev_err(&port->dev, "%s no more kernel memory...\n", __func__);
                                goto exit;
                        }
                }
@@ -238,7 +235,7 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
 
                memcpy (urb->transfer_buffer, current_position, transfer_size);
 
-               usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size, urb->transfer_buffer);
+               usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, urb->transfer_buffer);
 
                /* build up our urb */
                usb_fill_bulk_urb (
@@ -254,7 +251,7 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
                /* 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);
+                       dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", __func__, status);
                        bytes_sent = status;
                        break;
                }
@@ -278,7 +275,7 @@ static int empeg_write_room (struct usb_serial_port *port)
        int i;
        int room = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave (&write_urb_pool_lock, flags);
 
@@ -291,7 +288,7 @@ static int empeg_write_room (struct usb_serial_port *port)
 
        spin_unlock_irqrestore (&write_urb_pool_lock, flags);
 
-       dbg("%s - returns %d", __FUNCTION__, room);
+       dbg("%s - returns %d", __func__, room);
 
        return (room);
 
@@ -304,7 +301,7 @@ static int empeg_chars_in_buffer (struct usb_serial_port *port)
        int i;
        int chars = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave (&write_urb_pool_lock, flags);
 
@@ -317,7 +314,7 @@ static int empeg_chars_in_buffer (struct usb_serial_port *port)
 
        spin_unlock_irqrestore (&write_urb_pool_lock, flags);
 
-       dbg("%s - returns %d", __FUNCTION__, chars);
+       dbg("%s - returns %d", __func__, chars);
 
        return (chars);
 
@@ -329,11 +326,11 @@ static void empeg_write_bulk_callback (struct urb *urb)
        struct usb_serial_port *port = urb->context;
        int status = urb->status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (status) {
                dbg("%s - nonzero write bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        }
 
@@ -343,21 +340,21 @@ static void empeg_write_bulk_callback (struct urb *urb)
 
 static void empeg_read_bulk_callback (struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
        int result;
        int status = urb->status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (status) {
                dbg("%s - nonzero read bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+       usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
 
        tty = port->tty;
 
@@ -382,7 +379,7 @@ static void empeg_read_bulk_callback (struct urb *urb)
        result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 
        if (result)
-               dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+               dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
 
        return;
 
@@ -391,7 +388,7 @@ static void empeg_read_bulk_callback (struct urb *urb)
 
 static void empeg_throttle (struct usb_serial_port *port)
 {
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
        usb_kill_urb(port->read_urb);
 }
 
@@ -400,14 +397,14 @@ static void empeg_unthrottle (struct usb_serial_port *port)
 {
        int result;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        port->read_urb->dev = port->serial->dev;
 
        result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 
        if (result)
-               dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
+               dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
 
        return;
 }
@@ -417,14 +414,14 @@ static int  empeg_startup (struct usb_serial *serial)
 {
        int r;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
                err("active config #%d != 1 ??",
                        serial->dev->actconfig->desc.bConfigurationValue);
                return -ENODEV;
        }
-       dbg("%s - reset config", __FUNCTION__);
+       dbg("%s - reset config", __func__);
        r = usb_reset_configuration (serial->dev);
 
        /* continue on with initialization */
@@ -435,13 +432,13 @@ static int  empeg_startup (struct usb_serial *serial)
 
 static void empeg_shutdown (struct usb_serial *serial)
 {
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 }
 
 
 static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
 {
-       dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
+       dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
 
        return -ENOIOCTLCMD;
 }
@@ -450,7 +447,7 @@ static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsign
 static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
 {
        struct ktermios *termios = port->tty->termios;
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /*
          * The empeg-car player wants these particular tty settings.
@@ -517,7 +514,7 @@ static int __init empeg_init (void)
                urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
                if (!urb->transfer_buffer) {
                        err("%s - out of memory for urb buffers.", 
-                           __FUNCTION__);
+                           __func__);
                        continue;
                }
        }
index 3f698baa0abb69d1015c4d69fa7576d357f0b9c5..cc4fbd9d60be9620532ca5c18da43d9ff406b705 100644 (file)
@@ -27,13 +27,13 @@ int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *da
 
        /* dbg("ezusb_writememory %x, %d", address, length); */
        if (!serial->dev) {
-               err("%s - no physical device present, failing.", __FUNCTION__);
+               err("%s - no physical device present, failing.", __func__);
                return -ENODEV;
        }
 
        transfer_buffer = kmemdup(data, length, GFP_KERNEL);
        if (!transfer_buffer) {
-               dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, length);
+               dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, length);
                return -ENOMEM;
        }
        result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3000);
@@ -45,10 +45,10 @@ int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
 {
        int response;
 
-       /* dbg("%s - %d", __FUNCTION__, reset_bit); */
+       /* dbg("%s - %d", __func__, reset_bit); */
        response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
        if (response < 0)
-               dev_err(&serial->dev->dev, "%s- %d failed\n", __FUNCTION__, reset_bit);
+               dev_err(&serial->dev->dev, "%s- %d failed\n", __func__, reset_bit);
        return response;
 }
 
index 3abb3c863647832a31937fb3363f415f4a344ed9..23f51a41093ec7e6215aae4228badd3bfa3f7d48 100644 (file)
@@ -439,9 +439,6 @@ static struct usb_serial_driver ftdi_sio_device = {
        .description =          "FTDI USB Serial Device",
        .usb_driver =           &ftdi_driver ,
        .id_table =             id_table_combined,
-       .num_interrupt_in =     0,
-       .num_bulk_in =          1,
-       .num_bulk_out =         1,
        .num_ports =            1,
        .probe =                ftdi_sio_probe,
        .port_probe =           ftdi_sio_port_probe,
@@ -528,14 +525,13 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned
        int rv;
 
        if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) {
-               dbg("%s - DTR|RTS not being set|cleared", __FUNCTION__);
+               dbg("%s - DTR|RTS not being set|cleared", __func__);
                return 0;       /* no change */
        }
 
        buf = kmalloc(1, GFP_NOIO);
-       if (!buf) {
+       if (!buf)
                return -ENOMEM;
-       }
 
        clear &= ~set;  /* 'set' takes precedence over 'clear' */
        urb_value = 0;
@@ -557,17 +553,18 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned
        kfree(buf);
        if (rv < 0) {
                err("%s Error from MODEM_CTRL urb: DTR %s, RTS %s",
-                               __FUNCTION__,
+                               __func__,
                                (set & TIOCM_DTR) ? "HIGH" :
                                (clear & TIOCM_DTR) ? "LOW" : "unchanged",
                                (set & TIOCM_RTS) ? "HIGH" :
                                (clear & TIOCM_RTS) ? "LOW" : "unchanged");
        } else {
-               dbg("%s - DTR %s, RTS %s", __FUNCTION__,
+               dbg("%s - DTR %s, RTS %s", __func__,
                                (set & TIOCM_DTR) ? "HIGH" :
                                (clear & TIOCM_DTR) ? "LOW" : "unchanged",
                                (set & TIOCM_RTS) ? "HIGH" :
                                (clear & TIOCM_RTS) ? "LOW" : "unchanged");
+               /* FIXME: locking on last_dtr_rts */
                priv->last_dtr_rts = (priv->last_dtr_rts & ~clear) | set;
        }
        return rv;
@@ -642,7 +639,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
        /* 1. Get the baud rate from the tty settings, this observes alt_speed hack */
 
        baud = tty_get_baud_rate(port->tty);
-       dbg("%s - tty_get_baud_rate reports speed %d", __FUNCTION__, baud);
+       dbg("%s - tty_get_baud_rate reports speed %d", __func__, baud);
 
        /* 2. Observe async-compatible custom_divisor hack, update baudrate if needed */
 
@@ -650,7 +647,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
            ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
             (priv->custom_divisor)) {
                baud = priv->baud_base / priv->custom_divisor;
-               dbg("%s - custom divisor %d sets baud rate to %d", __FUNCTION__, priv->custom_divisor, baud);
+               dbg("%s - custom divisor %d sets baud rate to %d", __func__, priv->custom_divisor, baud);
        }
 
        /* 3. Convert baudrate to device-specific divisor */
@@ -671,7 +668,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
                case 115200: div_value = ftdi_sio_b115200; break;
                } /* baud */
                if (div_value == 0) {
-                       dbg("%s - Baudrate (%d) requested is not supported", __FUNCTION__,  baud);
+                       dbg("%s - Baudrate (%d) requested is not supported", __func__,  baud);
                        div_value = ftdi_sio_b9600;
                        baud = 9600;
                        div_okay = 0;
@@ -681,7 +678,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
                if (baud <= 3000000) {
                        div_value = ftdi_232am_baud_to_divisor(baud);
                } else {
-                       dbg("%s - Baud rate too high!", __FUNCTION__);
+                       dbg("%s - Baud rate too high!", __func__);
                        baud = 9600;
                        div_value = ftdi_232am_baud_to_divisor(9600);
                        div_okay = 0;
@@ -693,7 +690,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
                if (baud <= 3000000) {
                        div_value = ftdi_232bm_baud_to_divisor(baud);
                } else {
-                       dbg("%s - Baud rate too high!", __FUNCTION__);
+                       dbg("%s - Baud rate too high!", __func__);
                        div_value = ftdi_232bm_baud_to_divisor(9600);
                        div_okay = 0;
                        baud = 9600;
@@ -703,7 +700,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
 
        if (div_okay) {
                dbg("%s - Baud rate set to %d (divisor 0x%lX) on chip %s",
-                       __FUNCTION__, baud, (unsigned long)div_value,
+                       __func__, baud, (unsigned long)div_value,
                        ftdi_chip_name[priv->chip_type]);
        }
 
@@ -804,7 +801,7 @@ static void ftdi_determine_type(struct usb_serial_port *port)
 
        version = le16_to_cpu(udev->descriptor.bcdDevice);
        interfaces = udev->actconfig->desc.bNumInterfaces;
-       dbg("%s: bcdDevice = 0x%x, bNumInterfaces = %u", __FUNCTION__,
+       dbg("%s: bcdDevice = 0x%x, bNumInterfaces = %u", __func__,
                        version, interfaces);
        if (interfaces > 1) {
                int inter;
@@ -822,7 +819,7 @@ static void ftdi_determine_type(struct usb_serial_port *port)
                 * to 0x200 when iSerialNumber is 0.  */
                if (version < 0x500) {
                        dbg("%s: something fishy - bcdDevice too low for multi-interface device",
-                                       __FUNCTION__);
+                                       __func__);
                }
        } else if (version < 0x200) {
                /* Old device.  Assume its the original SIO. */
@@ -860,7 +857,7 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a
        int rv = 0;
 
 
-       dbg("%s",__FUNCTION__);
+       dbg("%s",__func__);
 
        rv = usb_control_msg(udev,
                             usb_rcvctrlpipe(udev, 0),
@@ -887,7 +884,7 @@ static ssize_t store_latency_timer(struct device *dev, struct device_attribute *
        int v = simple_strtoul(valbuf, NULL, 10);
        int rv = 0;
 
-       dbg("%s: setting latency timer = %i", __FUNCTION__, v);
+       dbg("%s: setting latency timer = %i", __func__, v);
 
        rv = usb_control_msg(udev,
                             usb_sndctrlpipe(udev, 0),
@@ -916,7 +913,7 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att
        int v = simple_strtoul(valbuf, NULL, 10);
        int rv = 0;
 
-       dbg("%s: setting event char = %i", __FUNCTION__, v);
+       dbg("%s: setting event char = %i", __func__, v);
 
        rv = usb_control_msg(udev,
                             usb_sndctrlpipe(udev, 0),
@@ -941,7 +938,7 @@ static int create_sysfs_attrs(struct usb_serial_port *port)
        struct ftdi_private *priv = usb_get_serial_port_data(port);
        int retval = 0;
 
-       dbg("%s",__FUNCTION__);
+       dbg("%s",__func__);
 
        /* XXX I've no idea if the original SIO supports the event_char
         * sysfs parameter, so I'm playing it safe.  */
@@ -963,7 +960,7 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
 {
        struct ftdi_private *priv = usb_get_serial_port_data(port);
 
-       dbg("%s",__FUNCTION__);
+       dbg("%s",__func__);
 
        /* XXX see create_sysfs_attrs */
        if (priv->chip_type != SIO) {
@@ -1005,11 +1002,11 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
        struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial);
 
 
-       dbg("%s",__FUNCTION__);
+       dbg("%s",__func__);
 
        priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL);
        if (!priv){
-               err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct ftdi_private));
+               err("%s- kmalloc(%Zd) failed.", __func__, sizeof(struct ftdi_private));
                return -ENOMEM;
        }
 
@@ -1058,7 +1055,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
 /* Called from usbserial:serial_probe */
 static void ftdi_USB_UIRT_setup (struct ftdi_private *priv)
 {
-       dbg("%s",__FUNCTION__);
+       dbg("%s",__func__);
 
        priv->flags |= ASYNC_SPD_CUST;
        priv->custom_divisor = 77;
@@ -1069,7 +1066,7 @@ static void ftdi_USB_UIRT_setup (struct ftdi_private *priv)
  * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled.  */
 static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv)
 {
-       dbg("%s",__FUNCTION__);
+       dbg("%s",__func__);
 
        priv->flags |= ASYNC_SPD_CUST;
        priv->custom_divisor = 240;
@@ -1087,7 +1084,7 @@ static int ftdi_jtag_probe(struct usb_serial *serial)
        struct usb_device *udev = serial->dev;
        struct usb_interface *interface = serial->interface;
 
-       dbg("%s",__FUNCTION__);
+       dbg("%s",__func__);
 
        if (interface == udev->actconfig->interface[0]) {
                info("Ignoring serial port reserved for JTAG");
@@ -1123,14 +1120,14 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
  */
 static void ftdi_shutdown (struct usb_serial *serial)
 {
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 }
 
 static int ftdi_sio_port_remove(struct usb_serial_port *port)
 {
        struct ftdi_private *priv = usb_get_serial_port_data(port);
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        remove_sysfs_attrs(port);
 
@@ -1155,7 +1152,7 @@ static int  ftdi_open (struct usb_serial_port *port, struct file *filp)
        int result = 0;
        char buf[1]; /* Needed for the usb_control_msg I think */
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        spin_lock_irqsave(&priv->tx_lock, flags);
        priv->tx_bytes = 0;
@@ -1200,7 +1197,7 @@ static int  ftdi_open (struct usb_serial_port *port, struct file *filp)
                      ftdi_read_bulk_callback, port);
        result = usb_submit_urb(port->read_urb, GFP_KERNEL);
        if (result)
-               err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+               err("%s - failed submitting read urb, error %d", __func__, result);
 
 
        return result;
@@ -1222,7 +1219,7 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
        struct ftdi_private *priv = usb_get_serial_port_data(port);
        char buf[1];
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        mutex_lock(&port->serial->disc_mutex);
        if (c_cflag & HUPCL && !port->serial->disconnected){
@@ -1269,7 +1266,7 @@ static int ftdi_write (struct usb_serial_port *port,
        int transfer_size;
        unsigned long flags;
 
-       dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count);
+       dbg("%s port %d, %d bytes", __func__, port->number, count);
 
        if (count == 0) {
                dbg("write request of 0 bytes");
@@ -1278,7 +1275,7 @@ static int ftdi_write (struct usb_serial_port *port,
        spin_lock_irqsave(&priv->tx_lock, flags);
        if (priv->tx_outstanding_urbs > URB_UPPER_LIMIT) {
                spin_unlock_irqrestore(&priv->tx_lock, flags);
-               dbg("%s - write limit hit\n", __FUNCTION__);
+               dbg("%s - write limit hit\n", __func__);
                return 0;
        }
        priv->tx_outstanding_urbs++;
@@ -1298,14 +1295,14 @@ static int ftdi_write (struct usb_serial_port *port,
 
        buffer = kmalloc (transfer_size, GFP_ATOMIC);
        if (!buffer) {
-               err("%s ran out of kernel memory for urb ...", __FUNCTION__);
+               err("%s ran out of kernel memory for urb ...", __func__);
                count = -ENOMEM;
                goto error_no_buffer;
        }
 
        urb = usb_alloc_urb(0, GFP_ATOMIC);
        if (!urb) {
-               err("%s - no more free urbs", __FUNCTION__);
+               err("%s - no more free urbs", __func__);
                count = -ENOMEM;
                goto error_no_urb;
        }
@@ -1337,7 +1334,7 @@ static int ftdi_write (struct usb_serial_port *port,
                memcpy (buffer, buf, count);
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size, buffer);
+       usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, buffer);
 
        /* fill the buffer and send it */
        usb_fill_bulk_urb(urb, port->serial->dev,
@@ -1347,7 +1344,7 @@ static int ftdi_write (struct usb_serial_port *port,
 
        status = usb_submit_urb(urb, GFP_ATOMIC);
        if (status) {
-               err("%s - failed submitting write urb, error %d", __FUNCTION__, status);
+               err("%s - failed submitting write urb, error %d", __func__, status);
                count = status;
                goto error;
        } else {
@@ -1361,7 +1358,7 @@ static int ftdi_write (struct usb_serial_port *port,
         * really free it when it is finished with it */
        usb_free_urb(urb);
 
-       dbg("%s write returning: %d", __FUNCTION__, count);
+       dbg("%s write returning: %d", __func__, count);
        return count;
 error:
        usb_free_urb(urb);
@@ -1380,7 +1377,7 @@ error_no_buffer:
 static void ftdi_write_bulk_callback (struct urb *urb)
 {
        unsigned long flags;
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct ftdi_private *priv;
        int data_offset;       /* will be 1 for the SIO and 0 otherwise */
        unsigned long countback;
@@ -1389,7 +1386,7 @@ static void ftdi_write_bulk_callback (struct urb *urb)
        /* free up the transfer buffer, as usb_free_urb() does not do this */
        kfree (urb->transfer_buffer);
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (status) {
                dbg("nonzero write bulk status received: %d", status);
@@ -1398,7 +1395,7 @@ static void ftdi_write_bulk_callback (struct urb *urb)
 
        priv = usb_get_serial_port_data(port);
        if (!priv) {
-               dbg("%s - bad port private data pointer - exiting", __FUNCTION__);
+               dbg("%s - bad port private data pointer - exiting", __func__);
                return;
        }
        /* account for transferred data */
@@ -1406,7 +1403,7 @@ static void ftdi_write_bulk_callback (struct urb *urb)
        data_offset = priv->write_offset;
        if (data_offset > 0) {
                /* Subtract the control bytes */
-               countback -= (data_offset * ((countback + (PKTSZ - 1)) / PKTSZ));
+               countback -= (data_offset * DIV_ROUND_UP(countback, PKTSZ));
        }
        spin_lock_irqsave(&priv->tx_lock, flags);
        --priv->tx_outstanding_urbs;
@@ -1423,7 +1420,7 @@ static int ftdi_write_room( struct usb_serial_port *port )
        int room;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->tx_lock, flags);
        if (priv->tx_outstanding_urbs < URB_UPPER_LIMIT) {
@@ -1447,13 +1444,13 @@ static int ftdi_chars_in_buffer (struct usb_serial_port *port)
        int buffered;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->tx_lock, flags);
        buffered = (int)priv->tx_outstanding_bytes;
        spin_unlock_irqrestore(&priv->tx_lock, flags);
        if (buffered < 0) {
-               err("%s outstanding tx bytes is negative!", __FUNCTION__);
+               err("%s outstanding tx bytes is negative!", __func__);
                buffered = 0;
        }
        return buffered;
@@ -1463,7 +1460,7 @@ static int ftdi_chars_in_buffer (struct usb_serial_port *port)
 
 static void ftdi_read_bulk_callback (struct urb *urb)
 { /* ftdi_read_bulk_callback */
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct tty_struct *tty;
        struct ftdi_private *priv;
        unsigned long countread;
@@ -1471,30 +1468,30 @@ static void ftdi_read_bulk_callback (struct urb *urb)
        int status = urb->status;
 
        if (urb->number_of_packets > 0) {
-               err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__,
+               err("%s transfer_buffer_length %d actual_length %d number of packets %d",__func__,
                    urb->transfer_buffer_length, urb->actual_length, urb->number_of_packets );
-               err("%s transfer_flags %x ", __FUNCTION__,urb->transfer_flags );
+               err("%s transfer_flags %x ", __func__,urb->transfer_flags );
        }
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (port->open_count <= 0)
                return;
 
        tty = port->tty;
        if (!tty) {
-               dbg("%s - bad tty pointer - exiting",__FUNCTION__);
+               dbg("%s - bad tty pointer - exiting",__func__);
                return;
        }
 
        priv = usb_get_serial_port_data(port);
        if (!priv) {
-               dbg("%s - bad port private data pointer - exiting", __FUNCTION__);
+               dbg("%s - bad port private data pointer - exiting", __func__);
                return;
        }
 
        if (urb != port->read_urb) {
-               err("%s - Not my urb!", __FUNCTION__);
+               err("%s - Not my urb!", __func__);
        }
 
        if (status) {
@@ -1506,7 +1503,7 @@ static void ftdi_read_bulk_callback (struct urb *urb)
 
        /* count data bytes, but not status bytes */
        countread = urb->actual_length;
-       countread -= 2 * ((countread + (PKTSZ - 1)) / PKTSZ);
+       countread -= 2 * DIV_ROUND_UP(countread, PKTSZ);
        spin_lock_irqsave(&priv->rx_lock, flags);
        priv->rx_bytes += countread;
        spin_unlock_irqrestore(&priv->rx_lock, flags);
@@ -1532,39 +1529,39 @@ static void ftdi_process_read (struct work_struct *work)
        int packet_offset;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (port->open_count <= 0)
                return;
 
        tty = port->tty;
        if (!tty) {
-               dbg("%s - bad tty pointer - exiting",__FUNCTION__);
+               dbg("%s - bad tty pointer - exiting",__func__);
                return;
        }
 
        priv = usb_get_serial_port_data(port);
        if (!priv) {
-               dbg("%s - bad port private data pointer - exiting", __FUNCTION__);
+               dbg("%s - bad port private data pointer - exiting", __func__);
                return;
        }
 
        urb = port->read_urb;
        if (!urb) {
-               dbg("%s - bad read_urb pointer - exiting", __FUNCTION__);
+               dbg("%s - bad read_urb pointer - exiting", __func__);
                return;
        }
 
        data = urb->transfer_buffer;
 
        if (priv->rx_processed) {
-               dbg("%s - already processed: %d bytes, %d remain", __FUNCTION__,
+               dbg("%s - already processed: %d bytes, %d remain", __func__,
                                priv->rx_processed,
                                urb->actual_length - priv->rx_processed);
        } else {
                /* The first two bytes of every read packet are status */
                if (urb->actual_length > 2) {
-                       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+                       usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
                } else {
                        dbg("Status only: %03oo %03oo",data[0],data[1]);
                }
@@ -1594,17 +1591,17 @@ static void ftdi_process_read (struct work_struct *work)
 
                length = min(PKTSZ, urb->actual_length-packet_offset)-2;
                if (length < 0) {
-                       err("%s - bad packet length: %d", __FUNCTION__, length+2);
+                       err("%s - bad packet length: %d", __func__, length+2);
                        length = 0;
                }
 
                if (priv->rx_flags & THROTTLED) {
-                       dbg("%s - throttled", __FUNCTION__);
+                       dbg("%s - throttled", __func__);
                        break;
                }
                if (tty_buffer_request_room(tty, length) < length) {
                        /* break out & wait for throttling/unthrottling to happen */
-                       dbg("%s - receive room low", __FUNCTION__);
+                       dbg("%s - receive room low", __func__);
                        break;
                }
 
@@ -1672,7 +1669,7 @@ static void ftdi_process_read (struct work_struct *work)
                /* not completely processed - record progress */
                priv->rx_processed = packet_offset;
                dbg("%s - incomplete, %d bytes processed, %d remain",
-                               __FUNCTION__, packet_offset,
+                               __func__, packet_offset,
                                urb->actual_length - packet_offset);
                /* check if we were throttled while processing */
                spin_lock_irqsave(&priv->rx_lock, flags);
@@ -1680,7 +1677,7 @@ static void ftdi_process_read (struct work_struct *work)
                        priv->rx_flags |= ACTUALLY_THROTTLED;
                        spin_unlock_irqrestore(&priv->rx_lock, flags);
                        dbg("%s - deferring remainder until unthrottled",
-                                       __FUNCTION__);
+                                       __func__);
                        return;
                }
                spin_unlock_irqrestore(&priv->rx_lock, flags);
@@ -1689,7 +1686,7 @@ static void ftdi_process_read (struct work_struct *work)
                        /* delay processing of remainder */
                        schedule_delayed_work(&priv->rx_work, 1);
                } else {
-                       dbg("%s - port is closed", __FUNCTION__);
+                       dbg("%s - port is closed", __func__);
                }
                return;
        }
@@ -1707,7 +1704,7 @@ static void ftdi_process_read (struct work_struct *work)
 
                result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
                if (result)
-                       err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+                       err("%s - failed resubmitting read urb, error %d", __func__, result);
        }
 
        return;
@@ -1736,10 +1733,10 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
                            FTDI_SIO_SET_DATA_REQUEST_TYPE,
                            urb_value , priv->interface,
                            buf, 0, WDR_TIMEOUT) < 0) {
-               err("%s FAILED to enable/disable break state (state was %d)", __FUNCTION__,break_state);
+               err("%s FAILED to enable/disable break state (state was %d)", __func__,break_state);
        }
 
-       dbg("%s break state is %d - urb is %d", __FUNCTION__,break_state, urb_value);
+       dbg("%s break state is %d - urb is %d", __func__,break_state, urb_value);
 
 }
 
@@ -1763,18 +1760,18 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
        unsigned char vstop;
        unsigned char vstart;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /* Force baud rate if this device requires it, unless it is set to B0. */
        if (priv->force_baud && ((termios->c_cflag & CBAUD) != B0)) {
-               dbg("%s: forcing baud rate for this device", __FUNCTION__);
+               dbg("%s: forcing baud rate for this device", __func__);
                tty_encode_baud_rate(port->tty, priv->force_baud,
                                        priv->force_baud);
        }
 
        /* Force RTS-CTS if this device requires it. */
        if (priv->force_rtscts) {
-               dbg("%s: forcing rtscts for this device", __FUNCTION__);
+               dbg("%s: forcing rtscts for this device", __func__);
                termios->c_cflag |= CRTSCTS;
        }
 
@@ -1818,7 +1815,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
                            FTDI_SIO_SET_DATA_REQUEST_TYPE,
                            urb_value , priv->interface,
                            buf, 0, WDR_SHORT_TIMEOUT) < 0) {
-               err("%s FAILED to set databits/stopbits/parity", __FUNCTION__);
+               err("%s FAILED to set databits/stopbits/parity", __func__);
        }
 
        /* Now do the baudrate */
@@ -1829,14 +1826,14 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
                                    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
                                    0, priv->interface,
                                    buf, 0, WDR_TIMEOUT) < 0) {
-                       err("%s error from disable flowcontrol urb", __FUNCTION__);
+                       err("%s error from disable flowcontrol urb", __func__);
                }
                /* Drop RTS and DTR */
                clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
        } else {
                /* set the baudrate determined before */
                if (change_speed(port)) {
-                       err("%s urb failed to set baudrate", __FUNCTION__);
+                       err("%s urb failed to set baudrate", __func__);
                }
                /* Ensure RTS and DTR are raised when baudrate changed from 0 */
                if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) {
@@ -1847,7 +1844,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
        /* Set flow control */
        /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */
        if (cflag & CRTSCTS) {
-               dbg("%s Setting to CRTSCTS flow control", __FUNCTION__);
+               dbg("%s Setting to CRTSCTS flow control", __func__);
                if (usb_control_msg(dev,
                                    usb_sndctrlpipe(dev, 0),
                                    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
@@ -1865,7 +1862,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
                 * if IXOFF is not set, the pre-xon/xoff code is executed.
                */
                if (iflag & IXOFF) {
-                       dbg("%s  request to enable xonxoff iflag=%04x",__FUNCTION__,iflag);
+                       dbg("%s  request to enable xonxoff iflag=%04x",__func__,iflag);
                        // Try to enable the XON/XOFF on the ftdi_sio
                        // Set the vstart and vstop -- could have been done up above where
                        // a lot of other dereferencing is done but that would be very
@@ -1886,7 +1883,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
                } else {
                        /* else clause to only run if cfag ! CRTSCTS and iflag ! XOFF */
                        /* CHECKME Assuming XON/XOFF handled by tty stack - not by device */
-                       dbg("%s Turning off hardware flow control", __FUNCTION__);
+                       dbg("%s Turning off hardware flow control", __func__);
                        if (usb_control_msg(dev,
                                            usb_sndctrlpipe(dev, 0),
                                            FTDI_SIO_SET_FLOW_CTRL_REQUEST,
@@ -1908,7 +1905,7 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
        unsigned char buf[2];
        int ret;
 
-       dbg("%s TIOCMGET", __FUNCTION__);
+       dbg("%s TIOCMGET", __func__);
        switch (priv->chip_type) {
        case SIO:
                /* Request the status from the device */
@@ -1918,7 +1915,7 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
                                           FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
                                           0, 0,
                                           buf, 1, WDR_TIMEOUT)) < 0 ) {
-                       err("%s Could not get modem status of device - err: %d", __FUNCTION__,
+                       err("%s Could not get modem status of device - err: %d", __func__,
                            ret);
                        return(ret);
                }
@@ -1935,7 +1932,7 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
                                           FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
                                           0, priv->interface,
                                           buf, 2, WDR_TIMEOUT)) < 0 ) {
-                       err("%s Could not get modem status of device - err: %d", __FUNCTION__,
+                       err("%s Could not get modem status of device - err: %d", __func__,
                            ret);
                        return(ret);
                }
@@ -1954,7 +1951,7 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
 
 static int ftdi_tiocmset(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear)
 {
-       dbg("%s TIOCMSET", __FUNCTION__);
+       dbg("%s TIOCMSET", __func__);
        return update_mctrl(port, set, clear);
 }
 
@@ -1963,7 +1960,7 @@ static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigne
 {
        struct ftdi_private *priv = usb_get_serial_port_data(port);
 
-       dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
+       dbg("%s cmd 0x%04x", __func__, cmd);
 
        /* Based on code from acm.c and others */
        switch (cmd) {
@@ -2022,7 +2019,7 @@ static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigne
        /* This is not necessarily an error - turns out the higher layers will do
         *  some ioctls itself (see comment above)
         */
-       dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __FUNCTION__, cmd);
+       dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __func__, cmd);
 
        return(-ENOIOCTLCMD);
 } /* ftdi_ioctl */
@@ -2033,7 +2030,7 @@ static void ftdi_throttle (struct usb_serial_port *port)
        struct ftdi_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->rx_lock, flags);
        priv->rx_flags |= THROTTLED;
@@ -2047,7 +2044,7 @@ static void ftdi_unthrottle (struct usb_serial_port *port)
        int actually_throttled;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->rx_lock, flags);
        actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
@@ -2062,7 +2059,7 @@ static int __init ftdi_init (void)
 {
        int retval;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
        if (vendor > 0 && product > 0) {
                /* Add user specified VID/PID to reserved element of table. */
                int i;
@@ -2091,7 +2088,7 @@ failed_sio_register:
 static void __exit ftdi_exit (void)
 {
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        usb_deregister (&ftdi_driver);
        usb_serial_deregister (&ftdi_sio_device);
index b5194dc7d3bba271e2066e539570e691f0fa0d93..e8ba2cb5995db1eefc0073607facf9ade1d15599 100644 (file)
@@ -39,9 +39,6 @@ static struct usb_serial_driver funsoft_device = {
        },
        .id_table =             id_table,
        .usb_driver =           &funsoft_driver,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          NUM_DONT_CARE,
-       .num_bulk_out =         NUM_DONT_CARE,
        .num_ports =            1,
 };
 
index d74e43d69230b5ea1d7b75a4b599f9052f658004..8ce5a56a48e30ec1da010705a093262993c172bb 100644 (file)
@@ -280,7 +280,7 @@ static void send_to_tty(struct usb_serial_port *port,
        if (tty && actual_length) {
 
                usb_serial_debug_data(debug, &port->dev, 
-                                       __FUNCTION__, actual_length, data);
+                                       __func__, actual_length, data);
 
                tty_buffer_request_room(tty, actual_length);
                tty_insert_flip_string(tty, data, actual_length);
@@ -355,7 +355,7 @@ static void pkt_clear(struct garmin_data * garmin_data_p)
        unsigned long flags;
        struct garmin_packet *result = NULL;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        spin_lock_irqsave(&garmin_data_p->lock, flags);
        while (!list_empty(&garmin_data_p->pktlist)) {
@@ -379,7 +379,7 @@ static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
        __u8 *ptr = pkt;
        unsigned  l = 0;
 
-       dbg("%s - pkt-id: 0x%X.", __FUNCTION__, 0xFF & pkt_id);
+       dbg("%s - pkt-id: 0x%X.", __func__, 0xFF & pkt_id);
 
        *ptr++ = DLE;
        *ptr++ = ACK;
@@ -429,11 +429,11 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
        int size = recpkt[1];
 
        usb_serial_debug_data(debug, &garmin_data_p->port->dev,
-                              __FUNCTION__, count-GSP_INITIAL_OFFSET, recpkt);
+                              __func__, count-GSP_INITIAL_OFFSET, recpkt);
 
        if (size != (count-GSP_INITIAL_OFFSET-3)) {
                dbg("%s - invalid size, expected %d bytes, got %d",
-                       __FUNCTION__, size, (count-GSP_INITIAL_OFFSET-3));
+                       __func__, size, (count-GSP_INITIAL_OFFSET-3));
                return -EINVPKT;
        }
 
@@ -443,7 +443,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
        // sanity check, remove after test ...
        if ((__u8*)&(usbdata[3]) != recpkt) {
                dbg("%s - ptr mismatch %p - %p",
-                       __FUNCTION__, &(usbdata[4]), recpkt);
+                       __func__, &(usbdata[4]), recpkt);
                return -EINVPKT;
        }
 
@@ -454,7 +454,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
 
        if ((0xff & (cksum + *recpkt)) != 0) {
                dbg("%s - invalid checksum, expected %02x, got %02x",
-                       __FUNCTION__, 0xff & -cksum, 0xff & *recpkt);
+                       __func__, 0xff & -cksum, 0xff & *recpkt);
                return -EINVPKT;
        }
 
@@ -519,7 +519,7 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
        spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
        dbg("%s - dle=%d skip=%d size=%d count=%d",
-               __FUNCTION__, dleSeen, skip, size, count);
+               __func__, dleSeen, skip, size, count);
 
        if (size == 0) {
                size = GSP_INITIAL_OFFSET;
@@ -578,7 +578,7 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
                }
 
                if (size >= GPS_IN_BUFSIZ) {
-                       dbg("%s - packet too large.", __FUNCTION__);
+                       dbg("%s - packet too large.", __func__);
                        skip = 1;
                        size = GSP_INITIAL_OFFSET;
                        dleSeen = 0;
@@ -634,7 +634,7 @@ static int gsp_send(struct garmin_data * garmin_data_p,
        int i=0;
        int k;
 
-       dbg("%s - state %d - %d bytes.", __FUNCTION__,
+       dbg("%s - state %d - %d bytes.", __func__,
                 garmin_data_p->state, count);
 
        k = garmin_data_p->outsize;
@@ -658,13 +658,13 @@ static int gsp_send(struct garmin_data * garmin_data_p,
                return 0;
        }
 
-       dbg("%s - %d bytes in buffer, %d bytes in pkt.", __FUNCTION__,
+       dbg("%s - %d bytes in buffer, %d bytes in pkt.", __func__,
                 k, i);
 
        /* garmin_data_p->outbuffer now contains a complete packet */
 
        usb_serial_debug_data(debug, &garmin_data_p->port->dev,
-                                  __FUNCTION__, k, garmin_data_p->outbuffer);
+                                  __func__, k, garmin_data_p->outbuffer);
 
        garmin_data_p->outsize = 0;
 
@@ -749,7 +749,7 @@ static void gsp_next_packet(struct garmin_data * garmin_data_p)
        struct garmin_packet *pkt = NULL;
 
        while ((pkt = pkt_pop(garmin_data_p)) != NULL) {
-               dbg("%s - next pkt: %d", __FUNCTION__, pkt->seq);
+               dbg("%s - next pkt: %d", __func__, pkt->seq);
                if (gsp_send(garmin_data_p, pkt->data, pkt->size) > 0) {
                        kfree(pkt);
                        return;
@@ -794,7 +794,7 @@ static int nat_receive(struct garmin_data * garmin_data_p,
                if (len >= GPS_IN_BUFSIZ) {
                        /* seem to be an invalid packet, ignore rest of input */
                        dbg("%s - packet size too large: %d",
-                               __FUNCTION__, len);
+                               __func__, len);
                        garmin_data_p->insize = 0;
                        count = 0;
                        result = -EINVPKT;
@@ -873,11 +873,11 @@ static int process_resetdev_request(struct usb_serial_port *port)
        spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
        usb_kill_urb (port->interrupt_in_urb);
-       dbg("%s - usb_reset_device", __FUNCTION__ );
+       dbg("%s - usb_reset_device", __func__ );
        status = usb_reset_device(port->serial->dev);
        if (status)
                dbg("%s - usb_reset_device failed: %d",
-                       __FUNCTION__, status);
+                       __func__, status);
        return status;
 }
 
@@ -926,18 +926,18 @@ static int garmin_init_session(struct usb_serial_port *port)
        if (status == 0) {
                usb_kill_urb (port->interrupt_in_urb);
 
-               dbg("%s - adding interrupt input", __FUNCTION__);
+               dbg("%s - adding interrupt input", __func__);
                port->interrupt_in_urb->dev = serial->dev;
                status = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
                if (status)
                        dev_err(&serial->dev->dev,
                                "%s - failed submitting interrupt urb,"
                                " error %d\n",
-                               __FUNCTION__, status);
+                               __func__, status);
        }
 
        if (status == 0) {
-               dbg("%s - starting session ...", __FUNCTION__);
+               dbg("%s - starting session ...", __func__);
                garmin_data_p->state = STATE_ACTIVE;
                status = garmin_write_bulk(port, GARMIN_START_SESSION_REQ,
                                           sizeof(GARMIN_START_SESSION_REQ),
@@ -976,7 +976,7 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp)
        int status = 0;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /*
         * Force low_latency on so that our tty_push actually forces the data
@@ -1013,7 +1013,7 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp)
        struct usb_serial *serial = port->serial;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
-       dbg("%s - port %d - mode=%d state=%d flags=0x%X", __FUNCTION__,
+       dbg("%s - port %d - mode=%d state=%d flags=0x%X", __func__,
                port->number, garmin_data_p->mode,
                garmin_data_p->state, garmin_data_p->flags);
 
@@ -1046,13 +1046,13 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp)
 static void garmin_write_bulk_callback (struct urb *urb)
 {
        unsigned long flags;
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        int status = urb->status;
 
        if (port) {
                struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
-               dbg("%s - port %d", __FUNCTION__, port->number);
+               dbg("%s - port %d", __func__, port->number);
 
                if (GARMIN_LAYERID_APPL == getLayerId(urb->transfer_buffer)
                    && (garmin_data_p->mode == MODE_GARMIN_SERIAL))  {
@@ -1061,7 +1061,7 @@ static void garmin_write_bulk_callback (struct urb *urb)
 
                if (status) {
                        dbg("%s - nonzero write bulk status received: %d",
-                           __FUNCTION__, urb->status);
+                           __func__, urb->status);
                        spin_lock_irqsave(&garmin_data_p->lock, flags);
                        garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
                        spin_unlock_irqrestore(&garmin_data_p->lock, flags);
@@ -1088,7 +1088,7 @@ static int garmin_write_bulk (struct usb_serial_port *port,
        unsigned char *buffer;
        int status;
 
-       dbg("%s - port %d, state %d", __FUNCTION__, port->number,
+       dbg("%s - port %d, state %d", __func__, port->number,
                garmin_data_p->state);
 
        spin_lock_irqsave(&garmin_data_p->lock, flags);
@@ -1110,7 +1110,7 @@ static int garmin_write_bulk (struct usb_serial_port *port,
 
        memcpy (buffer, buf, count);
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
+       usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
 
        usb_fill_bulk_urb (urb, serial->dev,
                                usb_sndbulkpipe (serial->dev,
@@ -1134,7 +1134,7 @@ static int garmin_write_bulk (struct usb_serial_port *port,
                dev_err(&port->dev,
                        "%s - usb_submit_urb(write bulk) "
                        "failed with status = %d\n",
-                               __FUNCTION__, status);
+                               __func__, status);
                count = status;
        }
 
@@ -1154,7 +1154,7 @@ static int garmin_write (struct usb_serial_port *port,
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
        __le32 *privpkt = (__le32 *)garmin_data_p->privpkt;
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buf);
+       usb_serial_debug_data(debug, &port->dev, __func__, count, buf);
 
        /* check for our private packets */
        if (count >= GARMIN_PKTHDR_LENGTH) {
@@ -1172,7 +1172,7 @@ static int garmin_write (struct usb_serial_port *port,
                    && GARMIN_LAYERID_PRIVATE == getLayerId(garmin_data_p->privpkt)) {
 
                        dbg("%s - processing private request %d",
-                               __FUNCTION__, pktid);
+                               __func__, pktid);
 
                        // drop all unfinished transfers
                        garmin_clear(garmin_data_p);
@@ -1184,7 +1184,7 @@ static int garmin_write (struct usb_serial_port *port,
                                        return -EINVPKT;
                                debug = __le32_to_cpu(privpkt[3]);
                                dbg("%s - debug level set to 0x%X",
-                                       __FUNCTION__, debug);
+                                       __func__, debug);
                                break;
 
                        case PRIV_PKTID_SET_MODE:
@@ -1192,7 +1192,7 @@ static int garmin_write (struct usb_serial_port *port,
                                        return -EINVPKT;
                                garmin_data_p->mode = __le32_to_cpu(privpkt[3]);
                                dbg("%s - mode set to %d",
-                                       __FUNCTION__, garmin_data_p->mode);
+                                       __func__, garmin_data_p->mode);
                                break;
 
                        case PRIV_PKTID_INFO_REQ:
@@ -1208,7 +1208,7 @@ static int garmin_write (struct usb_serial_port *port,
                                        return -EINVPKT;
                                initial_mode = __le32_to_cpu(privpkt[3]);
                                dbg("%s - initial_mode set to %d",
-                                       __FUNCTION__,
+                                       __func__,
                                        garmin_data_p->mode);
                                break;
                        }
@@ -1255,7 +1255,7 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
 {
        if (garmin_data_p->flags & FLAGS_DROP_DATA) {
                /* abort-transfer cmd is actice */
-               dbg("%s - pkt dropped", __FUNCTION__);
+               dbg("%s - pkt dropped", __func__);
        } else if (garmin_data_p->state != STATE_DISCONNECTED &&
                   garmin_data_p->state != STATE_RESET ) {
 
@@ -1286,28 +1286,28 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
 static void garmin_read_bulk_callback (struct urb *urb)
 {
        unsigned long flags;
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *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;
        int retval;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (!serial) {
-               dbg("%s - bad serial pointer, exiting", __FUNCTION__);
+               dbg("%s - bad serial pointer, exiting", __func__);
                return;
        }
 
        if (status) {
                dbg("%s - nonzero read bulk status received: %d",
-                       __FUNCTION__, status);
+                       __func__, status);
                return;
        }
 
        usb_serial_debug_data(debug, &port->dev, 
-                               __FUNCTION__, urb->actual_length, data);
+                               __func__, urb->actual_length, data);
 
        garmin_read_process(garmin_data_p, data, urb->actual_length);
 
@@ -1320,7 +1320,7 @@ static void garmin_read_bulk_callback (struct urb *urb)
                if (retval)
                        dev_err(&port->dev,
                                "%s - failed resubmitting read urb, error %d\n",
-                               __FUNCTION__, retval);
+                               __func__, retval);
        } else if (urb->actual_length > 0) {
                /* Continue trying to read until nothing more is received  */
                if (0 == (garmin_data_p->flags & FLAGS_THROTTLED)) {
@@ -1328,10 +1328,10 @@ static void garmin_read_bulk_callback (struct urb *urb)
                        if (retval)
                                dev_err(&port->dev,
                                        "%s - failed resubmitting read urb, "
-                                       "error %d\n", __FUNCTION__, retval);
+                                       "error %d\n", __func__, retval);
                }
        } else {
-               dbg("%s - end of bulk data", __FUNCTION__);
+               dbg("%s - end of bulk data", __func__);
                spin_lock_irqsave(&garmin_data_p->lock, flags);
                garmin_data_p->flags &= ~FLAGS_BULK_IN_ACTIVE;
                spin_unlock_irqrestore(&garmin_data_p->lock, flags);
@@ -1344,7 +1344,7 @@ static void garmin_read_int_callback (struct urb *urb)
 {
        unsigned long flags;
        int retval;
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *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;
@@ -1359,22 +1359,22 @@ 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__, status);
+                       __func__, status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d",
-                       __FUNCTION__, status);
+                       __func__, status);
                return;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, 
+       usb_serial_debug_data(debug, &port->dev, __func__,
                                urb->actual_length, urb->transfer_buffer);
 
        if (urb->actual_length == sizeof(GARMIN_BULK_IN_AVAIL_REPLY) &&
            0 == memcmp(data, GARMIN_BULK_IN_AVAIL_REPLY,
                        sizeof(GARMIN_BULK_IN_AVAIL_REPLY))) {
 
-               dbg("%s - bulk data available.", __FUNCTION__);
+               dbg("%s - bulk data available.", __func__);
 
                if (0 == (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
 
@@ -1389,7 +1389,7 @@ static void garmin_read_int_callback (struct urb *urb)
                        if (retval) {
                                dev_err(&port->dev,
                                        "%s - failed submitting read urb, error %d\n",
-                               __FUNCTION__, retval);
+                               __func__, retval);
                        } else {
                                spin_lock_irqsave(&garmin_data_p->lock, flags);
                                garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE;
@@ -1417,14 +1417,14 @@ static void garmin_read_int_callback (struct urb *urb)
                        = __le32_to_cpup((__le32*)(data+GARMIN_PKTHDR_LENGTH));
 
                dbg("%s - start-of-session reply seen - serial %u.",
-                       __FUNCTION__, garmin_data_p->serial_num);
+                       __func__, garmin_data_p->serial_num);
        }
 
        if (garmin_data_p->ignorePkts) {
                /* this reply belongs to a request generated by the driver,
                   ignore it. */
                dbg("%s - pkt ignored (%d)",
-                       __FUNCTION__, garmin_data_p->ignorePkts);
+                       __func__, garmin_data_p->ignorePkts);
                spin_lock_irqsave(&garmin_data_p->lock, flags);
                garmin_data_p->ignorePkts--;
                spin_unlock_irqrestore(&garmin_data_p->lock, flags);
@@ -1437,7 +1437,7 @@ static void garmin_read_int_callback (struct urb *urb)
        if (retval)
                dev_err(&urb->dev->dev,
                        "%s - Error %d submitting interrupt urb\n",
-                       __FUNCTION__, retval);
+                       __func__, retval);
 }
 
 
@@ -1473,7 +1473,7 @@ static void garmin_throttle (struct usb_serial_port *port)
        unsigned long flags;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
        /* set flag, data received will be put into a queue
           for later processing */
        spin_lock_irqsave(&garmin_data_p->lock, flags);
@@ -1488,7 +1488,7 @@ static void garmin_unthrottle (struct usb_serial_port *port)
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
        int status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
        spin_lock_irqsave(&garmin_data_p->lock, flags);
        garmin_data_p->flags &= ~FLAGS_THROTTLED;
        spin_unlock_irqrestore(&garmin_data_p->lock, flags);
@@ -1503,7 +1503,7 @@ static void garmin_unthrottle (struct usb_serial_port *port)
                if (status)
                        dev_err(&port->dev,
                                "%s - failed resubmitting read urb, error %d\n",
-                               __FUNCTION__, status);
+                               __func__, status);
        }
 }
 
@@ -1532,11 +1532,11 @@ static int garmin_attach (struct usb_serial *serial)
        struct usb_serial_port *port = serial->port[0];
        struct garmin_data * garmin_data_p = NULL;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
        if (garmin_data_p == NULL) {
-               dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__);
+               dev_err(&port->dev, "%s - Out of memory\n", __func__);
                return -ENOMEM;
        }
        init_timer(&garmin_data_p->timer);
@@ -1561,7 +1561,7 @@ static void garmin_shutdown (struct usb_serial *serial)
        struct usb_serial_port *port = serial->port[0];
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        usb_kill_urb (port->interrupt_in_urb);
        del_timer_sync(&garmin_data_p->timer);
@@ -1579,9 +1579,6 @@ static struct usb_serial_driver garmin_device = {
        .description         = "Garmin GPS usb/tty",
        .usb_driver          = &garmin_driver,
        .id_table            = id_table,
-       .num_interrupt_in    = 1,
-       .num_bulk_in         = 1,
-       .num_bulk_out        = 1,
        .num_ports           = 1,
        .open                = garmin_open,
        .close               = garmin_close,
index 7cfce9dabb9001c0f68bc68503c87e5bd07ed82a..537f12a027c224e2a2253224ae020e515714416d 100644 (file)
@@ -62,9 +62,6 @@ struct usb_serial_driver usb_serial_generic_device = {
        },
        .id_table =             generic_device_ids,
        .usb_driver =           &generic_driver,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          NUM_DONT_CARE,
-       .num_bulk_out =         NUM_DONT_CARE,
        .num_ports =            1,
        .shutdown =             usb_serial_generic_shutdown,
        .throttle =             usb_serial_generic_throttle,
@@ -121,7 +118,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
        int result = 0;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /* force low_latency on so that our tty_push actually forces the data through, 
           otherwise it is scheduled, and with high data rates (like with OHCI) data
@@ -148,7 +145,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
                                   port);
                result = usb_submit_urb(port->read_urb, GFP_KERNEL);
                if (result)
-                       dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+                       dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
        }
 
        return result;
@@ -159,7 +156,7 @@ static void generic_cleanup (struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (serial->dev) {
                /* shutdown any bulk reads that might be going on */
@@ -197,7 +194,7 @@ int usb_serial_generic_resume(struct usb_serial *serial)
 
 void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp)
 {
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
        generic_cleanup (port);
 }
 
@@ -207,10 +204,10 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
        int result;
        unsigned char *data;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (count == 0) {
-               dbg("%s - write request of 0 bytes", __FUNCTION__);
+               dbg("%s - write request of 0 bytes", __func__);
                return (0);
        }
 
@@ -220,7 +217,7 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
                spin_lock_irqsave(&port->lock, flags);
                if (port->write_urb_busy) {
                        spin_unlock_irqrestore(&port->lock, flags);
-                       dbg("%s - already writing", __FUNCTION__);
+                       dbg("%s - already writing", __func__);
                        return 0;
                }
                port->write_urb_busy = 1;
@@ -230,7 +227,7 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
 
                memcpy (port->write_urb->transfer_buffer, buf, count);
                data = port->write_urb->transfer_buffer;
-               usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, data);
+               usb_serial_debug_data(debug, &port->dev, __func__, count, data);
 
                /* set up our urb */
                usb_fill_bulk_urb (port->write_urb, serial->dev,
@@ -245,7 +242,7 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
                port->write_urb_busy = 1;
                result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
                if (result) {
-                       dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
+                       dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
                        /* don't have to grab the lock here, as we will retry if != 0 */
                        port->write_urb_busy = 0;
                } else
@@ -263,15 +260,16 @@ int usb_serial_generic_write_room (struct usb_serial_port *port)
        struct usb_serial *serial = port->serial;
        int room = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
+       /* FIXME: Locking */
        if (serial->num_bulk_out) {
                if (!(port->write_urb_busy))
                        room = port->bulk_out_size;
        }
 
-       dbg("%s - returns %d", __FUNCTION__, room);
-       return (room);
+       dbg("%s - returns %d", __func__, room);
+       return room;
 }
 
 int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
@@ -279,14 +277,15 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
        struct usb_serial *serial = port->serial;
        int chars = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
+       /* FIXME: Locking */
        if (serial->num_bulk_out) {
                if (port->write_urb_busy)
                        chars = port->write_urb->transfer_buffer_length;
        }
 
-       dbg("%s - returns %d", __FUNCTION__, chars);
+       dbg("%s - returns %d", __func__, chars);
        return (chars);
 }
 
@@ -308,7 +307,7 @@ static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags)
                             usb_serial_generic_read_bulk_callback), port);
        result = usb_submit_urb(urb, mem_flags);
        if (result)
-               dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+               dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
 }
 
 /* Push data to tty layer and resubmit the bulk read URB */
@@ -332,20 +331,20 @@ static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
 
 void usb_serial_generic_read_bulk_callback (struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        unsigned char *data = urb->transfer_buffer;
        int status = urb->status;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (unlikely(status != 0)) {
                dbg("%s - nonzero read bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+       usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
 
        /* Throttle the device if requested by tty */
        spin_lock_irqsave(&port->lock, flags);
@@ -360,18 +359,17 @@ 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;
+       struct usb_serial_port *port = urb->context;
        int status = urb->status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        port->write_urb_busy = 0;
        if (status) {
                dbg("%s - nonzero write bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        }
-
        usb_serial_port_softint(port);
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
@@ -380,7 +378,7 @@ void usb_serial_generic_throttle (struct usb_serial_port *port)
 {
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /* Set the throttle request flag. It will be picked up
         * by usb_serial_generic_read_bulk_callback(). */
@@ -394,7 +392,7 @@ void usb_serial_generic_unthrottle (struct usb_serial_port *port)
        int was_throttled;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /* Clear the throttle flags */
        spin_lock_irqsave(&port->lock, flags);
@@ -412,7 +410,7 @@ void usb_serial_generic_shutdown (struct usb_serial *serial)
 {
        int i;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /* stop reads and writes on all ports */
        for (i=0; i < serial->num_ports; ++i) {
index 6c6ebae741c98573af1e8c9ee29f5a4344d263fb..75b88b356ebca4408f8f6e28c94d677856aeee4c 100644 (file)
@@ -50,9 +50,6 @@ static struct usb_serial_driver hp49gp_device = {
        },
        .id_table =             id_table,
        .usb_driver =           &hp49gp_driver,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          NUM_DONT_CARE,
-       .num_bulk_out =         NUM_DONT_CARE,
        .num_ports =            1,
 };
 
index 3428ccc28da7ca0a96ee284e0a300ba2a0313632..ce2e487f324042df2bc36904c6a48ffa55c8d4bb 100644 (file)
@@ -371,7 +371,7 @@ static int get_string (struct usb_device *dev, int Id, char *string, int buflen)
        struct usb_string_descriptor StringDesc;
        struct usb_string_descriptor *pStringDesc;
 
-       dbg("%s - USB String ID = %d", __FUNCTION__, Id );
+       dbg("%s - USB String ID = %d", __func__, Id );
 
        if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) {
                return 0;
@@ -391,7 +391,7 @@ static int get_string (struct usb_device *dev, int Id, char *string, int buflen)
        unicode_to_ascii(string, buflen, pStringDesc->wData, pStringDesc->bLength/2);
 
        kfree(pStringDesc);
-       dbg("%s - USB String %s", __FUNCTION__, string);
+       dbg("%s - USB String %s", __func__, string);
        return strlen(string);
 }
 
@@ -407,7 +407,7 @@ static int get_string_desc (struct usb_device *dev, int Id, struct usb_string_de
        struct usb_string_descriptor StringDesc;
        struct usb_string_descriptor *pStringDesc;
 
-       dbg("%s - USB String ID = %d", __FUNCTION__, Id );
+       dbg("%s - USB String ID = %d", __func__, Id );
 
        if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) {
                return 0;
@@ -537,7 +537,7 @@ static int get_epic_descriptor(struct edgeport_serial *ep)
                                 sizeof(struct edge_compatibility_descriptor),
                                 300);
 
-       dbg("%s result = %d", __FUNCTION__, result);
+       dbg("%s result = %d", __func__, result);
 
        if (result > 0) {
                ep->is_epic = 1;
@@ -589,7 +589,7 @@ static int get_epic_descriptor(struct edgeport_serial *ep)
  *****************************************************************************/
 static void edge_interrupt_callback (struct urb *urb)
 {
-       struct edgeport_serial  *edge_serial = (struct edgeport_serial *)urb->context;
+       struct edgeport_serial  *edge_serial = urb->context;
        struct edgeport_port *edge_port;
        struct usb_serial_port *port;
        unsigned char *data = urb->transfer_buffer;
@@ -601,7 +601,7 @@ static void edge_interrupt_callback (struct urb *urb)
        int result;
        int status = urb->status;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        switch (status) {
        case 0:
@@ -612,35 +612,35 @@ static void edge_interrupt_callback (struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                goto exit;
        }
 
        // process this interrupt-read even if there are no ports open
        if (length) {
-               usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __FUNCTION__, length, data);
+               usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, length, data);
 
                if (length > 1) {
                        bytes_avail = data[0] | (data[1] << 8);
                        if (bytes_avail) {
                                spin_lock(&edge_serial->es_lock);
                                edge_serial->rxBytesAvail += bytes_avail;
-                               dbg("%s - bytes_avail=%d, rxBytesAvail=%d, read_in_progress=%d", __FUNCTION__, bytes_avail, edge_serial->rxBytesAvail, edge_serial->read_in_progress);
+                               dbg("%s - bytes_avail=%d, rxBytesAvail=%d, read_in_progress=%d", __func__, bytes_avail, edge_serial->rxBytesAvail, edge_serial->read_in_progress);
 
                                if (edge_serial->rxBytesAvail > 0 &&
                                    !edge_serial->read_in_progress) {
-                                       dbg("%s - posting a read", __FUNCTION__);
+                                       dbg("%s - posting a read", __func__);
                                        edge_serial->read_in_progress = true;
 
                                        /* we have pending bytes on the bulk in pipe, send a request */
                                        edge_serial->read_urb->dev = edge_serial->serial->dev;
                                        result = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
                                        if (result) {
-                                               dev_err(&edge_serial->serial->dev->dev, "%s - usb_submit_urb(read bulk) failed with result = %d\n", __FUNCTION__, result);
+                                               dev_err(&edge_serial->serial->dev->dev, "%s - usb_submit_urb(read bulk) failed with result = %d\n", __func__, result);
                                                edge_serial->read_in_progress = false;
                                        }
                                }
@@ -659,7 +659,7 @@ static void edge_interrupt_callback (struct urb *urb)
                                        spin_lock(&edge_port->ep_lock);
                                        edge_port->txCredits += txCredits;
                                        spin_unlock(&edge_port->ep_lock);
-                                       dbg("%s - txcredits for port%d = %d", __FUNCTION__, portNumber, edge_port->txCredits);
+                                       dbg("%s - txcredits for port%d = %d", __func__, portNumber, edge_port->txCredits);
 
                                        /* tell the tty driver that something has changed */
                                        if (edge_port->port->tty)
@@ -677,7 +677,7 @@ static void edge_interrupt_callback (struct urb *urb)
 exit:
        result = usb_submit_urb (urb, GFP_ATOMIC);
        if (result) {
-               dev_err(&urb->dev->dev, "%s - Error %d submitting control urb\n", __FUNCTION__, result);
+               dev_err(&urb->dev->dev, "%s - Error %d submitting control urb\n", __func__, result);
        }
 }
 
@@ -689,49 +689,49 @@ exit:
  *****************************************************************************/
 static void edge_bulk_in_callback (struct urb *urb)
 {
-       struct edgeport_serial  *edge_serial = (struct edgeport_serial *)urb->context;
+       struct edgeport_serial  *edge_serial = urb->context;
        unsigned char           *data = urb->transfer_buffer;
        int                     retval;
        __u16                   raw_data_length;
        int status = urb->status;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        if (status) {
                dbg("%s - nonzero read bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                edge_serial->read_in_progress = false;
                return;
        }
 
        if (urb->actual_length == 0) {
-               dbg("%s - read bulk callback with no data", __FUNCTION__);
+               dbg("%s - read bulk callback with no data", __func__);
                edge_serial->read_in_progress = false;
                return;
        }
 
        raw_data_length = urb->actual_length;
 
-       usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __FUNCTION__, raw_data_length, data);
+       usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, raw_data_length, data);
 
        spin_lock(&edge_serial->es_lock);
 
        /* decrement our rxBytes available by the number that we just got */
        edge_serial->rxBytesAvail -= raw_data_length;
 
-       dbg("%s - Received = %d, rxBytesAvail %d", __FUNCTION__, raw_data_length, edge_serial->rxBytesAvail);
+       dbg("%s - Received = %d, rxBytesAvail %d", __func__, raw_data_length, edge_serial->rxBytesAvail);
 
        process_rcvd_data (edge_serial, data, urb->actual_length);
 
        /* check to see if there's any more data for us to read */
        if (edge_serial->rxBytesAvail > 0) {
-               dbg("%s - posting a read", __FUNCTION__);
+               dbg("%s - posting a read", __func__);
                edge_serial->read_urb->dev = edge_serial->serial->dev;
                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);
+                               "retval = %d\n", __func__, retval);
                        edge_serial->read_in_progress = false;
                }
        } else {
@@ -749,15 +749,15 @@ static void edge_bulk_in_callback (struct urb *urb)
  *****************************************************************************/
 static void edge_bulk_out_data_callback (struct urb *urb)
 {
-       struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
+       struct edgeport_port *edge_port = urb->context;
        struct tty_struct *tty;
        int status = urb->status;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        if (status) {
                dbg("%s - nonzero write bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
        }
 
        tty = edge_port->port->tty;
@@ -782,14 +782,14 @@ static void edge_bulk_out_data_callback (struct urb *urb)
  *****************************************************************************/
 static void edge_bulk_out_cmd_callback (struct urb *urb)
 {
-       struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
+       struct edgeport_port *edge_port = urb->context;
        struct tty_struct *tty;
        int status = urb->status;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        atomic_dec(&CmdUrbs);
-       dbg("%s - FREE URB %p (outstanding %d)", __FUNCTION__, urb, atomic_read(&CmdUrbs));
+       dbg("%s - FREE URB %p (outstanding %d)", __func__, urb, atomic_read(&CmdUrbs));
 
 
        /* clean up the transfer buffer */
@@ -799,7 +799,7 @@ static void edge_bulk_out_cmd_callback (struct urb *urb)
        usb_free_urb (urb);
 
        if (status) {
-               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, status);
+               dbg("%s - nonzero write bulk status received: %d", __func__, status);
                return;
        }
 
@@ -833,7 +833,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
        struct edgeport_serial *edge_serial;
        int response;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (edge_port == NULL)
                return -ENODEV;
@@ -883,7 +883,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
                 * this interrupt will continue as long as the edgeport is connected */
                response = usb_submit_urb (edge_serial->interrupt_read_urb, GFP_KERNEL);
                if (response) {
-                       dev_err(&port->dev, "%s - Error %d submitting control urb\n", __FUNCTION__, response);
+                       dev_err(&port->dev, "%s - Error %d submitting control urb\n", __func__, response);
                }
        }
        
@@ -907,7 +907,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
        response = send_iosp_ext_cmd (edge_port, IOSP_CMD_OPEN_PORT, 0);
 
        if (response < 0) {
-               dev_err(&port->dev, "%s - error sending open port command\n", __FUNCTION__);
+               dev_err(&port->dev, "%s - error sending open port command\n", __func__);
                edge_port->openPending = false;
                return -ENODEV;
        }
@@ -917,7 +917,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
 
        if (!edge_port->open) {
                /* open timed out */
-               dbg("%s - open timedout", __FUNCTION__);
+               dbg("%s - open timedout", __func__);
                edge_port->openPending = false;
                return -ENODEV;
        }
@@ -930,7 +930,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
        edge_port->txfifo.fifo  = kmalloc (edge_port->maxTxCredits, GFP_KERNEL);
 
        if (!edge_port->txfifo.fifo) {
-               dbg("%s - no memory", __FUNCTION__);
+               dbg("%s - no memory", __func__);
                edge_close (port, filp);
                return -ENOMEM;
        }
@@ -940,14 +940,14 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
        edge_port->write_in_progress = false;
 
        if (!edge_port->write_urb) {
-               dbg("%s - no memory", __FUNCTION__);
+               dbg("%s - no memory", __func__);
                edge_close (port, filp);
                return -ENOMEM;
        }
 
-       dbg("%s(%d) - Initialize TX fifo to %d bytes", __FUNCTION__, port->number, edge_port->maxTxCredits);
+       dbg("%s(%d) - Initialize TX fifo to %d bytes", __func__, port->number, edge_port->maxTxCredits);
 
-       dbg("%s exited", __FUNCTION__);
+       dbg("%s exited", __func__);
 
        return 0;
 }
@@ -976,11 +976,11 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
 
                // Did we get our Chase response
                if (!edge_port->chaseResponsePending) {
-                       dbg("%s - Got Chase Response", __FUNCTION__);
+                       dbg("%s - Got Chase Response", __func__);
 
                        // did we get all of our credit back?
                        if (edge_port->txCredits == edge_port->maxTxCredits ) {
-                               dbg("%s - Got all credits", __FUNCTION__);
+                               dbg("%s - Got all credits", __func__);
                                return;
                        }
                }
@@ -995,12 +995,12 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
                        loop--;
                        if (loop == 0) {
                                edge_port->chaseResponsePending = false;
-                               dbg("%s - Chase TIMEOUT", __FUNCTION__);
+                               dbg("%s - Chase TIMEOUT", __func__);
                                return;
                        }
                } else {
                        // Reset timeout value back to 10 seconds
-                       dbg("%s - Last %d, Current %d", __FUNCTION__, lastCredits, edge_port->txCredits);
+                       dbg("%s - Last %d, Current %d", __func__, lastCredits, edge_port->txCredits);
                        loop = 10;
                }
        }
@@ -1031,7 +1031,7 @@ static void block_until_tx_empty (struct edgeport_port *edge_port)
 
                // Is the Edgeport Buffer empty?
                if (lastCount == 0) {
-                       dbg("%s - TX Buffer Empty", __FUNCTION__);
+                       dbg("%s - TX Buffer Empty", __func__);
                        return;
                }
 
@@ -1040,13 +1040,13 @@ static void block_until_tx_empty (struct edgeport_port *edge_port)
                schedule_timeout(timeout);
                finish_wait(&edge_port->wait_chase, &wait);
 
-               dbg("%s wait", __FUNCTION__);
+               dbg("%s wait", __func__);
 
                if (lastCount == fifo->count) {
                        // No activity.. count down.
                        loop--;
                        if (loop == 0) {
-                               dbg("%s - TIMEOUT", __FUNCTION__);
+                               dbg("%s - TIMEOUT", __func__);
                                return;
                        }
                } else {
@@ -1067,7 +1067,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
        struct edgeport_port *edge_port;
        int status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
                         
        edge_serial = usb_get_serial_data(port->serial);
        edge_port = usb_get_serial_port_data(port);
@@ -1085,7 +1085,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
                /* flush and chase */
                edge_port->chaseResponsePending = true;
 
-               dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__);
+               dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__);
                status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
                if (status == 0) {
                        // block until chase finished
@@ -1099,7 +1099,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
            ((edge_serial->is_epic) &&
             (edge_serial->epic_descriptor.Supports.IOSPClose))) {
               /* close the port */
-               dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __FUNCTION__);
+               dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __func__);
                send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0);
        }
 
@@ -1119,7 +1119,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
        kfree(edge_port->txfifo.fifo);
        edge_port->txfifo.fifo = NULL;
 
-       dbg("%s exited", __FUNCTION__);
+       dbg("%s exited", __func__);
 }   
 
 /*****************************************************************************
@@ -1139,7 +1139,7 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
        int secondhalf;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (edge_port == NULL)
                return -ENODEV;
@@ -1152,12 +1152,12 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
        // calculate number of bytes to put in fifo
        copySize = min ((unsigned int)count, (edge_port->txCredits - fifo->count));
 
-       dbg("%s(%d) of %d byte(s) Fifo room  %d -- will copy %d bytes", __FUNCTION__, 
+       dbg("%s(%d) of %d byte(s) Fifo room  %d -- will copy %d bytes", __func__,
            port->number, count, edge_port->txCredits - fifo->count, copySize);
 
        /* catch writes of 0 bytes which the tty driver likes to give us, and when txCredits is empty */
        if (copySize == 0) {
-               dbg("%s - copySize = Zero", __FUNCTION__);
+               dbg("%s - copySize = Zero", __func__);
                goto finish_write;
        }
 
@@ -1169,11 +1169,11 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
 
        bytesleft = fifo->size - fifo->head;
        firsthalf = min (bytesleft, copySize);
-       dbg("%s - copy %d bytes of %d into fifo ", __FUNCTION__, firsthalf, bytesleft);
+       dbg("%s - copy %d bytes of %d into fifo ", __func__, firsthalf, bytesleft);
 
        /* now copy our data */
        memcpy(&fifo->fifo[fifo->head], data, firsthalf);
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, firsthalf, &fifo->fifo[fifo->head]);
+       usb_serial_debug_data(debug, &port->dev, __func__, firsthalf, &fifo->fifo[fifo->head]);
 
        // update the index and size
        fifo->head  += firsthalf;
@@ -1187,9 +1187,9 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
        secondhalf = copySize-firsthalf;
 
        if (secondhalf) {
-               dbg("%s - copy rest of data %d", __FUNCTION__, secondhalf);
+               dbg("%s - copy rest of data %d", __func__, secondhalf);
                memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf);
-               usb_serial_debug_data(debug, &port->dev, __FUNCTION__, secondhalf, &fifo->fifo[fifo->head]);
+               usb_serial_debug_data(debug, &port->dev, __func__, secondhalf, &fifo->fifo[fifo->head]);
                // update the index and size
                fifo->count += secondhalf;
                fifo->head  += secondhalf;
@@ -1201,7 +1201,7 @@ finish_write:
 
        send_more_port_data((struct edgeport_serial *)usb_get_serial_data(port->serial), edge_port);
 
-       dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __FUNCTION__, copySize, edge_port->txCredits, fifo->count);
+       dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __func__, copySize, edge_port->txCredits, fifo->count);
 
        return copySize;   
 }
@@ -1232,14 +1232,14 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
        int             secondhalf;
        unsigned long   flags;
 
-       dbg("%s(%d)", __FUNCTION__, edge_port->port->number);
+       dbg("%s(%d)", __func__, edge_port->port->number);
 
        spin_lock_irqsave(&edge_port->ep_lock, flags);
 
        if (edge_port->write_in_progress ||
            !edge_port->open             ||
            (fifo->count == 0)) {
-               dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d", __FUNCTION__, edge_port->port->number, fifo->count, edge_port->write_in_progress);
+               dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d", __func__, edge_port->port->number, fifo->count, edge_port->write_in_progress);
                goto exit_send;
        }
 
@@ -1251,7 +1251,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
        //      it's better to wait for more credits so we can do a larger
        //      write.
        if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits,EDGE_FW_BULK_MAX_PACKET_SIZE)) {
-               dbg("%s(%d) Not enough credit - fifo %d TxCredit %d", __FUNCTION__, edge_port->port->number, fifo->count, edge_port->txCredits );
+               dbg("%s(%d) Not enough credit - fifo %d TxCredit %d", __func__, edge_port->port->number, fifo->count, edge_port->txCredits );
                goto exit_send;
        }
 
@@ -1269,7 +1269,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
        count = fifo->count;
        buffer = kmalloc (count+2, GFP_ATOMIC);
        if (buffer == NULL) {
-               dev_err(&edge_port->port->dev, "%s - no more kernel memory...\n", __FUNCTION__);
+               dev_err(&edge_port->port->dev, "%s - no more kernel memory...\n", __func__);
                edge_port->write_in_progress = false;
                goto exit_send;
        }
@@ -1294,7 +1294,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
        }
 
        if (count)
-               usb_serial_debug_data(debug, &edge_port->port->dev, __FUNCTION__, count, &buffer[2]);
+               usb_serial_debug_data(debug, &edge_port->port->dev, __func__, count, &buffer[2]);
 
        /* fill up the urb with all of our data and submit it */
        usb_fill_bulk_urb (urb, edge_serial->serial->dev, 
@@ -1309,14 +1309,14 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
        status = usb_submit_urb(urb, GFP_ATOMIC);
        if (status) {
                /* something went wrong */
-               dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n", __FUNCTION__, status);
+               dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n", __func__, status);
                edge_port->write_in_progress = false;
 
                /* revert the credits as something bad happened. */
                edge_port->txCredits += count;
                edge_port->icount.tx -= count;
        }
-       dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d", __FUNCTION__, count, edge_port->txCredits, fifo->count);
+       dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d", __func__, count, edge_port->txCredits, fifo->count);
 
 exit_send:
        spin_unlock_irqrestore(&edge_port->ep_lock, flags);
@@ -1337,17 +1337,17 @@ static int edge_write_room (struct usb_serial_port *port)
        int room;
        unsigned long flags;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        if (edge_port == NULL)
                return -ENODEV;
        if (edge_port->closePending)
                return -ENODEV;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (!edge_port->open) {
-               dbg("%s - port not opened", __FUNCTION__);
+               dbg("%s - port not opened", __func__);
                return -EINVAL;
        }
 
@@ -1356,7 +1356,7 @@ static int edge_write_room (struct usb_serial_port *port)
        room = edge_port->txCredits - edge_port->txfifo.count;
        spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 
-       dbg("%s - returns %d", __FUNCTION__, room);
+       dbg("%s - returns %d", __func__, room);
        return room;
 }
 
@@ -1376,7 +1376,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
        int num_chars;
        unsigned long flags;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        if (edge_port == NULL)
                return -ENODEV;
@@ -1384,7 +1384,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
                return -ENODEV;
 
        if (!edge_port->open) {
-               dbg("%s - port not opened", __FUNCTION__);
+               dbg("%s - port not opened", __func__);
                return -EINVAL;
        }
 
@@ -1392,7 +1392,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
        num_chars = edge_port->maxTxCredits - edge_port->txCredits + edge_port->txfifo.count;
        spin_unlock_irqrestore(&edge_port->ep_lock, flags);
        if (num_chars) {
-               dbg("%s(port %d) - returns %d", __FUNCTION__, port->number, num_chars);
+               dbg("%s(port %d) - returns %d", __func__, port->number, num_chars);
        }
 
        return num_chars;
@@ -1410,19 +1410,19 @@ static void edge_throttle (struct usb_serial_port *port)
        struct tty_struct *tty;
        int status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (edge_port == NULL)
                return;
 
        if (!edge_port->open) {
-               dbg("%s - port not opened", __FUNCTION__);
+               dbg("%s - port not opened", __func__);
                return;
        }
 
        tty = port->tty;
        if (!tty) {
-               dbg ("%s - no tty available", __FUNCTION__);
+               dbg ("%s - no tty available", __func__);
                return;
        }
 
@@ -1459,19 +1459,19 @@ static void edge_unthrottle (struct usb_serial_port *port)
        struct tty_struct *tty;
        int status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (edge_port == NULL)
                return;
 
        if (!edge_port->open) {
-               dbg("%s - port not opened", __FUNCTION__);
+               dbg("%s - port not opened", __func__);
                return;
        }
 
        tty = port->tty;
        if (!tty) {
-               dbg ("%s - no tty available", __FUNCTION__);
+               dbg ("%s - no tty available", __func__);
                return;
        }
 
@@ -1509,18 +1509,18 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
        unsigned int cflag;
 
        cflag = tty->termios->c_cflag;
-       dbg("%s - clfag %08x iflag %08x", __FUNCTION__, 
+       dbg("%s - clfag %08x iflag %08x", __func__,
            tty->termios->c_cflag, tty->termios->c_iflag);
-       dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
+       dbg("%s - old clfag %08x old iflag %08x", __func__,
            old_termios->c_cflag, old_termios->c_iflag);
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (edge_port == NULL)
                return;
 
        if (!edge_port->open) {
-               dbg("%s - port not opened", __FUNCTION__);
+               dbg("%s - port not opened", __func__);
                return;
        }
 
@@ -1549,7 +1549,7 @@ static int get_lsr_info(struct edgeport_port *edge_port, unsigned int __user *va
        spin_lock_irqsave(&edge_port->ep_lock, flags);
        if (edge_port->maxTxCredits == edge_port->txCredits &&
            edge_port->txfifo.count == 0) {
-               dbg("%s -- Empty", __FUNCTION__);
+               dbg("%s -- Empty", __func__);
                result = TIOCSER_TEMT;
        }
        spin_unlock_irqrestore(&edge_port->ep_lock, flags);
@@ -1569,7 +1569,7 @@ static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int
 
        result = tty->read_cnt;
 
-       dbg("%s(%d) = %d", __FUNCTION__,  edge_port->port->number, result);
+       dbg("%s(%d) = %d", __func__,  edge_port->port->number, result);
        if (copy_to_user(value, &result, sizeof(int)))
                return -EFAULT;
        //return 0;
@@ -1581,7 +1581,7 @@ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsig
        struct edgeport_port *edge_port = usb_get_serial_port_data(port);
        unsigned int mcr;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        mcr = edge_port->shadowMCR;
        if (set & TIOCM_RTS)
@@ -1612,7 +1612,7 @@ static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
        unsigned int msr;
        unsigned int mcr;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        msr = edge_port->shadowMSR;
        mcr = edge_port->shadowMCR;
@@ -1624,7 +1624,7 @@ static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
                  | ((msr & EDGEPORT_MSR_DSR)   ? TIOCM_DSR: 0);  /* 0x100 */
 
 
-       dbg("%s -- %x", __FUNCTION__, result);
+       dbg("%s -- %x", __func__, result);
 
        return result;
 }
@@ -1670,30 +1670,30 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
        struct async_icount cprev;
        struct serial_icounter_struct icount;
 
-       dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
+       dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
 
        switch (cmd) {
                // return number of bytes available
                case TIOCINQ:
-                       dbg("%s (%d) TIOCINQ", __FUNCTION__,  port->number);
+                       dbg("%s (%d) TIOCINQ", __func__,  port->number);
                        return get_number_bytes_avail(edge_port, (unsigned int __user *) arg);
                        break;
 
                case TIOCSERGETLSR:
-                       dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__,  port->number);
+                       dbg("%s (%d) TIOCSERGETLSR", __func__,  port->number);
                        return get_lsr_info(edge_port, (unsigned int __user *) arg);
                        return 0;
 
                case TIOCGSERIAL:
-                       dbg("%s (%d) TIOCGSERIAL", __FUNCTION__,  port->number);
+                       dbg("%s (%d) TIOCGSERIAL", __func__,  port->number);
                        return get_serial_info(edge_port, (struct serial_struct __user *) arg);
 
                case TIOCSSERIAL:
-                       dbg("%s (%d) TIOCSSERIAL", __FUNCTION__,  port->number);
+                       dbg("%s (%d) TIOCSSERIAL", __func__,  port->number);
                        break;
 
                case TIOCMIWAIT:
-                       dbg("%s (%d) TIOCMIWAIT", __FUNCTION__,  port->number);
+                       dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
                        cprev = edge_port->icount;
                        while (1) {
                                prepare_to_wait(&edge_port->delta_msr_wait, &wait, TASK_INTERRUPTIBLE);
@@ -1732,7 +1732,7 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
                        icount.brk = cnow.brk;
                        icount.buf_overrun = cnow.buf_overrun;
 
-                       dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,  port->number, icount.rx, icount.tx );
+                       dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,  port->number, icount.rx, icount.tx );
                        if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
                                return -EFAULT;
                        return 0;
@@ -1758,7 +1758,7 @@ static void edge_break (struct usb_serial_port *port, int break_state)
                /* flush and chase */
                edge_port->chaseResponsePending = true;
 
-               dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__);
+               dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__);
                status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
                if (status == 0) {
                        // block until chase finished
@@ -1772,14 +1772,14 @@ static void edge_break (struct usb_serial_port *port, int break_state)
            ((edge_serial->is_epic) &&
             (edge_serial->epic_descriptor.Supports.IOSPSetClrBreak))) {
                if (break_state == -1) {
-                       dbg("%s - Sending IOSP_CMD_SET_BREAK", __FUNCTION__);
+                       dbg("%s - Sending IOSP_CMD_SET_BREAK", __func__);
                        status = send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_BREAK, 0);
                } else {
-                       dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __FUNCTION__);
+                       dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __func__);
                        status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CLEAR_BREAK, 0);
                }
                if (status) {
-                       dbg("%s - error sending break set/clear command.", __FUNCTION__);
+                       dbg("%s - error sending break set/clear command.", __func__);
                }
        }
 
@@ -1799,14 +1799,14 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha
        __u16 lastBufferLength;
        __u16 rxLen;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        lastBufferLength = bufferLength + 1;
 
        while (bufferLength > 0) {
                /* failsafe incase we get a message that we don't understand */
                if (lastBufferLength == bufferLength) {
-                       dbg("%s - stuck in loop, exiting it.", __FUNCTION__);
+                       dbg("%s - stuck in loop, exiting it.", __func__);
                        break;
                }
                lastBufferLength = bufferLength;
@@ -1828,7 +1828,7 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha
                                ++buffer;
                                --bufferLength;
 
-                               dbg("%s - Hdr1=%02X Hdr2=%02X", __FUNCTION__, edge_serial->rxHeader1, edge_serial->rxHeader2);
+                               dbg("%s - Hdr1=%02X Hdr2=%02X", __func__, edge_serial->rxHeader1, edge_serial->rxHeader2);
 
                                // Process depending on whether this header is
                                // data or status
@@ -1858,7 +1858,7 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha
                                        edge_serial->rxPort = IOSP_GET_HDR_PORT(edge_serial->rxHeader1);
                                        edge_serial->rxBytesRemaining = IOSP_GET_HDR_DATA_LEN(edge_serial->rxHeader1, edge_serial->rxHeader2);
 
-                                       dbg("%s - Data for Port %u Len %u", __FUNCTION__, edge_serial->rxPort, edge_serial->rxBytesRemaining);
+                                       dbg("%s - Data for Port %u Len %u", __func__, edge_serial->rxPort, edge_serial->rxBytesRemaining);
 
                                        //ASSERT( DevExt->RxPort < DevExt->NumPorts );
                                        //ASSERT( DevExt->RxBytesRemaining < IOSP_MAX_DATA_LENGTH );
@@ -1891,7 +1891,7 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha
                                        if (edge_port->open) {
                                                tty = edge_port->port->tty;
                                                if (tty) {
-                                                       dbg("%s - Sending %d bytes to TTY for port %d", __FUNCTION__, rxLen, edge_serial->rxPort);
+                                                       dbg("%s - Sending %d bytes to TTY for port %d", __func__, rxLen, edge_serial->rxPort);
                                                        edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen);
                                                }
                                                edge_port->icount.rx += rxLen;
@@ -1930,17 +1930,17 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
        port = edge_serial->serial->port[edge_serial->rxPort];
        edge_port = usb_get_serial_port_data(port);
        if (edge_port == NULL) {
-               dev_err(&edge_serial->serial->dev->dev, "%s - edge_port == NULL for port %d\n", __FUNCTION__, edge_serial->rxPort);
+               dev_err(&edge_serial->serial->dev->dev, "%s - edge_port == NULL for port %d\n", __func__, edge_serial->rxPort);
                return;
        }
 
-       dbg("%s - port %d", __FUNCTION__, edge_serial->rxPort);
+       dbg("%s - port %d", __func__, edge_serial->rxPort);
 
        if (code == IOSP_EXT_STATUS) {
                switch (byte2) {
                        case IOSP_EXT_STATUS_CHASE_RSP:
                                // we want to do EXT status regardless of port open/closed 
-                               dbg("%s - Port %u EXT CHASE_RSP Data = %02x", __FUNCTION__, edge_serial->rxPort, byte3 );
+                               dbg("%s - Port %u EXT CHASE_RSP Data = %02x", __func__, edge_serial->rxPort, byte3 );
                                // Currently, the only EXT_STATUS is Chase, so process here instead of one more call
                                // to one more subroutine. If/when more EXT_STATUS, there'll be more work to do.
                                // Also, we currently clear flag and close the port regardless of content of above's Byte3.
@@ -1951,7 +1951,7 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
                                return;
 
                        case IOSP_EXT_STATUS_RX_CHECK_RSP:
-                               dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __FUNCTION__, edge_serial->rxPort, byte3 );
+                               dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __func__, edge_serial->rxPort, byte3 );
                                //Port->RxCheckRsp = true;
                                return;
                }
@@ -1960,7 +1960,7 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
        if (code == IOSP_STATUS_OPEN_RSP) {
                edge_port->txCredits = GET_TX_BUFFER_SIZE(byte3);
                edge_port->maxTxCredits = edge_port->txCredits;
-               dbg("%s - Port %u Open Response Inital MSR = %02x TxBufferSize = %d", __FUNCTION__, edge_serial->rxPort, byte2, edge_port->txCredits);
+               dbg("%s - Port %u Open Response Inital MSR = %02x TxBufferSize = %d", __func__, edge_serial->rxPort, byte2, edge_port->txCredits);
                handle_new_msr (edge_port, byte2);
 
                /* send the current line settings to the port so we are in sync with any further termios calls */
@@ -1984,23 +1984,23 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
        switch (code) {
                // Not currently sent by Edgeport
                case IOSP_STATUS_LSR:
-                       dbg("%s - Port %u LSR Status = %02x", __FUNCTION__, edge_serial->rxPort, byte2);
+                       dbg("%s - Port %u LSR Status = %02x", __func__, edge_serial->rxPort, byte2);
                        handle_new_lsr(edge_port, false, byte2, 0);
                        break;
 
                case IOSP_STATUS_LSR_DATA:
-                       dbg("%s - Port %u LSR Status = %02x, Data = %02x", __FUNCTION__, edge_serial->rxPort, byte2, byte3);
+                       dbg("%s - Port %u LSR Status = %02x, Data = %02x", __func__, edge_serial->rxPort, byte2, byte3);
                        // byte2 is LSR Register
                        // byte3 is broken data byte
                        handle_new_lsr(edge_port, true, byte2, byte3);
                        break;
                        //
                        //      case IOSP_EXT_4_STATUS:
-                       //              dbg("%s - Port %u LSR Status = %02x Data = %02x", __FUNCTION__, edge_serial->rxPort, byte2, byte3);
+                       //              dbg("%s - Port %u LSR Status = %02x Data = %02x", __func__, edge_serial->rxPort, byte2, byte3);
                        //              break;
                        //
                case IOSP_STATUS_MSR:
-                       dbg("%s - Port %u MSR Status = %02x", __FUNCTION__, edge_serial->rxPort, byte2);
+                       dbg("%s - Port %u MSR Status = %02x", __func__, edge_serial->rxPort, byte2);
 
                        // Process this new modem status and generate appropriate
                        // events, etc, based on the new status. This routine
@@ -2009,7 +2009,7 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
                        break;
 
                default:
-                       dbg("%s - Unrecognized IOSP status code %u\n", __FUNCTION__, code);
+                       dbg("%s - Unrecognized IOSP status code %u\n", __func__, code);
                        break;
        }
 
@@ -2029,7 +2029,7 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
                cnt = tty_buffer_request_room(tty, length);
                if (cnt < length) {
                        dev_err(dev, "%s - dropping data, %d bytes lost\n",
-                                       __FUNCTION__, length - cnt);
+                                       __func__, length - cnt);
                        if(cnt == 0)
                                break;
                }
@@ -2050,7 +2050,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
 {
        struct  async_icount *icount;
 
-       dbg("%s %02x", __FUNCTION__, newMsr);
+       dbg("%s %02x", __func__, newMsr);
 
        if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
                icount = &edge_port->icount;
@@ -2087,7 +2087,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, __u8 l
        __u8    newLsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
        struct  async_icount *icount;
 
-       dbg("%s - %02x", __FUNCTION__, newLsr);
+       dbg("%s - %02x", __func__, newLsr);
 
        edge_port->shadowLSR = lsr;
 
@@ -2136,11 +2136,11 @@ static int sram_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u
        __u16 current_length;
        unsigned char *transfer_buffer;
 
-       dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
+       dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
 
        transfer_buffer =  kmalloc (64, GFP_KERNEL);
        if (!transfer_buffer) {
-               dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 64);
+               dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
                return -ENOMEM;
        }
 
@@ -2152,7 +2152,7 @@ static int sram_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u
                } else {
                        current_length = length;
                }
-//             dbg("%s - writing %x, %x, %d", __FUNCTION__, extAddr, addr, current_length);
+//             dbg("%s - writing %x, %x, %d", __func__, extAddr, addr, current_length);
                memcpy (transfer_buffer, data, current_length);
                result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_RAM, 
                                          0x40, addr, extAddr, transfer_buffer, current_length, 300);
@@ -2181,11 +2181,11 @@ static int rom_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u1
        __u16 current_length;
        unsigned char *transfer_buffer;
 
-//     dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
+//     dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
 
        transfer_buffer =  kmalloc (64, GFP_KERNEL);
        if (!transfer_buffer) {
-               dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 64);
+               dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
                return -ENOMEM;
        }
 
@@ -2197,7 +2197,7 @@ static int rom_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u1
                } else {
                        current_length = length;
                }
-//             dbg("%s - writing %x, %x, %d", __FUNCTION__, extAddr, addr, current_length);
+//             dbg("%s - writing %x, %x, %d", __func__, extAddr, addr, current_length);
                memcpy (transfer_buffer, data, current_length);
                result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_ROM, 
                                          0x40, addr, extAddr, transfer_buffer, current_length, 300);
@@ -2226,11 +2226,11 @@ static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16
        __u16 current_length;
        unsigned char *transfer_buffer;
 
-       dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
+       dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
 
        transfer_buffer =  kmalloc (64, GFP_KERNEL);
        if (!transfer_buffer) {
-               dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 64);
+               dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
                return -ENOMEM;
        }
 
@@ -2242,7 +2242,7 @@ static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16
                } else {
                        current_length = length;
                }
-//             dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, current_length);
+//             dbg("%s - %x, %x, %d", __func__, extAddr, addr, current_length);
                result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), USB_REQUEST_ION_READ_ROM, 
                                          0xC0, addr, extAddr, transfer_buffer, current_length, 300);
                if (result < 0)
@@ -2269,11 +2269,11 @@ static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u
        int             length = 0;
        int             status = 0;
 
-       dbg("%s - %d, %d", __FUNCTION__, command, param);
+       dbg("%s - %d, %d", __func__, command, param);
 
        buffer =  kmalloc (10, GFP_ATOMIC);
        if (!buffer) {
-               dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 10);
+               dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __func__, 10);
                return -ENOMEM;
        }
 
@@ -2304,7 +2304,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
        struct urb *urb;
        int timeout;
 
-       usb_serial_debug_data(debug, &edge_port->port->dev, __FUNCTION__, length, buffer);
+       usb_serial_debug_data(debug, &edge_port->port->dev, __func__, length, buffer);
 
        /* Allocate our next urb */
        urb = usb_alloc_urb (0, GFP_ATOMIC);
@@ -2312,7 +2312,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
                return -ENOMEM;
 
        atomic_inc(&CmdUrbs);
-       dbg("%s - ALLOCATE URB %p (outstanding %d)", __FUNCTION__, urb, atomic_read(&CmdUrbs));
+       dbg("%s - ALLOCATE URB %p (outstanding %d)", __func__, urb, atomic_read(&CmdUrbs));
 
        usb_fill_bulk_urb (urb, edge_serial->serial->dev, 
                       usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint),
@@ -2323,7 +2323,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
 
        if (status) {
                /* something went wrong */
-               dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write command) failed, status = %d\n", __FUNCTION__, status);
+               dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write command) failed, status = %d\n", __func__, status);
                usb_kill_urb(urb);
                usb_free_urb(urb);
                atomic_dec(&CmdUrbs);
@@ -2337,7 +2337,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
 
        if (edge_port->commandPending) {
                /* command timed out */
-               dbg("%s - command timed out", __FUNCTION__);
+               dbg("%s - command timed out", __func__);
                status = -EINVAL;
        }
 #endif
@@ -2367,18 +2367,18 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa
                return 0;
        }
 
-       dbg("%s - port = %d, baud = %d", __FUNCTION__, edge_port->port->number, baudRate);
+       dbg("%s - port = %d, baud = %d", __func__, edge_port->port->number, baudRate);
 
        status = calc_baud_rate_divisor (baudRate, &divisor);
        if (status) {
-               dev_err(&edge_port->port->dev, "%s - bad baud rate\n", __FUNCTION__);
+               dev_err(&edge_port->port->dev, "%s - bad baud rate\n", __func__);
                return status;
        }
 
        // Alloc memory for the string of commands.
        cmdBuffer =  kmalloc (0x100, GFP_ATOMIC);
        if (!cmdBuffer) {
-               dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 0x100);
+               dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __func__, 0x100);
                return -ENOMEM;
        }
        currCmd = cmdBuffer;
@@ -2414,7 +2414,7 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor)
        __u16 custom;
 
 
-       dbg("%s - %d", __FUNCTION__, baudrate);
+       dbg("%s - %d", __func__, baudrate);
 
        for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {
                if ( divisor_table[i].BaudRate == baudrate ) {
@@ -2432,7 +2432,7 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor)
 
                *divisor = custom;
 
-               dbg("%s - Baud %d = %d\n", __FUNCTION__, baudrate, custom);
+               dbg("%s - Baud %d = %d\n", __func__, baudrate, custom);
                return 0;
        }
 
@@ -2452,7 +2452,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
        unsigned long cmdLen = 0;
        int status;
 
-       dbg("%s - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", __FUNCTION__, regValue);
+       dbg("%s - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", __func__, regValue);
 
        if (edge_serial->is_epic &&
            !edge_serial->epic_descriptor.Supports.IOSPWriteMCR &&
@@ -2513,29 +2513,29 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
        __u8 txFlow;
        int status;
 
-       dbg("%s - port %d", __FUNCTION__, edge_port->port->number);
+       dbg("%s - port %d", __func__, edge_port->port->number);
 
        if (!edge_port->open &&
            !edge_port->openPending) {
-               dbg("%s - port not opened", __FUNCTION__);
+               dbg("%s - port not opened", __func__);
                return;
        }
 
        tty = edge_port->port->tty;
        if ((!tty) ||
            (!tty->termios)) {
-               dbg("%s - no tty structures", __FUNCTION__);
+               dbg("%s - no tty structures", __func__);
                return;
        }
 
        cflag = tty->termios->c_cflag;
 
        switch (cflag & CSIZE) {
-               case CS5:   lData = LCR_BITS_5; mask = 0x1f;    dbg("%s - data bits = 5", __FUNCTION__);   break;
-               case CS6:   lData = LCR_BITS_6; mask = 0x3f;    dbg("%s - data bits = 6", __FUNCTION__);   break;
-               case CS7:   lData = LCR_BITS_7; mask = 0x7f;    dbg("%s - data bits = 7", __FUNCTION__);   break;
+               case CS5:   lData = LCR_BITS_5; mask = 0x1f;    dbg("%s - data bits = 5", __func__);   break;
+               case CS6:   lData = LCR_BITS_6; mask = 0x3f;    dbg("%s - data bits = 6", __func__);   break;
+               case CS7:   lData = LCR_BITS_7; mask = 0x7f;    dbg("%s - data bits = 7", __func__);   break;
                default:
-               case CS8:   lData = LCR_BITS_8;                 dbg("%s - data bits = 8", __FUNCTION__);   break;
+               case CS8:   lData = LCR_BITS_8;                 dbg("%s - data bits = 8", __func__);   break;
        }
 
        lParity = LCR_PAR_NONE;
@@ -2543,28 +2543,28 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
                if (cflag & CMSPAR) {
                        if (cflag & PARODD) {
                                lParity = LCR_PAR_MARK;
-                               dbg("%s - parity = mark", __FUNCTION__);
+                               dbg("%s - parity = mark", __func__);
                        } else {
                                lParity = LCR_PAR_SPACE;
-                               dbg("%s - parity = space", __FUNCTION__);
+                               dbg("%s - parity = space", __func__);
                        }
                } else if (cflag & PARODD) {
                        lParity = LCR_PAR_ODD;
-                       dbg("%s - parity = odd", __FUNCTION__);
+                       dbg("%s - parity = odd", __func__);
                } else {
                        lParity = LCR_PAR_EVEN;
-                       dbg("%s - parity = even", __FUNCTION__);
+                       dbg("%s - parity = even", __func__);
                }
        } else {
-               dbg("%s - parity = none", __FUNCTION__);
+               dbg("%s - parity = none", __func__);
        }
 
        if (cflag & CSTOPB) {
                lStop = LCR_STOP_2;
-               dbg("%s - stop bits = 2", __FUNCTION__);
+               dbg("%s - stop bits = 2", __func__);
        } else {
                lStop = LCR_STOP_1;
-               dbg("%s - stop bits = 1", __FUNCTION__);
+               dbg("%s - stop bits = 1", __func__);
        }
 
        /* figure out the flow control settings */
@@ -2572,9 +2572,9 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
        if (cflag & CRTSCTS) {
                rxFlow |= IOSP_RX_FLOW_RTS;
                txFlow |= IOSP_TX_FLOW_CTS;
-               dbg("%s - RTS/CTS is enabled", __FUNCTION__);
+               dbg("%s - RTS/CTS is enabled", __func__);
        } else {
-               dbg("%s - RTS/CTS is disabled", __FUNCTION__);
+               dbg("%s - RTS/CTS is disabled", __func__);
        }
 
        /* if we are implementing XON/XOFF, set the start and stop character in the device */
@@ -2592,17 +2592,17 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
                /* if we are implementing INBOUND XON/XOFF */
                if (I_IXOFF(tty)) {
                        rxFlow |= IOSP_RX_FLOW_XON_XOFF;
-                       dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __FUNCTION__, start_char, stop_char);
+                       dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __func__, start_char, stop_char);
                } else {
-                       dbg("%s - INBOUND XON/XOFF is disabled", __FUNCTION__);
+                       dbg("%s - INBOUND XON/XOFF is disabled", __func__);
                }
 
                /* if we are implementing OUTBOUND XON/XOFF */
                if (I_IXON(tty)) {
                        txFlow |= IOSP_TX_FLOW_XON_XOFF;
-                       dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __FUNCTION__, start_char, stop_char);
+                       dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __func__, start_char, stop_char);
                } else {
-                       dbg("%s - OUTBOUND XON/XOFF is disabled", __FUNCTION__);
+                       dbg("%s - OUTBOUND XON/XOFF is disabled", __func__);
                }
        }
 
@@ -2645,7 +2645,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
                baud = 9600;
        }
 
-       dbg("%s - baud rate = %d", __FUNCTION__, baud);
+       dbg("%s - baud rate = %d", __func__, baud);
        status = send_cmd_write_baud_rate (edge_port, baud);
        if (status == -1) {
                /* Speed change was not possible - put back the old speed */
@@ -2843,7 +2843,7 @@ static int edge_startup (struct usb_serial *serial)
        /* create our private serial structure */
        edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
        if (edge_serial == NULL) {
-               dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
+               dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
                return -ENOMEM;
        }
        spin_lock_init(&edge_serial->es_lock);
@@ -2885,19 +2885,19 @@ static int edge_startup (struct usb_serial *serial)
                         serial->num_ports);
        }
 
-       dbg("%s - time 1 %ld", __FUNCTION__, jiffies);
+       dbg("%s - time 1 %ld", __func__, jiffies);
 
        /* If not an EPiC device */
        if (!edge_serial->is_epic) {
                /* now load the application firmware into this device */
                load_application_firmware (edge_serial);
 
-               dbg("%s - time 2 %ld", __FUNCTION__, jiffies);
+               dbg("%s - time 2 %ld", __func__, jiffies);
 
                /* Check current Edgeport EEPROM and update if necessary */
                update_edgeport_E2PROM (edge_serial);
 
-               dbg("%s - time 3 %ld", __FUNCTION__, jiffies);
+               dbg("%s - time 3 %ld", __func__, jiffies);
 
                /* set the configuration to use #1 */
 //             dbg("set_configuration 1");
@@ -2911,7 +2911,7 @@ static int edge_startup (struct usb_serial *serial)
        for (i = 0; i < serial->num_ports; ++i) {
                edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL);
                if (edge_port == NULL) {
-                       dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
+                       dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
                        for (j = 0; j < i; ++j) {
                                kfree (usb_get_serial_port_data(serial->port[j]));
                                usb_set_serial_port_data(serial->port[j],  NULL);
@@ -3017,7 +3017,7 @@ static int edge_startup (struct usb_serial *serial)
                 * continue as long as the edgeport is connected */
                response = usb_submit_urb(edge_serial->interrupt_read_urb, GFP_KERNEL);
                if (response)
-                       err("%s - Error %d submitting control urb", __FUNCTION__, response);
+                       err("%s - Error %d submitting control urb", __func__, response);
        }
        return response;
 }
@@ -3032,7 +3032,7 @@ static void edge_shutdown (struct usb_serial *serial)
        struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
        int i;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /* stop reads and writes on all ports */
        for (i=0; i < serial->num_ports; ++i) {
index 6d3008772540fc2eccbda153930195a574216cf9..2ec85893f27abc8f8877d0fcfe23aad58db17dbd 100644 (file)
@@ -111,9 +111,6 @@ static struct usb_serial_driver edgeport_2port_device = {
        .description            = "Edgeport 2 port adapter",
        .usb_driver             = &io_driver,
        .id_table               = edgeport_2port_id_table,
-       .num_interrupt_in       = 1,
-       .num_bulk_in            = 1,
-       .num_bulk_out           = 1,
        .num_ports              = 2,
        .open                   = edge_open,
        .close                  = edge_close,
@@ -142,9 +139,6 @@ static struct usb_serial_driver edgeport_4port_device = {
        .description            = "Edgeport 4 port adapter",
        .usb_driver             = &io_driver,
        .id_table               = edgeport_4port_id_table,
-       .num_interrupt_in       = 1,
-       .num_bulk_in            = 1,
-       .num_bulk_out           = 1,
        .num_ports              = 4,
        .open                   = edge_open,
        .close                  = edge_close,
@@ -173,9 +167,6 @@ static struct usb_serial_driver edgeport_8port_device = {
        .description            = "Edgeport 8 port adapter",
        .usb_driver             = &io_driver,
        .id_table               = edgeport_8port_id_table,
-       .num_interrupt_in       = 1,
-       .num_bulk_in            = 1,
-       .num_bulk_out           = 1,
        .num_ports              = 8,
        .open                   = edge_open,
        .close                  = edge_close,
@@ -203,9 +194,6 @@ static struct usb_serial_driver epic_device = {
        },
        .description            = "EPiC device",
        .id_table               = Epic_port_id_table,
-       .num_interrupt_in       = 1,
-       .num_bulk_in            = 1,
-       .num_bulk_out           = 1,
        .num_ports              = 1,
        .open                   = edge_open,
        .close                  = edge_close,
index e5ea5ef6335d1acc42e3049fe507eb92b35a3222..05e4fa730730fb4439b72f3a4cdfb658d0d445f0 100644 (file)
@@ -290,7 +290,7 @@ static int TIReadVendorRequestSync (struct usb_device *dev,
                return status;
        if (status != size) {
                dbg ("%s - wanted to write %d, but only wrote %d",
-                    __FUNCTION__, size, status);
+                    __func__, size, status);
                return -ECOMM;
        }
        return 0;
@@ -320,7 +320,7 @@ static int TISendVendorRequestSync (struct usb_device *dev,
                return status;
        if (status != size) {
                dbg ("%s - wanted to write %d, but only wrote %d",
-                    __FUNCTION__, size, status);
+                    __func__, size, status);
                return -ECOMM;
        }
        return 0;
@@ -344,7 +344,7 @@ static int TIPurgeDataSync (struct usb_serial_port *port, __u16 mask)
 {
        int port_number = port->number - port->serial->minor;
 
-       dbg ("%s - port %d, mask %x", __FUNCTION__, port_number, mask);
+       dbg ("%s - port %d, mask %x", __func__, port_number, mask);
 
        return TIWriteCommandSync (port->serial->dev,
                                        UMPC_PURGE_PORT,
@@ -369,7 +369,7 @@ static int TIReadDownloadMemory(struct usb_device *dev, int start_address,
        __u8 read_length;
        __be16 be_start_address;
        
-       dbg ("%s - @ %x for %d", __FUNCTION__, start_address, length);
+       dbg ("%s - @ %x for %d", __func__, start_address, length);
 
        /* Read in blocks of 64 bytes
         * (TI firmware can't handle more than 64 byte reads)
@@ -381,7 +381,7 @@ static int TIReadDownloadMemory(struct usb_device *dev, int start_address,
                        read_length = (__u8)length;
 
                if (read_length > 1) {
-                       dbg ("%s - @ %x for %d", __FUNCTION__, 
+                       dbg ("%s - @ %x for %d", __func__,
                             start_address, read_length);
                }
                be_start_address = cpu_to_be16 (start_address);
@@ -393,12 +393,12 @@ static int TIReadDownloadMemory(struct usb_device *dev, int start_address,
                                                  read_length); // TransferBufferLength
 
                if (status) {
-                       dbg ("%s - ERROR %x", __FUNCTION__, status);
+                       dbg ("%s - ERROR %x", __func__, status);
                        return status;
                }
 
                if (read_length > 1) {
-                       usb_serial_debug_data(debug, &dev->dev, __FUNCTION__,
+                       usb_serial_debug_data(debug, &dev->dev, __func__,
                                              read_length, buffer);
                }
 
@@ -434,13 +434,13 @@ static int TIReadBootMemory (struct edgeport_serial *serial, int start_address,
                                        &buffer[i],                     // TransferBuffer
                                        0x01);                          // TransferBufferLength
                if (status) {
-                       dbg ("%s - ERROR %x", __FUNCTION__, status);
+                       dbg ("%s - ERROR %x", __func__, status);
                        return status;
                }
        }
 
-       dbg ("%s - start_address = %x, length = %d", __FUNCTION__, start_address, length);
-       usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, length, buffer);
+       dbg ("%s - start_address = %x, length = %d", __func__, start_address, length);
+       usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, length, buffer);
 
        serial->TiReadI2C = 1;
 
@@ -472,8 +472,8 @@ static int TIWriteBootMemory (struct edgeport_serial *serial, int start_address,
                        return status;
        }
 
-       dbg ("%s - start_sddr = %x, length = %d", __FUNCTION__, start_address, length);
-       usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, length, buffer);
+       dbg ("%s - start_sddr = %x, length = %d", __func__, start_address, length);
+       usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, length, buffer);
 
        return status;
 }
@@ -494,8 +494,8 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
        if (write_length > length)
                write_length = length;
 
-       dbg ("%s - BytesInFirstPage Addr = %x, length = %d", __FUNCTION__, start_address, write_length);
-       usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, write_length, buffer);
+       dbg ("%s - BytesInFirstPage Addr = %x, length = %d", __func__, start_address, write_length);
+       usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, write_length, buffer);
 
        /* Write first page */
        be_start_address = cpu_to_be16 (start_address);
@@ -506,7 +506,7 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
                                        buffer,                 // TransferBuffer
                                        write_length);
        if (status) {
-               dbg ("%s - ERROR %d", __FUNCTION__, status);
+               dbg ("%s - ERROR %d", __func__, status);
                return status;
        }
 
@@ -521,8 +521,8 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
                else
                        write_length = length;
 
-               dbg ("%s - Page Write Addr = %x, length = %d", __FUNCTION__, start_address, write_length);
-               usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, write_length, buffer);
+               dbg ("%s - Page Write Addr = %x, length = %d", __func__, start_address, write_length);
+               usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, write_length, buffer);
 
                /* Write next page */
                be_start_address = cpu_to_be16 (start_address);
@@ -533,7 +533,7 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
                                                buffer,                 // TransferBuffer
                                                write_length);          // TransferBufferLength
                if (status) {
-                       dev_err (&serial->serial->dev->dev, "%s - ERROR %d\n", __FUNCTION__, status);
+                       dev_err (&serial->serial->dev->dev, "%s - ERROR %d\n", __func__, status);
                        return status;
                }
                
@@ -559,7 +559,7 @@ static int TIIsTxActive (struct edgeport_port *port)
 
        oedb = kmalloc (sizeof (* oedb), GFP_KERNEL);
        if (!oedb) {
-               dev_err (&port->port->dev, "%s - out of memory\n", __FUNCTION__);
+               dev_err (&port->port->dev, "%s - out of memory\n", __func__);
                return -ENOMEM;
        }
 
@@ -579,7 +579,7 @@ static int TIIsTxActive (struct edgeport_port *port)
        if (status)
                goto exit_is_tx_active;
 
-       dbg ("%s - XByteCount    0x%X", __FUNCTION__, oedb->XByteCount);
+       dbg ("%s - XByteCount    0x%X", __func__, oedb->XByteCount);
 
        /* and the LSR */
        status = TIReadRam (port->port->serial->dev, 
@@ -589,7 +589,7 @@ static int TIIsTxActive (struct edgeport_port *port)
 
        if (status)
                goto exit_is_tx_active;
-       dbg ("%s - LSR = 0x%X", __FUNCTION__, *lsr);
+       dbg ("%s - LSR = 0x%X", __func__, *lsr);
        
        /* If either buffer has data or we are transmitting then return TRUE */
        if ((oedb->XByteCount & 0x80 ) != 0 )
@@ -600,7 +600,7 @@ static int TIIsTxActive (struct edgeport_port *port)
 
        /* We return Not Active if we get any kind of error */
 exit_is_tx_active:
-       dbg ("%s - return %d", __FUNCTION__, bytes_left );
+       dbg ("%s - return %d", __func__, bytes_left );
 
        kfree(lsr);
        kfree(oedb);
@@ -654,7 +654,7 @@ static void TIChasePort(struct edgeport_port *port, unsigned long timeout, int f
        /* (TIIsTxActive doesn't seem to wait for the last byte) */
        if ((baud_rate=port->baud_rate) == 0)
                baud_rate = 50;
-       msleep(max(1,(10000+baud_rate-1)/baud_rate));
+       msleep(max(1, DIV_ROUND_UP(10000, baud_rate)));
 }
 
 static int TIChooseConfiguration (struct usb_device *dev)
@@ -664,11 +664,11 @@ static int TIChooseConfiguration (struct usb_device *dev)
        // we want. However, we just support one config at this point,
        // configuration # 1, which is Config Descriptor 0.
 
-       dbg ("%s - Number of Interfaces = %d", __FUNCTION__, dev->config->desc.bNumInterfaces);
-       dbg ("%s - MAX Power            = %d", __FUNCTION__, dev->config->desc.bMaxPower*2);
+       dbg ("%s - Number of Interfaces = %d", __func__, dev->config->desc.bNumInterfaces);
+       dbg ("%s - MAX Power            = %d", __func__, dev->config->desc.bMaxPower*2);
 
        if (dev->config->desc.bNumInterfaces != 1) {
-               dev_err (&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", __FUNCTION__);
+               dev_err (&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", __func__);
                return -ENODEV;
        }
 
@@ -751,7 +751,7 @@ static int ValidChecksum(struct ti_i2c_desc *rom_desc, __u8 *buffer)
                cs = (__u8)(cs + buffer[i]);
        }
        if (cs != rom_desc->CheckSum) {
-               dbg ("%s - Mismatch %x - %x", __FUNCTION__, rom_desc->CheckSum, cs);
+               dbg ("%s - Mismatch %x - %x", __func__, rom_desc->CheckSum, cs);
                return -EINVAL;
        }
        return 0;
@@ -769,12 +769,12 @@ static int TiValidateI2cImage (struct edgeport_serial *serial)
 
        rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
        if (!rom_desc) {
-               dev_err (dev, "%s - out of memory\n", __FUNCTION__);
+               dev_err (dev, "%s - out of memory\n", __func__);
                return -ENOMEM;
        }
        buffer = kmalloc (TI_MAX_I2C_SIZE, GFP_KERNEL);
        if (!buffer) {
-               dev_err (dev, "%s - out of memory when allocating buffer\n", __FUNCTION__);
+               dev_err (dev, "%s - out of memory when allocating buffer\n", __func__);
                kfree (rom_desc);
                return -ENOMEM;
        }
@@ -785,7 +785,7 @@ static int TiValidateI2cImage (struct edgeport_serial *serial)
                goto ExitTiValidateI2cImage; 
 
        if (*buffer != UMP5152 && *buffer != UMP3410) {
-               dev_err (dev, "%s - invalid buffer signature\n", __FUNCTION__);
+               dev_err (dev, "%s - invalid buffer signature\n", __func__);
                status = -ENODEV;
                goto ExitTiValidateI2cImage;
        }
@@ -801,11 +801,11 @@ static int TiValidateI2cImage (struct edgeport_serial *serial)
 
                if ((start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size) > TI_MAX_I2C_SIZE) {
                        status = -ENODEV;
-                       dbg ("%s - structure too big, erroring out.", __FUNCTION__);
+                       dbg ("%s - structure too big, erroring out.", __func__);
                        break;
                }
 
-               dbg ("%s Type = 0x%x", __FUNCTION__, rom_desc->Type);
+               dbg ("%s Type = 0x%x", __func__, rom_desc->Type);
 
                // Skip type 2 record
                ttype = rom_desc->Type & 0x0f;
@@ -845,13 +845,13 @@ static int TIReadManufDescriptor (struct edgeport_serial *serial, __u8 *buffer)
 
        rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
        if (!rom_desc) {
-               dev_err (&serial->serial->dev->dev, "%s - out of memory\n", __FUNCTION__);
+               dev_err (&serial->serial->dev->dev, "%s - out of memory\n", __func__);
                return -ENOMEM;
        }
        start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_ION, rom_desc);
 
        if (!start_address) {
-               dbg ("%s - Edge Descriptor not found in I2C", __FUNCTION__);
+               dbg ("%s - Edge Descriptor not found in I2C", __func__);
                status = -ENODEV;
                goto exit;
        }
@@ -867,12 +867,12 @@ static int TIReadManufDescriptor (struct edgeport_serial *serial, __u8 *buffer)
        status = ValidChecksum(rom_desc, buffer);
        
        desc = (struct edge_ti_manuf_descriptor *)buffer;
-       dbg ( "%s - IonConfig      0x%x", __FUNCTION__, desc->IonConfig         );
-       dbg ( "%s - Version          %d", __FUNCTION__, desc->Version           );
-       dbg ( "%s - Cpu/Board      0x%x", __FUNCTION__, desc->CpuRev_BoardRev   );
-       dbg ( "%s - NumPorts         %d", __FUNCTION__, desc->NumPorts          );      
-       dbg ( "%s - NumVirtualPorts  %d", __FUNCTION__, desc->NumVirtualPorts   );      
-       dbg ( "%s - TotalPorts       %d", __FUNCTION__, desc->TotalPorts        );      
+       dbg ( "%s - IonConfig      0x%x", __func__, desc->IonConfig     );
+       dbg ( "%s - Version          %d", __func__, desc->Version               );
+       dbg ( "%s - Cpu/Board      0x%x", __func__, desc->CpuRev_BoardRev       );
+       dbg ( "%s - NumPorts         %d", __func__, desc->NumPorts      );
+       dbg ( "%s - NumVirtualPorts  %d", __func__, desc->NumVirtualPorts       );
+       dbg ( "%s - TotalPorts       %d", __func__, desc->TotalPorts    );
 
 exit:
        kfree (rom_desc);
@@ -902,7 +902,7 @@ static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev)
 
        buffer = kmalloc (buffer_size, GFP_KERNEL);
        if (!buffer) {
-               dev_err (dev, "%s - out of memory\n", __FUNCTION__);
+               dev_err (dev, "%s - out of memory\n", __func__);
                return -ENOMEM;
        }
        
@@ -955,11 +955,11 @@ static int TIGetI2cTypeInBootMode (struct edgeport_serial *serial)
                                        &data,                          // TransferBuffer
                                        0x01);                          // TransferBufferLength
        if (status)
-               dbg ("%s - read 2 status error = %d", __FUNCTION__, status);
+               dbg ("%s - read 2 status error = %d", __func__, status);
        else
-               dbg ("%s - read 2 data = 0x%x", __FUNCTION__, data);
+               dbg ("%s - read 2 data = 0x%x", __func__, data);
        if ((!status) && (data == UMP5152 || data == UMP3410)) {
-               dbg ("%s - ROM_TYPE_II", __FUNCTION__);
+               dbg ("%s - ROM_TYPE_II", __func__);
                serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
                return 0;
        }
@@ -972,16 +972,16 @@ static int TIGetI2cTypeInBootMode (struct edgeport_serial *serial)
                                        &data,                          // TransferBuffer
                                        0x01);                          // TransferBufferLength
        if (status)
-               dbg ("%s - read 3 status error = %d", __FUNCTION__, status);
+               dbg ("%s - read 3 status error = %d", __func__, status);
        else
-               dbg ("%s - read 2 data = 0x%x", __FUNCTION__, data);
+               dbg ("%s - read 2 data = 0x%x", __func__, data);
        if ((!status) && (data == UMP5152 || data == UMP3410)) {
-               dbg ("%s - ROM_TYPE_III", __FUNCTION__);
+               dbg ("%s - ROM_TYPE_III", __func__);
                serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_III;
                return 0;
        }
 
-       dbg ("%s - Unknown", __FUNCTION__);
+       dbg ("%s - Unknown", __func__);
        serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
        return -ENODEV;
 }
@@ -1063,7 +1063,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
 
        interface = &serial->serial->interface->cur_altsetting->desc;
        if (!interface) {
-               dev_err (dev, "%s - no interface set, error!\n", __FUNCTION__);
+               dev_err (dev, "%s - no interface set, error!\n", __func__);
                return -ENODEV;
        }
 
@@ -1086,12 +1086,11 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
        if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) {
                struct ti_i2c_desc *rom_desc;
 
-               dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN DOWNLOAD MODE>>>>>>>>>>", __FUNCTION__);
+               dbg("%s - RUNNING IN DOWNLOAD MODE", __func__);
 
                status = TiValidateI2cImage (serial);
                if (status) {
-                       dbg ("%s - <<<<<<<<<<<<<<<DOWNLOAD MODE -- BAD I2C >>>>>>>>>>",
-                            __FUNCTION__);
+                       dbg("%s - DOWNLOAD MODE -- BAD I2C", __func__);
                        return status;
                }
                
@@ -1100,7 +1099,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
                 */
                ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL);
                if (!ti_manuf_desc) {
-                       dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
+                       dev_err (dev, "%s - out of memory.\n", __func__);
                        return -ENOMEM;
                }
                status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc);
@@ -1111,7 +1110,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
 
                // Check version number of ION descriptor
                if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) {
-                       dbg ( "%s - Wrong CPU Rev %d (Must be 2)", __FUNCTION__, 
+                       dbg ( "%s - Wrong CPU Rev %d (Must be 2)", __func__,
                             TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev));
                        kfree (ti_manuf_desc);
                        return -EINVAL;
@@ -1119,7 +1118,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
 
                rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
                if (!rom_desc) {
-                       dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
+                       dev_err (dev, "%s - out of memory.\n", __func__);
                        kfree (ti_manuf_desc);
                        return -ENOMEM;
                }
@@ -1129,11 +1128,11 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
                        struct ti_i2c_firmware_rec *firmware_version;
                        __u8 record;
 
-                       dbg ("%s - Found Type FIRMWARE (Type 2) record", __FUNCTION__);
+                       dbg ("%s - Found Type FIRMWARE (Type 2) record", __func__);
 
                        firmware_version = kmalloc (sizeof (*firmware_version), GFP_KERNEL);
                        if (!firmware_version) {
-                               dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
+                               dev_err (dev, "%s - out of memory.\n", __func__);
                                kfree (rom_desc);
                                kfree (ti_manuf_desc);
                                return -ENOMEM;
@@ -1159,7 +1158,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
                                           (OperationalCodeImageVersion.MinorVersion);
 
                        dbg ("%s - >>>Firmware Versions Device %d.%d  Driver %d.%d",
-                            __FUNCTION__,
+                            __func__,
                             firmware_version->Ver_Major,
                             firmware_version->Ver_Minor,
                             OperationalCodeImageVersion.MajorVersion,
@@ -1168,7 +1167,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
                        // Check if we have an old version in the I2C and update if necessary
                        if (download_cur_ver != download_new_ver) {
                                dbg ("%s - Update I2C Download from %d.%d to %d.%d",
-                                    __FUNCTION__,
+                                    __func__,
                                     firmware_version->Ver_Major,
                                     firmware_version->Ver_Minor,
                                     OperationalCodeImageVersion.MajorVersion,
@@ -1210,14 +1209,14 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
                                }
 
                                if (record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
-                                       dev_err (dev, "%s - error resetting device\n", __FUNCTION__);
+                                       dev_err (dev, "%s - error resetting device\n", __func__);
                                        kfree (firmware_version);
                                        kfree (rom_desc);
                                        kfree (ti_manuf_desc);
                                        return -ENODEV;
                                }
 
-                               dbg ("%s - HARDWARE RESET", __FUNCTION__);
+                               dbg ("%s - HARDWARE RESET", __func__);
 
                                // Reset UMP -- Back to BOOT MODE
                                status = TISendVendorRequestSync (serial->serial->dev,
@@ -1227,7 +1226,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
                                                                NULL,                   // TransferBuffer
                                                                0);                     // TransferBufferLength
 
-                               dbg ( "%s - HARDWARE RESET return %d", __FUNCTION__, status);
+                               dbg ( "%s - HARDWARE RESET return %d", __func__, status);
 
                                /* return an error on purpose. */
                                kfree (firmware_version);
@@ -1245,7 +1244,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
 
                        header  = kmalloc (HEADER_SIZE, GFP_KERNEL);
                        if (!header) {
-                               dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
+                               dev_err (dev, "%s - out of memory.\n", __func__);
                                kfree (rom_desc);
                                kfree (ti_manuf_desc);
                                return -ENOMEM;
@@ -1253,14 +1252,14 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
                                
                        vheader = kmalloc (HEADER_SIZE, GFP_KERNEL);
                        if (!vheader) {
-                               dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
+                               dev_err (dev, "%s - out of memory.\n", __func__);
                                kfree (header);
                                kfree (rom_desc);
                                kfree (ti_manuf_desc);
                                return -ENOMEM;
                        }
                        
-                       dbg ("%s - Found Type BLANK FIRMWARE (Type F2) record", __FUNCTION__);
+                       dbg ("%s - Found Type BLANK FIRMWARE (Type F2) record", __func__);
 
                        // In order to update the I2C firmware we must change the type 2 record to type 0xF2.
                        // This will force the UMP to come up in Boot Mode.  Then while in boot mode, the driver 
@@ -1298,7 +1297,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
                                                vheader);
 
                        if (status) {
-                               dbg ("%s - can't read header back", __FUNCTION__);
+                               dbg ("%s - can't read header back", __func__);
                                kfree (vheader);
                                kfree (header);
                                kfree (rom_desc);
@@ -1306,7 +1305,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
                                return status;
                        }
                        if (memcmp(vheader, header, HEADER_SIZE)) {
-                               dbg ("%s - write download record failed", __FUNCTION__);
+                               dbg ("%s - write download record failed", __func__);
                                kfree (vheader);
                                kfree (header);
                                kfree (rom_desc);
@@ -1317,7 +1316,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
                        kfree (vheader);
                        kfree (header);
 
-                       dbg ("%s - Start firmware update", __FUNCTION__);
+                       dbg ("%s - Start firmware update", __func__);
 
                        // Tell firmware to copy download image into I2C 
                        status = TISendVendorRequestSync (serial->serial->dev,
@@ -1327,9 +1326,9 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
                                                NULL,                   // TransferBuffer
                                                0);                     // TransferBufferLength
 
-                       dbg ("%s - Update complete 0x%x", __FUNCTION__, status);
+                       dbg ("%s - Update complete 0x%x", __func__, status);
                        if (status) {
-                               dev_err (dev, "%s - UMPC_COPY_DNLD_TO_I2C failed\n", __FUNCTION__);
+                               dev_err (dev, "%s - UMPC_COPY_DNLD_TO_I2C failed\n", __func__);
                                kfree (rom_desc);
                                kfree (ti_manuf_desc);
                                return status;
@@ -1345,8 +1344,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
        /********************************************************************/
        /* Boot Mode */
        /********************************************************************/
-       dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN BOOT MODE>>>>>>>>>>>>>>>",
-            __FUNCTION__);
+       dbg("%s - RUNNING IN BOOT MODE", __func__);
 
        // Configure the TI device so we can use the BULK pipes for download
        status = TIConfigureBootDevice (serial->serial->dev);
@@ -1354,7 +1352,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
                return status;
 
        if (le16_to_cpu(serial->serial->dev->descriptor.idVendor) != USB_VENDOR_ID_ION) {
-               dbg ("%s - VID = 0x%x", __FUNCTION__,
+               dbg ("%s - VID = 0x%x", __func__,
                     le16_to_cpu(serial->serial->dev->descriptor.idVendor));
                serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
                goto StayInBootMode;
@@ -1368,7 +1366,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
 
        // Registry variable set?
        if (TIStayInBootMode) {
-               dbg ("%s - TIStayInBootMode", __FUNCTION__);
+               dbg ("%s - TIStayInBootMode", __func__);
                goto StayInBootMode;
        }
 
@@ -1385,7 +1383,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
                 */
                ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL);
                if (!ti_manuf_desc) {
-                       dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
+                       dev_err (dev, "%s - out of memory.\n", __func__);
                        return -ENOMEM;
                }
                status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc);
@@ -1396,7 +1394,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
 
                // Check for version 2
                if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) {
-                       dbg ("%s - Wrong CPU Rev %d (Must be 2)", __FUNCTION__,
+                       dbg ("%s - Wrong CPU Rev %d (Must be 2)", __func__,
                             TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev));
                        kfree (ti_manuf_desc);
                        goto StayInBootMode;
@@ -1420,7 +1418,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
                buffer_size = (((1024 * 16) - 512) + sizeof(struct ti_i2c_image_header));
                buffer = kmalloc (buffer_size, GFP_KERNEL);
                if (!buffer) {
-                       dev_err (dev, "%s - out of memory\n", __FUNCTION__);
+                       dev_err (dev, "%s - out of memory\n", __func__);
                        return -ENOMEM;
                }
                
@@ -1440,20 +1438,20 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
                header->CheckSum = cs;
 
                // Download the operational code 
-               dbg ("%s - Downloading operational code image (TI UMP)", __FUNCTION__);
+               dbg ("%s - Downloading operational code image (TI UMP)", __func__);
                status = TIDownloadCodeImage (serial, buffer, buffer_size);
 
                kfree (buffer);
 
                if (status) {
-                       dbg ("%s - Error downloading operational code image", __FUNCTION__);
+                       dbg ("%s - Error downloading operational code image", __func__);
                        return status;
                }
 
                // Device will reboot
                serial->product_info.TiMode = TI_MODE_TRANSITIONING;
 
-               dbg ("%s - Download successful -- Device rebooting...", __FUNCTION__);
+               dbg ("%s - Download successful -- Device rebooting...", __func__);
 
                /* return an error on purpose */
                return -ENODEV;
@@ -1461,7 +1459,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
 
 StayInBootMode:
        // Eprom is invalid or blank stay in boot mode
-       dbg ("%s - <<<<<<<<<<<<<<<STAYING IN BOOT MODE>>>>>>>>>>>>", __FUNCTION__);
+       dbg("%s - STAYING IN BOOT MODE", __func__);
        serial->product_info.TiMode = TI_MODE_BOOT;
 
        return 0;
@@ -1472,7 +1470,7 @@ static int TISetDtr (struct edgeport_port *port)
 {
        int port_number = port->port->number - port->port->serial->minor;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
        port->shadow_mcr |= MCR_DTR;
 
        return TIWriteCommandSync (port->port->serial->dev,
@@ -1487,7 +1485,7 @@ static int TIClearDtr (struct edgeport_port *port)
 {
        int port_number = port->port->number - port->port->serial->minor;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
        port->shadow_mcr &= ~MCR_DTR;
 
        return TIWriteCommandSync (port->port->serial->dev,
@@ -1502,7 +1500,7 @@ static int TISetRts (struct edgeport_port *port)
 {
        int port_number = port->port->number - port->port->serial->minor;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
        port->shadow_mcr |= MCR_RTS;
 
        return TIWriteCommandSync (port->port->serial->dev,
@@ -1517,7 +1515,7 @@ static int TIClearRts (struct edgeport_port *port)
 {
        int port_number = port->port->number - port->port->serial->minor;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
        port->shadow_mcr &= ~MCR_RTS;
 
        return TIWriteCommandSync (port->port->serial->dev,
@@ -1532,7 +1530,7 @@ static int TISetLoopBack (struct edgeport_port *port)
 {
        int port_number = port->port->number - port->port->serial->minor;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        return TIWriteCommandSync (port->port->serial->dev,
                                UMPC_SET_CLR_LOOPBACK,
@@ -1546,7 +1544,7 @@ static int TIClearLoopBack (struct edgeport_port *port)
 {
        int port_number = port->port->number - port->port->serial->minor;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        return TIWriteCommandSync (port->port->serial->dev,
                                UMPC_SET_CLR_LOOPBACK,
@@ -1560,7 +1558,7 @@ static int TISetBreak (struct edgeport_port *port)
 {
        int port_number = port->port->number - port->port->serial->minor;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        return TIWriteCommandSync (port->port->serial->dev,
                                UMPC_SET_CLR_BREAK,
@@ -1574,7 +1572,7 @@ static int TIClearBreak (struct edgeport_port *port)
 {
        int port_number = port->port->number - port->port->serial->minor;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        return TIWriteCommandSync (port->port->serial->dev,
                                UMPC_SET_CLR_BREAK,
@@ -1588,7 +1586,7 @@ static int TIRestoreMCR (struct edgeport_port *port, __u8 mcr)
 {
        int status = 0;
 
-       dbg ("%s - %x", __FUNCTION__, mcr);
+       dbg ("%s - %x", __func__, mcr);
 
        if (mcr & MCR_DTR)
                status = TISetDtr (port);
@@ -1642,7 +1640,7 @@ static void handle_new_msr (struct edgeport_port *edge_port, __u8 msr)
        struct async_icount *icount;
        struct tty_struct *tty;
 
-       dbg ("%s - %02x", __FUNCTION__, msr);
+       dbg ("%s - %02x", __func__, msr);
 
        if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
                icount = &edge_port->icount;
@@ -1681,7 +1679,7 @@ static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8
        struct async_icount *icount;
        __u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
 
-       dbg ("%s - %02x", __FUNCTION__, new_lsr);
+       dbg ("%s - %02x", __func__, new_lsr);
 
        edge_port->shadow_lsr = lsr;
 
@@ -1712,7 +1710,7 @@ static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8
 
 static void edge_interrupt_callback (struct urb *urb)
 {
-       struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context;
+       struct edgeport_serial *edge_serial = urb->context;
        struct usb_serial_port *port;
        struct edgeport_port *edge_port;
        unsigned char *data = urb->transfer_buffer;
@@ -1724,7 +1722,7 @@ static void edge_interrupt_callback (struct urb *urb)
        __u8 msr;
        int status = urb->status;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        switch (status) {
        case 0:
@@ -1735,34 +1733,34 @@ static void edge_interrupt_callback (struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        default:
                dev_err(&urb->dev->dev, "%s - nonzero urb status received: "
-                       "%d\n", __FUNCTION__, status);
+                       "%d\n", __func__, status);
                goto exit;
        }
 
        if (!length) {
-               dbg ("%s - no data in urb", __FUNCTION__);
+               dbg ("%s - no data in urb", __func__);
                goto exit;
        }
                
-       usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __FUNCTION__, length, data);
+       usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, length, data);
                
        if (length != 2) {
-               dbg ("%s - expecting packet of size 2, got %d", __FUNCTION__, length);
+               dbg ("%s - expecting packet of size 2, got %d", __func__, length);
                goto exit;
        }
 
        port_number = TIUMP_GET_PORT_FROM_CODE (data[0]);
        function    = TIUMP_GET_FUNC_FROM_CODE (data[0]);
        dbg ("%s - port_number %d, function %d, info 0x%x",
-            __FUNCTION__, port_number, function, data[1]);
+            __func__, port_number, function, data[1]);
        port = edge_serial->serial->port[port_number];
        edge_port = usb_get_serial_port_data(port);
        if (!edge_port) {
-               dbg ("%s - edge_port not found", __FUNCTION__);
+               dbg ("%s - edge_port not found", __func__);
                return;
        }
        switch (function) {
@@ -1771,12 +1769,12 @@ static void edge_interrupt_callback (struct urb *urb)
                if (lsr & UMP_UART_LSR_DATA_MASK) {
                        /* Save the LSR event for bulk read completion routine */
                        dbg ("%s - LSR Event Port %u LSR Status = %02x",
-                            __FUNCTION__, port_number, lsr);
+                            __func__, port_number, lsr);
                        edge_port->lsr_event = 1;
                        edge_port->lsr_mask = lsr;
                } else {
                        dbg ("%s - ===== Port %d LSR Status = %02x ======",
-                            __FUNCTION__, port_number, lsr);
+                            __func__, port_number, lsr);
                        handle_new_lsr (edge_port, 0, lsr, 0);
                }
                break;
@@ -1785,13 +1783,13 @@ static void edge_interrupt_callback (struct urb *urb)
                /* Copy MSR from UMP */
                msr = data[1];
                dbg ("%s - ===== Port %u MSR Status = %02x ======\n",
-                    __FUNCTION__, port_number, msr);
+                    __func__, port_number, msr);
                handle_new_msr (edge_port, msr);
                break;
 
        default:
                dev_err (&urb->dev->dev, "%s - Unknown Interrupt code from UMP %x\n",
-                        __FUNCTION__, data[1]);
+                        __func__, data[1]);
                break;
                
        }
@@ -1800,19 +1798,19 @@ exit:
        retval = usb_submit_urb (urb, GFP_ATOMIC);
        if (retval)
                dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
-                        __FUNCTION__, retval);
+                        __func__, retval);
 }
 
 static void edge_bulk_in_callback (struct urb *urb)
 {
-       struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
+       struct edgeport_port *edge_port = urb->context;
        unsigned char *data = urb->transfer_buffer;
        struct tty_struct *tty;
        int retval = 0;
        int port_number;
        int status = urb->status;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        switch (status) {
        case 0:
@@ -1823,18 +1821,18 @@ static void edge_bulk_in_callback (struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        default:
                dev_err (&urb->dev->dev,"%s - nonzero read bulk status received: %d\n",
-                    __FUNCTION__, status);
+                    __func__, status);
        }
 
        if (status == -EPIPE)
                goto exit;
 
        if (status) {
-               dev_err(&urb->dev->dev,"%s - stopping read!\n", __FUNCTION__);
+               dev_err(&urb->dev->dev,"%s - stopping read!\n", __func__);
                return;
        }
 
@@ -1843,7 +1841,7 @@ static void edge_bulk_in_callback (struct urb *urb)
        if (edge_port->lsr_event) {
                edge_port->lsr_event = 0;
                dbg ("%s ===== Port %u LSR Status = %02x, Data = %02x ======",
-                    __FUNCTION__, port_number, edge_port->lsr_mask, *data);
+                    __func__, port_number, edge_port->lsr_mask, *data);
                handle_new_lsr (edge_port, 1, edge_port->lsr_mask, *data);
                /* Adjust buffer length/pointer */
                --urb->actual_length;
@@ -1852,10 +1850,10 @@ static void edge_bulk_in_callback (struct urb *urb)
 
        tty = edge_port->port->tty;
        if (tty && urb->actual_length) {
-               usb_serial_debug_data(debug, &edge_port->port->dev, __FUNCTION__, urb->actual_length, data);
+               usb_serial_debug_data(debug, &edge_port->port->dev, __func__, urb->actual_length, data);
 
                if (edge_port->close_pending) {
-                       dbg ("%s - close is pending, dropping data on the floor.", __FUNCTION__);
+                       dbg ("%s - close is pending, dropping data on the floor.", __func__);
                } else {
                        edge_tty_recv(&edge_port->port->dev, tty, data, urb->actual_length);
                }
@@ -1874,7 +1872,7 @@ exit:
        spin_unlock(&edge_port->ep_lock);
        if (retval)
                dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
-                        __FUNCTION__, retval);
+                        __func__, retval);
 }
 
 static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length)
@@ -1885,7 +1883,7 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
                cnt = tty_buffer_request_room(tty, length);
                if (cnt < length) {
                        dev_err(dev, "%s - dropping data, %d bytes lost\n",
-                               __FUNCTION__, length - cnt);
+                               __func__, length - cnt);
                        if(cnt == 0)
                                break;
                }
@@ -1899,11 +1897,11 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
 
 static void edge_bulk_out_callback (struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *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);
+       dbg ("%s - port %d", __func__, port->number);
 
        edge_port->ep_write_urb_in_use = 0;
 
@@ -1916,11 +1914,11 @@ static void edge_bulk_out_callback (struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        default:
                dev_err(&urb->dev->dev, "%s - nonzero write bulk status "
-                       "received: %d\n", __FUNCTION__, status);
+                       "received: %d\n", __func__, status);
        }
 
        /* send any buffered data */
@@ -1938,13 +1936,12 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
        u16 open_settings;
        u8 transaction_timeout;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (edge_port == NULL)
                return -ENODEV;
 
-       if (port->tty)
-               port->tty->low_latency = low_latency;
+       port->tty->low_latency = low_latency;
 
        port_number = port->number - port->serial->minor;
        switch (port_number) {
@@ -1962,7 +1959,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
        }
 
        dbg ("%s - port_number = %d, uart_base = %04x, dma_address = %04x",
-            __FUNCTION__, port_number, edge_port->uart_base, edge_port->dma_address);
+            __func__, port_number, edge_port->uart_base, edge_port->dma_address);
 
        dev = port->serial->dev;
 
@@ -1973,7 +1970,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
        status = TIClearLoopBack (edge_port);
        if (status) {
                dev_err(&port->dev,"%s - cannot send clear loopback command, %d\n",
-                       __FUNCTION__, status);
+                       __func__, status);
                return status;
        }
        
@@ -1992,7 +1989,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
                             UMP_PIPE_TRANS_TIMEOUT_ENA | 
                             (transaction_timeout << 2));
 
-       dbg ("%s - Sending UMPC_OPEN_PORT", __FUNCTION__);
+       dbg ("%s - Sending UMPC_OPEN_PORT", __func__);
 
        /* Tell TI to open and start the port */
        status = TIWriteCommandSync (dev,
@@ -2002,7 +1999,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
                                        NULL,
                                        0);
        if (status) {
-               dev_err(&port->dev,"%s - cannot send open command, %d\n", __FUNCTION__, status);
+               dev_err(&port->dev,"%s - cannot send open command, %d\n", __func__, status);
                return status;
        }
 
@@ -2014,14 +2011,14 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
                                        NULL,
                                        0);
        if (status) {
-               dev_err(&port->dev,"%s - cannot send start DMA command, %d\n", __FUNCTION__, status);
+               dev_err(&port->dev,"%s - cannot send start DMA command, %d\n", __func__, status);
                return status;
        }
 
        /* Clear TX and RX buffers in UMP */
        status = TIPurgeDataSync (port, UMP_PORT_DIR_OUT | UMP_PORT_DIR_IN);
        if (status) {
-               dev_err(&port->dev,"%s - cannot send clear buffers command, %d\n", __FUNCTION__, status);
+               dev_err(&port->dev,"%s - cannot send clear buffers command, %d\n", __func__, status);
                return status;
        }
 
@@ -2033,7 +2030,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
                                        &edge_port->shadow_msr,                 // TransferBuffer
                                        1);                                     // TransferBufferLength
        if (status) {
-               dev_err(&port->dev,"%s - cannot send read MSR command, %d\n", __FUNCTION__, status);
+               dev_err(&port->dev,"%s - cannot send read MSR command, %d\n", __func__, status);
                return status;
        }
 
@@ -2050,7 +2047,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
                /* we are the first port to be opened, let's post the interrupt urb */
                urb = edge_serial->serial->port[0]->interrupt_in_urb;
                if (!urb) {
-                       dev_err (&port->dev, "%s - no interrupt urb present, exiting\n", __FUNCTION__);
+                       dev_err (&port->dev, "%s - no interrupt urb present, exiting\n", __func__);
                        status = -EINVAL;
                        goto release_es_lock;
                }
@@ -2059,7 +2056,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
                urb->dev = dev;
                status = usb_submit_urb (urb, GFP_KERNEL);
                if (status) {
-                       dev_err (&port->dev, "%s - usb_submit_urb failed with value %d\n", __FUNCTION__, status);
+                       dev_err (&port->dev, "%s - usb_submit_urb failed with value %d\n", __func__, status);
                        goto release_es_lock;
                }
        }
@@ -2074,7 +2071,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
        /* start up our bulk read urb */
        urb = port->read_urb;
        if (!urb) {
-               dev_err (&port->dev, "%s - no read urb present, exiting\n", __FUNCTION__);
+               dev_err (&port->dev, "%s - no read urb present, exiting\n", __func__);
                status = -EINVAL;
                goto unlink_int_urb;
        }
@@ -2084,13 +2081,13 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
        urb->dev = dev;
        status = usb_submit_urb (urb, GFP_KERNEL);
        if (status) {
-               dev_err (&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __FUNCTION__, status);
+               dev_err (&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __func__, status);
                goto unlink_int_urb;
        }
 
        ++edge_serial->num_ports_open;
 
-       dbg("%s - exited", __FUNCTION__);
+       dbg("%s - exited", __func__);
 
        goto release_es_lock;
 
@@ -2109,7 +2106,7 @@ static void edge_close (struct usb_serial_port *port, struct file *filp)
        int port_number;
        int status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
                         
        edge_serial = usb_get_serial_data(port->serial);
        edge_port = usb_get_serial_port_data(port);
@@ -2129,7 +2126,7 @@ static void edge_close (struct usb_serial_port *port, struct file *filp)
 
        /* assuming we can still talk to the device,
         * send a close port command to it */
-       dbg("%s - send umpc_close_port", __FUNCTION__);
+       dbg("%s - send umpc_close_port", __func__);
        port_number = port->number - port->serial->minor;
        status = TIWriteCommandSync (port->serial->dev,
                                     UMPC_CLOSE_PORT,
@@ -2147,7 +2144,7 @@ static void edge_close (struct usb_serial_port *port, struct file *filp)
        mutex_unlock(&edge_serial->es_lock);
        edge_port->close_pending = 0;
 
-       dbg("%s - exited", __FUNCTION__);
+       dbg("%s - exited", __func__);
 }
 
 static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count)
@@ -2155,10 +2152,10 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
        struct edgeport_port *edge_port = usb_get_serial_port_data(port);
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (count == 0) {
-               dbg("%s - write request of 0 bytes", __FUNCTION__);
+               dbg("%s - write request of 0 bytes", __func__);
                return 0;
        }
 
@@ -2184,7 +2181,7 @@ static void edge_send(struct usb_serial_port *port)
        unsigned long flags;
 
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&edge_port->ep_lock, flags);
 
@@ -2206,7 +2203,7 @@ static void edge_send(struct usb_serial_port *port)
 
        spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer);
+       usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer);
 
        /* set up our urb */
        usb_fill_bulk_urb (port->write_urb, port->serial->dev,
@@ -2219,7 +2216,7 @@ static void edge_send(struct usb_serial_port *port)
        /* send the data out the bulk port */
        result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
        if (result) {
-               dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
+               dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
                edge_port->ep_write_urb_in_use = 0;
                // TODO: reschedule edge_send
        } else {
@@ -2240,7 +2237,7 @@ static int edge_write_room (struct usb_serial_port *port)
        int room = 0;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (edge_port == NULL)
                return -ENODEV;
@@ -2251,7 +2248,7 @@ static int edge_write_room (struct usb_serial_port *port)
        room = edge_buf_space_avail(edge_port->ep_out_buf);
        spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 
-       dbg("%s - returns %d", __FUNCTION__, room);
+       dbg("%s - returns %d", __func__, room);
        return room;
 }
 
@@ -2261,7 +2258,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
        int chars = 0;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (edge_port == NULL)
                return -ENODEV;
@@ -2272,7 +2269,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
        chars = edge_buf_data_avail(edge_port->ep_out_buf);
        spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 
-       dbg ("%s - returns %d", __FUNCTION__, chars);
+       dbg ("%s - returns %d", __func__, chars);
        return chars;
 }
 
@@ -2282,14 +2279,14 @@ static void edge_throttle (struct usb_serial_port *port)
        struct tty_struct *tty;
        int status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (edge_port == NULL)
                return;
 
        tty = port->tty;
        if (!tty) {
-               dbg ("%s - no tty available", __FUNCTION__);
+               dbg ("%s - no tty available", __func__);
                return;
        }
 
@@ -2298,7 +2295,7 @@ static void edge_throttle (struct usb_serial_port *port)
                unsigned char stop_char = STOP_CHAR(tty);
                status = edge_write (port, &stop_char, 1);
                if (status <= 0) {
-                       dev_err(&port->dev, "%s - failed to write stop character, %d\n", __FUNCTION__, status);
+                       dev_err(&port->dev, "%s - failed to write stop character, %d\n", __func__, status);
                }
        }
 
@@ -2315,14 +2312,14 @@ static void edge_unthrottle (struct usb_serial_port *port)
        struct tty_struct *tty;
        int status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (edge_port == NULL)
                return;
 
        tty = port->tty;
        if (!tty) {
-               dbg ("%s - no tty available", __FUNCTION__);
+               dbg ("%s - no tty available", __func__);
                return;
        }
 
@@ -2331,7 +2328,7 @@ static void edge_unthrottle (struct usb_serial_port *port)
                unsigned char start_char = START_CHAR(tty);
                status = edge_write (port, &start_char, 1);
                if (status <= 0) {
-                       dev_err(&port->dev, "%s - failed to write start character, %d\n", __FUNCTION__, status);
+                       dev_err(&port->dev, "%s - failed to write start character, %d\n", __func__, status);
                }
        }
 
@@ -2340,7 +2337,7 @@ static void edge_unthrottle (struct usb_serial_port *port)
        if (C_CRTSCTS(tty)) {
                status = restart_read(edge_port);
                if (status)
-                       dev_err(&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __FUNCTION__, status);
+                       dev_err(&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __func__, status);
        }
 
 }
@@ -2390,13 +2387,13 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
        int status;
        int port_number = edge_port->port->number - edge_port->port->serial->minor;
 
-       dbg("%s - port %d", __FUNCTION__, edge_port->port->number);
+       dbg("%s - port %d", __func__, edge_port->port->number);
 
        tty = edge_port->port->tty;
 
        config = kmalloc (sizeof (*config), GFP_KERNEL);
        if (!config) {
-               dev_err (&edge_port->port->dev, "%s - out of memory\n", __FUNCTION__);
+               dev_err (&edge_port->port->dev, "%s - out of memory\n", __func__);
                return;
        }
 
@@ -2412,20 +2409,20 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
        switch (cflag & CSIZE) {
                case CS5:
                            config->bDataBits = UMP_UART_CHAR5BITS;
-                           dbg ("%s - data bits = 5", __FUNCTION__);
+                           dbg ("%s - data bits = 5", __func__);
                            break;
                case CS6:
                            config->bDataBits = UMP_UART_CHAR6BITS;
-                           dbg ("%s - data bits = 6", __FUNCTION__);
+                           dbg ("%s - data bits = 6", __func__);
                            break;
                case CS7:
                            config->bDataBits = UMP_UART_CHAR7BITS;
-                           dbg ("%s - data bits = 7", __FUNCTION__);
+                           dbg ("%s - data bits = 7", __func__);
                            break;
                default:
                case CS8:
                            config->bDataBits = UMP_UART_CHAR8BITS;
-                           dbg ("%s - data bits = 8", __FUNCTION__);
+                           dbg ("%s - data bits = 8", __func__);
                            break;
        }
 
@@ -2433,32 +2430,32 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
                if (cflag & PARODD) {
                        config->wFlags |= UMP_MASK_UART_FLAGS_PARITY;
                        config->bParity = UMP_UART_ODDPARITY;
-                       dbg("%s - parity = odd", __FUNCTION__);
+                       dbg("%s - parity = odd", __func__);
                } else {
                        config->wFlags |= UMP_MASK_UART_FLAGS_PARITY;
                        config->bParity = UMP_UART_EVENPARITY;
-                       dbg("%s - parity = even", __FUNCTION__);
+                       dbg("%s - parity = even", __func__);
                }
        } else {
                config->bParity = UMP_UART_NOPARITY;    
-               dbg("%s - parity = none", __FUNCTION__);
+               dbg("%s - parity = none", __func__);
        }
 
        if (cflag & CSTOPB) {
                config->bStopBits = UMP_UART_STOPBIT2;
-               dbg("%s - stop bits = 2", __FUNCTION__);
+               dbg("%s - stop bits = 2", __func__);
        } else {
                config->bStopBits = UMP_UART_STOPBIT1;
-               dbg("%s - stop bits = 1", __FUNCTION__);
+               dbg("%s - stop bits = 1", __func__);
        }
 
        /* figure out the flow control settings */
        if (cflag & CRTSCTS) {
                config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X_CTS_FLOW;
                config->wFlags |= UMP_MASK_UART_FLAGS_RTS_FLOW;
-               dbg("%s - RTS/CTS is enabled", __FUNCTION__);
+               dbg("%s - RTS/CTS is enabled", __func__);
        } else {
-               dbg("%s - RTS/CTS is disabled", __FUNCTION__);
+               dbg("%s - RTS/CTS is disabled", __func__);
                tty->hw_stopped = 0;
                restart_read(edge_port);
        }
@@ -2472,18 +2469,18 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
                if (I_IXOFF(tty)) {
                        config->wFlags |= UMP_MASK_UART_FLAGS_IN_X;
                        dbg ("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
-                            __FUNCTION__, config->cXon, config->cXoff);
+                            __func__, config->cXon, config->cXoff);
                } else {
-                       dbg ("%s - INBOUND XON/XOFF is disabled", __FUNCTION__);
+                       dbg ("%s - INBOUND XON/XOFF is disabled", __func__);
                }
 
                /* if we are implementing OUTBOUND XON/XOFF */
                if (I_IXON(tty)) {
                        config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X;
                        dbg ("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
-                            __FUNCTION__, config->cXon, config->cXoff);
+                            __func__, config->cXon, config->cXoff);
                } else {
-                       dbg ("%s - OUTBOUND XON/XOFF is disabled", __FUNCTION__);
+                       dbg ("%s - OUTBOUND XON/XOFF is disabled", __func__);
                }
        }
 
@@ -2502,7 +2499,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
 
        /* FIXME: Recompute actual baud from divisor here */
 
-       dbg ("%s - baud rate = %d, wBaudRate = %d", __FUNCTION__, baud, config->wBaudRate);
+       dbg ("%s - baud rate = %d, wBaudRate = %d", __func__, baud, config->wBaudRate);
 
        dbg ("wBaudRate:   %d", (int)(461550L / config->wBaudRate));
        dbg ("wFlags:    0x%x", config->wFlags);
@@ -2525,7 +2522,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
                                sizeof(*config));
        if (status) {
                dbg ("%s - error %d when trying to write config to device",
-                    __FUNCTION__, status);
+                    __func__, status);
        }
 
        kfree (config);
@@ -2541,12 +2538,12 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
 
        cflag = tty->termios->c_cflag;
 
-       dbg("%s - clfag %08x iflag %08x", __FUNCTION__, 
+       dbg("%s - clfag %08x iflag %08x", __func__,
            tty->termios->c_cflag, tty->termios->c_iflag);
-       dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
+       dbg("%s - old clfag %08x old iflag %08x", __func__,
            old_termios->c_cflag, old_termios->c_iflag);
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (edge_port == NULL)
                return;
@@ -2561,9 +2558,11 @@ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsig
 {
        struct edgeport_port *edge_port = usb_get_serial_port_data(port);
        unsigned int mcr;
+       unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
+       spin_lock_irqsave(&edge_port->ep_lock, flags);
        mcr = edge_port->shadow_mcr;
        if (set & TIOCM_RTS)
                mcr |= MCR_RTS;
@@ -2580,6 +2579,7 @@ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsig
                mcr &= ~MCR_LOOPBACK;
 
        edge_port->shadow_mcr = mcr;
+       spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 
        TIRestoreMCR (edge_port, mcr);
 
@@ -2592,8 +2592,11 @@ static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
        unsigned int result = 0;
        unsigned int msr;
        unsigned int mcr;
+       unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
+
+       spin_lock_irqsave(&edge_port->ep_lock, flags);
 
        msr = edge_port->shadow_msr;
        mcr = edge_port->shadow_mcr;
@@ -2605,7 +2608,8 @@ static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
                  | ((msr & EDGEPORT_MSR_DSR)   ? TIOCM_DSR: 0);  /* 0x100 */
 
 
-       dbg("%s -- %x", __FUNCTION__, result);
+       dbg("%s -- %x", __func__, result);
+       spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 
        return result;
 }
@@ -2644,30 +2648,30 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
        struct async_icount cnow;
        struct async_icount cprev;
 
-       dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
+       dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
 
        switch (cmd) {
                case TIOCINQ:
-                       dbg("%s - (%d) TIOCINQ", __FUNCTION__, port->number);
+                       dbg("%s - (%d) TIOCINQ", __func__, port->number);
 //                     return get_number_bytes_avail(edge_port, (unsigned int *) arg);
                        break;
 
                case TIOCSERGETLSR:
-                       dbg("%s - (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
+                       dbg("%s - (%d) TIOCSERGETLSR", __func__, port->number);
 //                     return get_lsr_info(edge_port, (unsigned int *) arg);
                        break;
 
                case TIOCGSERIAL:
-                       dbg("%s - (%d) TIOCGSERIAL", __FUNCTION__, port->number);
+                       dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
                        return get_serial_info(edge_port, (struct serial_struct __user *) arg);
                        break;
 
                case TIOCSSERIAL:
-                       dbg("%s - (%d) TIOCSSERIAL", __FUNCTION__, port->number);
+                       dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
                        break;
 
                case TIOCMIWAIT:
-                       dbg("%s - (%d) TIOCMIWAIT", __FUNCTION__, port->number);
+                       dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
                        cprev = edge_port->icount;
                        while (1) {
                                interruptible_sleep_on(&edge_port->delta_msr_wait);
@@ -2690,7 +2694,7 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
                        break;
 
                case TIOCGICOUNT:
-                       dbg ("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
+                       dbg ("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
                             port->number, edge_port->icount.rx, edge_port->icount.tx);
                        if (copy_to_user((void __user *)arg, &edge_port->icount, sizeof(edge_port->icount)))
                                return -EFAULT;
@@ -2705,7 +2709,7 @@ static void edge_break (struct usb_serial_port *port, int break_state)
        struct edgeport_port *edge_port = usb_get_serial_port_data(port);
        int status;
 
-       dbg ("%s - state = %d", __FUNCTION__, break_state);
+       dbg ("%s - state = %d", __func__, break_state);
 
        /* chase the port close */
        TIChasePort (edge_port, 0, 0);
@@ -2717,7 +2721,7 @@ static void edge_break (struct usb_serial_port *port, int break_state)
        }
        if (status) {
                dbg ("%s - error %d sending break set/clear command.",
-                    __FUNCTION__, status);
+                    __func__, status);
        }
 }
 
@@ -2734,7 +2738,7 @@ static int edge_startup (struct usb_serial *serial)
        /* create our private serial structure */
        edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
        if (edge_serial == NULL) {
-               dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
+               dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
                return -ENOMEM;
        }
        mutex_init(&edge_serial->es_lock);
@@ -2751,13 +2755,13 @@ static int edge_startup (struct usb_serial *serial)
        for (i = 0; i < serial->num_ports; ++i) {
                edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
                if (edge_port == NULL) {
-                       dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
+                       dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
                        goto cleanup;
                }
                spin_lock_init(&edge_port->ep_lock);
                edge_port->ep_out_buf = edge_buf_alloc(EDGE_OUT_BUF_SIZE);
                if (edge_port->ep_out_buf == NULL) {
-                       dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
+                       dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
                        kfree(edge_port);
                        goto cleanup;
                }
@@ -2786,7 +2790,7 @@ static void edge_shutdown (struct usb_serial *serial)
        int i;
        struct edgeport_port *edge_port;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        for (i = 0; i < serial->num_ports; ++i) {
                edge_port = usb_get_serial_port_data(serial->port[i]);
@@ -2818,12 +2822,12 @@ static ssize_t store_uart_mode(struct device *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);
+       dbg("%s: setting uart_mode = %d", __func__, v);
 
        if (v < 256)
                edge_port->bUartMode = v;
        else
-               dev_err(dev, "%s - uart_mode %d is invalid\n", __FUNCTION__, v);
+               dev_err(dev, "%s - uart_mode %d is invalid\n", __func__, v);
 
        return count;
 }
@@ -3028,9 +3032,6 @@ static struct usb_serial_driver edgeport_1port_device = {
        .description            = "Edgeport TI 1 port adapter",
        .usb_driver             = &io_driver,
        .id_table               = edgeport_1port_id_table,
-       .num_interrupt_in       = 1,
-       .num_bulk_in            = 1,
-       .num_bulk_out           = 1,
        .num_ports              = 1,
        .open                   = edge_open,
        .close                  = edge_close,
@@ -3060,9 +3061,6 @@ static struct usb_serial_driver edgeport_2port_device = {
        .description            = "Edgeport TI 2 port adapter",
        .usb_driver             = &io_driver,
        .id_table               = edgeport_2port_id_table,
-       .num_interrupt_in       = 1,
-       .num_bulk_in            = 2,
-       .num_bulk_out           = 2,
        .num_ports              = 2,
        .open                   = edge_open,
        .close                  = edge_close,
index 9b38a08ac83a6803cda3d0123ae26f32b42a851a..ea924dc48496de2b8ca7341c5de69217c3ad8a7e 100644 (file)
@@ -570,10 +570,7 @@ static struct usb_serial_driver ipaq_device = {
        .description =          "PocketPC PDA",
        .usb_driver =           &ipaq_driver,
        .id_table =             ipaq_id_table,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          1,
-       .num_bulk_out =         1,
-       .num_ports =            1,
+       .num_ports =            2,
        .open =                 ipaq_open,
        .close =                ipaq_close,
        .attach =               ipaq_startup,
@@ -597,13 +594,13 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
        int                     i, result = 0;
        int                     retries = connect_retries;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        bytes_in = 0;
        bytes_out = 0;
        priv = kmalloc(sizeof(struct ipaq_private), GFP_KERNEL);
        if (priv == NULL) {
-               err("%s - Out of memory", __FUNCTION__);
+               err("%s - Out of memory", __func__);
                return -ENOMEM;
        }
        usb_set_serial_port_data(port, priv);
@@ -682,7 +679,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
        }
 
        if (!retries && result) {
-               err("%s - failed doing control urb, error %d", __FUNCTION__,
+               err("%s - failed doing control urb, error %d", __func__,
                    result);
                goto error;
        }
@@ -695,7 +692,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
 
        result = usb_submit_urb(port->read_urb, GFP_KERNEL);
        if (result) {
-               err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+               err("%s - failed submitting read urb, error %d", __func__, result);
                goto error;
        }
 
@@ -703,7 +700,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
 
 enomem:
        result = -ENOMEM;
-       err("%s - Out of memory", __FUNCTION__);
+       err("%s - Out of memory", __func__);
 error:
        ipaq_destroy_lists(port);
        kfree(priv);
@@ -715,7 +712,7 @@ static void ipaq_close(struct usb_serial_port *port, struct file *filp)
 {
        struct ipaq_private     *priv = usb_get_serial_port_data(port);
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
                         
        /*
         * shut down bulk read and write
@@ -732,21 +729,21 @@ static void ipaq_close(struct usb_serial_port *port, struct file *filp)
 
 static void ipaq_read_bulk_callback(struct urb *urb)
 {
-       struct usb_serial_port  *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port  *port = urb->context;
        struct tty_struct       *tty;
        unsigned char           *data = urb->transfer_buffer;
        int                     result;
        int status = urb->status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (status) {
                dbg("%s - nonzero read bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+       usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
 
        tty = port->tty;
        if (tty && urb->actual_length) {
@@ -763,7 +760,7 @@ static void ipaq_read_bulk_callback(struct urb *urb)
                      ipaq_read_bulk_callback, port);
        result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
        if (result)
-               err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+               err("%s - failed resubmitting read urb, error %d", __func__, result);
        return;
 }
 
@@ -774,7 +771,7 @@ static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf,
        int                     bytes_sent = 0;
        int                     transfer_size;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        while (count > 0) {
                transfer_size = min(count, PACKET_SIZE);
@@ -799,7 +796,7 @@ static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *bu
        unsigned long           flags;
 
        if (priv->free_len <= 0) {
-               dbg("%s - we're stuffed", __FUNCTION__);
+               dbg("%s - we're stuffed", __func__);
                return -EAGAIN;
        }
 
@@ -811,12 +808,12 @@ static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *bu
        }
        spin_unlock_irqrestore(&write_list_lock, flags);
        if (pkt == NULL) {
-               dbg("%s - we're stuffed", __FUNCTION__);
+               dbg("%s - we're stuffed", __func__);
                return -EAGAIN;
        }
 
        memcpy(pkt->data, buf, count);
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, pkt->data);
+       usb_serial_debug_data(debug, &port->dev, __func__, count, pkt->data);
 
        pkt->len = count;
        pkt->written = 0;
@@ -829,7 +826,7 @@ static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *bu
                spin_unlock_irqrestore(&write_list_lock, flags);
                result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
                if (result) {
-                       err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
+                       err("%s - failed submitting write urb, error %d", __func__, result);
                }
        } else {
                spin_unlock_irqrestore(&write_list_lock, flags);
@@ -872,17 +869,17 @@ static void ipaq_write_gather(struct usb_serial_port *port)
 
 static void ipaq_write_bulk_callback(struct urb *urb)
 {
-       struct usb_serial_port  *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port  *port = urb->context;
        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);
+       dbg("%s - port %d", __func__, port->number);
 
        if (status) {
                dbg("%s - nonzero write bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        }
 
@@ -892,7 +889,7 @@ static void ipaq_write_bulk_callback(struct urb *urb)
                spin_unlock_irqrestore(&write_list_lock, flags);
                result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
                if (result) {
-                       err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
+                       err("%s - failed submitting write urb, error %d", __func__, result);
                }
        } else {
                priv->active = 0;
@@ -906,7 +903,7 @@ static int ipaq_write_room(struct usb_serial_port *port)
 {
        struct ipaq_private     *priv = usb_get_serial_port_data(port);
 
-       dbg("%s - freelen %d", __FUNCTION__, priv->free_len);
+       dbg("%s - freelen %d", __func__, priv->free_len);
        return priv->free_len;
 }
 
@@ -914,7 +911,7 @@ static int ipaq_chars_in_buffer(struct usb_serial_port *port)
 {
        struct ipaq_private     *priv = usb_get_serial_port_data(port);
 
-       dbg("%s - queuelen %d", __FUNCTION__, priv->queue_len);
+       dbg("%s - queuelen %d", __func__, priv->queue_len);
        return priv->queue_len;
 }
 
@@ -936,7 +933,7 @@ static void ipaq_destroy_lists(struct usb_serial_port *port)
 
 static int ipaq_startup(struct usb_serial *serial)
 {
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
        if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
                err("active config #%d != 1 ??",
                        serial->dev->actconfig->desc.bConfigurationValue);
@@ -947,7 +944,7 @@ static int ipaq_startup(struct usb_serial *serial)
 
 static void ipaq_shutdown(struct usb_serial *serial)
 {
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 }
 
 static int __init ipaq_init(void)
index cbe5530f3db2554bc40b99e2c357dd33e2567e2f..bc85ca5c1c375d556d0b18c6d30ba201e2f8459f 100644 (file)
@@ -169,15 +169,15 @@ static void ipw_read_bulk_callback(struct urb *urb)
        int result;
        int status = urb->status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (status) {
                dbg("%s - nonzero read bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+       usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
 
        tty = port->tty;
        if (tty && urb->actual_length) {
@@ -195,7 +195,7 @@ static void ipw_read_bulk_callback(struct urb *urb)
                           ipw_read_bulk_callback, port);
        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);
+               dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
        return;
 }
 
@@ -206,7 +206,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
        u8 *buf_flow_init;
        int result;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        buf_flow_init = kmemdup(buf_flow_static, 16, GFP_KERNEL);
        if (!buf_flow_init)
@@ -217,7 +217,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
 
        /* --1: Tell the modem to initialize (we think) From sniffs this is always the
         * first thing that gets sent to the modem during opening of the device */
-       dbg("%s: Sending SIO_INIT (we guess)",__FUNCTION__);
+       dbg("%s: Sending SIO_INIT (we guess)",__func__);
        result = usb_control_msg(dev, usb_sndctrlpipe(dev,0),
                                 IPW_SIO_INIT,
                                 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
@@ -234,7 +234,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
        usb_clear_halt(dev, usb_sndbulkpipe(dev, port->bulk_out_endpointAddress));
 
        /*--2: Start reading from the device */ 
-       dbg("%s: setting up bulk read callback",__FUNCTION__);
+       dbg("%s: setting up bulk read callback",__func__);
        usb_fill_bulk_urb(port->read_urb, dev,
                          usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
                          port->bulk_in_buffer,
@@ -242,10 +242,10 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
                          ipw_read_bulk_callback, port);
        result = usb_submit_urb(port->read_urb, GFP_KERNEL);
        if (result < 0)
-               dbg("%s - usb_submit_urb(read bulk) failed with status %d", __FUNCTION__, result);
+               dbg("%s - usb_submit_urb(read bulk) failed with status %d", __func__, result);
 
        /*--3: Tell the modem to open the floodgates on the rx bulk channel */
-       dbg("%s:asking modem for RxRead (RXBULK_ON)",__FUNCTION__);
+       dbg("%s:asking modem for RxRead (RXBULK_ON)",__func__);
        result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                                 IPW_SIO_RXCTL,
                                 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
@@ -258,7 +258,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
                dev_err(&port->dev, "Enabling bulk RxRead failed (error = %d)\n", result);
 
        /*--4: setup the initial flowcontrol */
-       dbg("%s:setting init flowcontrol (%s)",__FUNCTION__,buf_flow_init);
+       dbg("%s:setting init flowcontrol (%s)",__func__,buf_flow_init);
        result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                                 IPW_SIO_HANDFLOW,
                                 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
@@ -272,7 +272,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
 
 
        /*--5: raise the dtr */
-       dbg("%s:raising dtr",__FUNCTION__);
+       dbg("%s:raising dtr",__func__);
        result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                                 IPW_SIO_SET_PIN,
                                 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
@@ -285,7 +285,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
                dev_err(&port->dev, "setting dtr failed (error = %d)\n", result);
 
        /*--6: raise the rts */
-       dbg("%s:raising rts",__FUNCTION__);
+       dbg("%s:raising rts",__func__);
        result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                                 IPW_SIO_SET_PIN,
                                 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
@@ -307,12 +307,12 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
        int result;
 
        if (tty_hung_up_p(filp)) {
-               dbg("%s: tty_hung_up_p ...", __FUNCTION__);
+               dbg("%s: tty_hung_up_p ...", __func__);
                return;
        }
 
        /*--1: drop the dtr */
-       dbg("%s:dropping dtr",__FUNCTION__);
+       dbg("%s:dropping dtr",__func__);
        result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                                 IPW_SIO_SET_PIN,
                                 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
@@ -325,7 +325,7 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
                dev_err(&port->dev, "dropping dtr failed (error = %d)\n", result);
 
        /*--2: drop the rts */
-       dbg("%s:dropping rts",__FUNCTION__);
+       dbg("%s:dropping rts",__func__);
        result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                                 IPW_SIO_SET_PIN, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
                                 IPW_PIN_CLRRTS,
@@ -338,7 +338,7 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
 
 
        /*--3: purge */
-       dbg("%s:sending purge",__FUNCTION__);
+       dbg("%s:sending purge",__func__);
        result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                                 IPW_SIO_PURGE, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
                                 0x03,
@@ -373,13 +373,13 @@ static void ipw_write_bulk_callback(struct urb *urb)
        struct usb_serial_port *port = urb->context;
        int status = urb->status;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        port->write_urb_busy = 0;
 
        if (status)
                dbg("%s - nonzero write bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
 
        usb_serial_port_softint(port);
 }
@@ -389,18 +389,18 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int
        struct usb_device *dev = port->serial->dev;
        int ret;
 
-       dbg("%s: TOP: count=%d, in_interrupt=%ld", __FUNCTION__,
+       dbg("%s: TOP: count=%d, in_interrupt=%ld", __func__,
                count, in_interrupt() );
 
        if (count == 0) {
-               dbg("%s - write request of 0 bytes", __FUNCTION__);
+               dbg("%s - write request of 0 bytes", __func__);
                return 0;
        }
 
        spin_lock_bh(&port->lock);
        if (port->write_urb_busy) {
                spin_unlock_bh(&port->lock);
-               dbg("%s - already writing", __FUNCTION__);
+               dbg("%s - already writing", __func__);
                return 0;
        }
        port->write_urb_busy = 1;
@@ -409,7 +409,7 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int
        count = min(count, port->bulk_out_size);
        memcpy(port->bulk_out_buffer, buf, count);
 
-       dbg("%s count now:%d", __FUNCTION__, count);
+       dbg("%s count now:%d", __func__, count);
 
        usb_fill_bulk_urb(port->write_urb, dev,
                          usb_sndbulkpipe(dev, port->bulk_out_endpointAddress),
@@ -421,11 +421,11 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int
        ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
        if (ret != 0) {
                port->write_urb_busy = 0;
-               dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, ret);
+               dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __func__, ret);
                return ret;
        }
 
-       dbg("%s returning %d", __FUNCTION__, count);
+       dbg("%s returning %d", __func__, count);
        return count;
 } 
 
@@ -448,9 +448,6 @@ static struct usb_serial_driver ipw_device = {
        .description =          "IPWireless converter",
        .usb_driver =           &usb_ipw_driver,
        .id_table =             usb_ipw_ids,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          1,
-       .num_bulk_out =         1,
        .num_ports =            1,
        .open =                 ipw_open,
        .close =                ipw_close,
index 6b803ab98543760d5669f13dced088dee87bb8d4..004d57385a757fac1064311efdb4d53b3355f009 100644 (file)
@@ -145,9 +145,6 @@ static struct usb_serial_driver ir_device = {
        .description =          "IR Dongle",
        .usb_driver =           &ir_driver,
        .id_table =             id_table,
-       .num_interrupt_in =     1,
-       .num_bulk_in =          1,
-       .num_bulk_out =         1,
        .num_ports =            1,
        .set_termios =          ir_set_termios,
        .attach =               ir_startup,
@@ -198,16 +195,16 @@ static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev,
                        USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
                        0, ifnum, desc, sizeof(*desc), 1000);
        
-       dbg("%s -  ret=%d", __FUNCTION__, ret);
+       dbg("%s -  ret=%d", __func__, ret);
        if (ret < sizeof(*desc)) {
                dbg("%s - class descriptor read %s (%d)",
-                               __FUNCTION__, 
+                               __func__,
                                (ret<0) ? "failed" : "too short",
                                ret);
                goto error;
        }
        if (desc->bDescriptorType != USB_DT_IRDA) {
-               dbg("%s - bad class descriptor type", __FUNCTION__);
+               dbg("%s - bad class descriptor type", __func__);
                goto error;
        }
        
@@ -251,7 +248,7 @@ static int ir_startup (struct usb_serial *serial)
        }
 
        dbg ("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s",
-               __FUNCTION__,
+               __func__,
                (irda_desc->wBaudRate & 0x0001) ? " 2400"    : "",
                (irda_desc->wBaudRate & 0x0002) ? " 9600"    : "",
                (irda_desc->wBaudRate & 0x0004) ? " 19200"   : "",
@@ -284,13 +281,13 @@ static int ir_open (struct usb_serial_port *port, struct file *filp)
        char *buffer;
        int result = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (buffer_size) {
                /* override the default buffer sizes */
                buffer = kmalloc (buffer_size, GFP_KERNEL);
                if (!buffer) {
-                       dev_err (&port->dev, "%s - out of memory.\n", __FUNCTION__);
+                       dev_err (&port->dev, "%s - out of memory.\n", __func__);
                        return -ENOMEM;
                }
                kfree (port->read_urb->transfer_buffer);
@@ -299,7 +296,7 @@ static int ir_open (struct usb_serial_port *port, struct file *filp)
 
                buffer = kmalloc (buffer_size, GFP_KERNEL);
                if (!buffer) {
-                       dev_err (&port->dev, "%s - out of memory.\n", __FUNCTION__);
+                       dev_err (&port->dev, "%s - out of memory.\n", __func__);
                        return -ENOMEM;
                }
                kfree (port->write_urb->transfer_buffer);
@@ -319,14 +316,14 @@ static int ir_open (struct usb_serial_port *port, struct file *filp)
                port);
        result = usb_submit_urb(port->read_urb, GFP_KERNEL);
        if (result)
-               dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
+               dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
 
        return result;
 }
 
 static void ir_close (struct usb_serial_port *port, struct file * filp)
 {
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
                         
        /* shutdown our bulk read */
        usb_kill_urb(port->read_urb);
@@ -338,10 +335,10 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
        int result;
        int transfer_size;
 
-       dbg("%s - port = %d, count = %d", __FUNCTION__, port->number, count);
+       dbg("%s - port = %d, count = %d", __func__, port->number, count);
 
        if (!port->tty) {
-               dev_err (&port->dev, "%s - no tty???\n", __FUNCTION__);
+               dev_err (&port->dev, "%s - no tty???\n", __func__);
                return 0;
        }
 
@@ -351,7 +348,7 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
        spin_lock_bh(&port->lock);
        if (port->write_urb_busy) {
                spin_unlock_bh(&port->lock);
-               dbg("%s - already writing", __FUNCTION__);
+               dbg("%s - already writing", __func__);
                return 0;
        }
        port->write_urb_busy = 1;
@@ -387,7 +384,7 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
        result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
        if (result) {
                port->write_urb_busy = 0;
-               dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
+               dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
        } else
                result = transfer_size;
 
@@ -396,22 +393,22 @@ 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;
+       struct usb_serial_port *port = urb->context;
        int status = urb->status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        port->write_urb_busy = 0;
        if (status) {
                dbg("%s - nonzero write bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        }
 
        usb_serial_debug_data (
                debug,
                &port->dev,
-               __FUNCTION__,
+               __func__,
                urb->actual_length,
                urb->transfer_buffer);
 
@@ -420,16 +417,16 @@ static void ir_write_bulk_callback (struct urb *urb)
 
 static void ir_read_bulk_callback (struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
        int result;
        int status = urb->status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (!port->open_count) {
-               dbg("%s - port closed.", __FUNCTION__);
+               dbg("%s - port closed.", __func__);
                return;
        }
 
@@ -447,7 +444,7 @@ static void ir_read_bulk_callback (struct urb *urb)
                        usb_serial_debug_data (
                                debug,
                                &port->dev,
-                               __FUNCTION__,
+                               __func__,
                                urb->actual_length,
                                data);
 
@@ -480,13 +477,13 @@ static void ir_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);
+                                       __func__, result);
 
                        break ;
 
                default:
                        dbg("%s - nonzero read bulk status received: %d",
-                               __FUNCTION__, 
+                               __func__,
                                status);
                        break ;
 
@@ -502,7 +499,7 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
        speed_t baud;
        int ir_baud;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        baud = tty_get_baud_rate(port->tty);
 
@@ -554,7 +551,7 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
 
        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);
+               dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
 
        /* Only speed changes are supported */
        tty_termios_copy_hw(port->tty->termios, old_termios);
index fde188e23ce1f0fad9539b9a6c7c09beb666cc53..8a217648b250311abf685cd0f89cc558de41f7ca 100644 (file)
@@ -98,10 +98,10 @@ static int iuu_alloc_buf(struct iuu_private *priv)
        priv->writebuf = kzalloc(256, GFP_KERNEL);
        if (!priv->buf || !priv->dbgbuf || !priv->writebuf) {
                iuu_free_buf(priv);
-               dbg("%s problem allocation buffer", __FUNCTION__);
+               dbg("%s problem allocation buffer", __func__);
                return -ENOMEM;
        }
-       dbg("%s - Privates buffers allocation success", __FUNCTION__);
+       dbg("%s - Privates buffers allocation success", __func__);
        return 0;
 }
 
@@ -109,7 +109,7 @@ static int iuu_startup(struct usb_serial *serial)
 {
        struct iuu_private *priv;
        priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL);
-       dbg("%s- priv allocation success", __FUNCTION__);
+       dbg("%s- priv allocation success", __func__);
        if (!priv)
                return -ENOMEM;
        if (iuu_alloc_buf(priv)) {
@@ -130,17 +130,17 @@ static void iuu_shutdown(struct usb_serial *serial)
        if (!port)
                return;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        if (priv) {
                iuu_free_buf(priv);
-               dbg("%s - I will free all", __FUNCTION__);
+               dbg("%s - I will free all", __func__);
                usb_set_serial_port_data(port, NULL);
 
-               dbg("%s - priv is not anymore in port structure", __FUNCTION__);
+               dbg("%s - priv is not anymore in port structure", __func__);
                kfree(priv);
 
-               dbg("%s priv is now kfree", __FUNCTION__);
+               dbg("%s priv is now kfree", __func__);
        }
 }
 
@@ -148,20 +148,21 @@ static int iuu_tiocmset(struct usb_serial_port *port, struct file *file,
                        unsigned int set, unsigned int clear)
 {
        struct iuu_private *priv = usb_get_serial_port_data(port);
-       struct tty_struct *tty;
-       tty = port->tty;
+       unsigned long flags;
 
-       dbg("%s (%d) msg : SET = 0x%04x, CLEAR = 0x%04x ", __FUNCTION__,
+       /* FIXME: locking on tiomstatus */
+       dbg("%s (%d) msg : SET = 0x%04x, CLEAR = 0x%04x ", __func__,
            port->number, set, clear);
+
+       spin_lock_irqsave(&priv->lock, flags);
        if (set & TIOCM_RTS)
                priv->tiostatus = TIOCM_RTS;
 
        if (!(set & TIOCM_RTS) && priv->tiostatus == TIOCM_RTS) {
-               dbg("%s TIOCMSET RESET called !!!", __FUNCTION__);
+               dbg("%s TIOCMSET RESET called !!!", __func__);
                priv->reset = 1;
-               return 0;
        }
-
+       spin_unlock_irqrestore(&priv->lock, flags);
        return 0;
 }
 
@@ -173,17 +174,24 @@ static int iuu_tiocmset(struct usb_serial_port *port, struct file *file,
 static int iuu_tiocmget(struct usb_serial_port *port, struct file *file)
 {
        struct iuu_private *priv = usb_get_serial_port_data(port);
-       return priv->tiostatus;
+       unsigned long flags;
+       int rc;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       rc = priv->tiostatus;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return rc;
 }
 
 static void iuu_rxcmd(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        int result;
-       dbg("%s - enter", __FUNCTION__);
+       dbg("%s - enter", __func__);
 
        if (urb->status) {
-               dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+               dbg("%s - urb->status = %d", __func__, urb->status);
                /* error stop all */
                return;
        }
@@ -203,7 +211,7 @@ static int iuu_reset(struct usb_serial_port *port, u8 wt)
        struct iuu_private *priv = usb_get_serial_port_data(port);
        int result;
        char *buf_ptr = port->write_urb->transfer_buffer;
-       dbg("%s - enter", __FUNCTION__);
+       dbg("%s - enter", __func__);
 
        /* Prepare the reset sequence */
 
@@ -232,19 +240,19 @@ static int iuu_reset(struct usb_serial_port *port, u8 wt)
  */
 static void iuu_update_status_callback(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct iuu_private *priv = usb_get_serial_port_data(port);
        u8 *st;
-       dbg("%s - enter", __FUNCTION__);
+       dbg("%s - enter", __func__);
 
        if (urb->status) {
-               dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+               dbg("%s - urb->status = %d", __func__, urb->status);
                /* error stop all */
                return;
        }
 
        st = urb->transfer_buffer;
-       dbg("%s - enter", __FUNCTION__);
+       dbg("%s - enter", __func__);
        if (urb->actual_length == 1) {
                switch (st[0]) {
                case 0x1:
@@ -262,11 +270,11 @@ static void iuu_update_status_callback(struct urb *urb)
 
 static void iuu_status_callback(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        int result;
-       dbg("%s - enter", __FUNCTION__);
+       dbg("%s - enter", __func__);
 
-       dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+       dbg("%s - urb->status = %d", __func__, urb->status);
        usb_fill_bulk_urb(port->read_urb, port->serial->dev,
                          usb_rcvbulkpipe(port->serial->dev,
                                          port->bulk_in_endpointAddress),
@@ -279,7 +287,7 @@ static int iuu_status(struct usb_serial_port *port)
 {
        int result;
 
-       dbg("%s - enter", __FUNCTION__);
+       dbg("%s - enter", __func__);
 
        memset(port->write_urb->transfer_buffer, IUU_GET_STATE_REGISTER, 1);
        usb_fill_bulk_urb(port->write_urb, port->serial->dev,
@@ -298,7 +306,7 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
        struct usb_serial *serial = port->serial;
        int actual = 0;
 
-       dbg("%s - enter", __FUNCTION__);
+       dbg("%s - enter", __func__);
 
        /* send the data out the bulk port */
 
@@ -309,9 +317,9 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
                         count, &actual, HZ * 1);
 
        if (status != IUU_OPERATION_OK) {
-               dbg("%s - error = %2x", __FUNCTION__, status);
+               dbg("%s - error = %2x", __func__, status);
        } else {
-               dbg("%s - write OK !", __FUNCTION__);
+               dbg("%s - write OK !", __func__);
        }
        return status;
 }
@@ -322,7 +330,7 @@ static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
        struct usb_serial *serial = port->serial;
        int actual = 0;
 
-       dbg("%s - enter", __FUNCTION__);
+       dbg("%s - enter", __func__);
 
        /* send the data out the bulk port */
 
@@ -333,9 +341,9 @@ static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
                         count, &actual, HZ * 1);
 
        if (status != IUU_OPERATION_OK) {
-               dbg("%s - error = %2x", __FUNCTION__, status);
+               dbg("%s - error = %2x", __func__, status);
        } else {
-               dbg("%s - read OK !", __FUNCTION__);
+               dbg("%s - read OK !", __func__);
        }
 
        return status;
@@ -350,7 +358,7 @@ static int iuu_led(struct usb_serial_port *port, unsigned int R,
        if (!buf)
                return -ENOMEM;
 
-       dbg("%s - enter", __FUNCTION__);
+       dbg("%s - enter", __func__);
 
        buf[0] = IUU_SET_LED;
        buf[1] = R & 0xFF;
@@ -363,9 +371,9 @@ static int iuu_led(struct usb_serial_port *port, unsigned int R,
        status = bulk_immediate(port, buf, 8);
        kfree(buf);
        if (status != IUU_OPERATION_OK)
-               dbg("%s - led error status = %2x", __FUNCTION__, status);
+               dbg("%s - led error status = %2x", __func__, status);
        else
-               dbg("%s - led OK !", __FUNCTION__);
+               dbg("%s - led OK !", __func__);
        return IUU_OPERATION_OK;
 }
 
@@ -384,7 +392,7 @@ static void iuu_rgbf_fill_buffer(u8 *buf, u8 r1, u8 r2, u8 g1, u8 g2, u8 b1,
 
 static void iuu_led_activity_on(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        int result;
        char *buf_ptr = port->write_urb->transfer_buffer;
        *buf_ptr++ = IUU_SET_LED;
@@ -405,7 +413,7 @@ static void iuu_led_activity_on(struct urb *urb)
 
 static void iuu_led_activity_off(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        int result;
        char *buf_ptr = port->write_urb->transfer_buffer;
        if (xmas == 1) {
@@ -443,7 +451,7 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq)
        unsigned int P2 = 0;
        int frq = (int)dwFrq;
 
-       dbg("%s - enter", __FUNCTION__);
+       dbg("%s - enter", __func__);
 
        if (frq == 0) {
                priv->buf[Count++] = IUU_UART_WRITE_I2C;
@@ -453,7 +461,7 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq)
 
                status = bulk_immediate(port, (u8 *) priv->buf, Count);
                if (status != 0) {
-                       dbg("%s - write error ", __FUNCTION__);
+                       dbg("%s - write error ", __func__);
                        return status;
                }
        } else if (frq == 3579000) {
@@ -562,7 +570,7 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq)
 
        status = bulk_immediate(port, (u8 *) priv->buf, Count);
        if (status != IUU_OPERATION_OK)
-               dbg("%s - write error ", __FUNCTION__);
+               dbg("%s - write error ", __func__);
        return status;
 }
 
@@ -573,7 +581,7 @@ static int iuu_uart_flush(struct usb_serial_port *port)
        u8 rxcmd = IUU_UART_RX;
        struct iuu_private *priv = usb_get_serial_port_data(port);
 
-       dbg("%s - enter", __FUNCTION__);
+       dbg("%s - enter", __func__);
 
        if (iuu_led(port, 0xF000, 0, 0, 0xFF) < 0)
                return -EIO;
@@ -581,50 +589,50 @@ static int iuu_uart_flush(struct usb_serial_port *port)
        for (i = 0; i < 2; i++) {
                status = bulk_immediate(port, &rxcmd, 1);
                if (status != IUU_OPERATION_OK) {
-                       dbg("%s - uart_flush_write error", __FUNCTION__);
+                       dbg("%s - uart_flush_write error", __func__);
                        return status;
                }
 
                status = read_immediate(port, &priv->len, 1);
                if (status != IUU_OPERATION_OK) {
-                       dbg("%s - uart_flush_read error", __FUNCTION__);
+                       dbg("%s - uart_flush_read error", __func__);
                        return status;
                }
 
                if (priv->len > 0) {
-                       dbg("%s - uart_flush datalen is : %i ", __FUNCTION__,
+                       dbg("%s - uart_flush datalen is : %i ", __func__,
                            priv->len);
                        status = read_immediate(port, priv->buf, priv->len);
                        if (status != IUU_OPERATION_OK) {
-                               dbg("%s - uart_flush_read error", __FUNCTION__);
+                               dbg("%s - uart_flush_read error", __func__);
                                return status;
                        }
                }
        }
-       dbg("%s - uart_flush_read OK!", __FUNCTION__);
+       dbg("%s - uart_flush_read OK!", __func__);
        iuu_led(port, 0, 0xF000, 0, 0xFF);
        return status;
 }
 
 static void read_buf_callback(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        unsigned char *data = urb->transfer_buffer;
        struct tty_struct *tty;
-       dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+       dbg("%s - urb->status = %d", __func__, urb->status);
 
        if (urb->status) {
-               dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+               dbg("%s - urb->status = %d", __func__, urb->status);
                if (urb->status == -EPROTO) {
                        /* reschedule needed */
                }
                return;
        }
 
-       dbg("%s - %i chars to write", __FUNCTION__, urb->actual_length);
+       dbg("%s - %i chars to write", __func__, urb->actual_length);
        tty = port->tty;
        if (data == NULL)
-               dbg("%s - data is NULL !!!", __FUNCTION__);
+               dbg("%s - data is NULL !!!", __func__);
        if (tty && urb->actual_length && data) {
                tty_insert_flip_string(tty, data, urb->actual_length);
                tty_flip_buffer_push(tty);
@@ -639,7 +647,7 @@ static int iuu_bulk_write(struct usb_serial_port *port)
        int result;
        int i;
        char *buf_ptr = port->write_urb->transfer_buffer;
-       dbg("%s - enter", __FUNCTION__);
+       dbg("%s - enter", __func__);
 
        *buf_ptr++ = IUU_UART_ESC;
        *buf_ptr++ = IUU_UART_TX;
@@ -652,7 +660,7 @@ static int iuu_bulk_write(struct usb_serial_port *port)
                        sprintf(priv->dbgbuf + i*2 ,
                                "%02X", priv->writebuf[i]);
                priv->dbgbuf[priv->writelen+i*2] = 0;
-               dbg("%s - writing %i chars : %s", __FUNCTION__,
+               dbg("%s - writing %i chars : %s", __func__,
                    priv->writelen, priv->dbgbuf);
        }
        usb_fill_bulk_urb(port->write_urb, port->serial->dev,
@@ -671,7 +679,7 @@ static int iuu_bulk_write(struct usb_serial_port *port)
 static int iuu_read_buf(struct usb_serial_port *port, int len)
 {
        int result;
-       dbg("%s - enter", __FUNCTION__);
+       dbg("%s - enter", __func__);
 
        usb_fill_bulk_urb(port->read_urb, port->serial->dev,
                          usb_rcvbulkpipe(port->serial->dev,
@@ -684,7 +692,7 @@ static int iuu_read_buf(struct usb_serial_port *port, int len)
 
 static void iuu_uart_read_callback(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct iuu_private *priv = usb_get_serial_port_data(port);
        unsigned int flags;
        int status;
@@ -693,21 +701,21 @@ static void iuu_uart_read_callback(struct urb *urb)
        unsigned char *data = urb->transfer_buffer;
        priv->poll++;
 
-       dbg("%s - enter", __FUNCTION__);
+       dbg("%s - enter", __func__);
 
        if (urb->status) {
-               dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+               dbg("%s - urb->status = %d", __func__, urb->status);
                /* error stop all */
                return;
        }
        if (data == NULL)
-               dbg("%s - data is NULL !!!", __FUNCTION__);
+               dbg("%s - data is NULL !!!", __func__);
 
        if (urb->actual_length == 1  && data != NULL)
                len = (int) data[0];
 
        if (urb->actual_length > 1) {
-               dbg("%s - urb->actual_length = %i", __FUNCTION__,
+               dbg("%s - urb->actual_length = %i", __func__,
                    urb->actual_length);
                error = 1;
                return;
@@ -716,7 +724,7 @@ static void iuu_uart_read_callback(struct urb *urb)
 
        if (len > 0 && error == 0) {
                dbg("%s - call read buf - len to read is %i ",
-                       __FUNCTION__, len);
+                       __func__, len);
                status = iuu_read_buf(port, len);
                return;
        }
@@ -742,7 +750,7 @@ static void iuu_uart_read_callback(struct urb *urb)
        }
        spin_unlock_irqrestore(&priv->lock, flags);
        /* if nothing to write call again rxcmd */
-       dbg("%s - rxcmd recall", __FUNCTION__);
+       dbg("%s - rxcmd recall", __func__);
        iuu_led_activity_off(urb);
        return;
 }
@@ -752,7 +760,7 @@ static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf,
 {
        struct iuu_private *priv = usb_get_serial_port_data(port);
        unsigned int flags;
-       dbg("%s - enter", __FUNCTION__);
+       dbg("%s - enter", __func__);
 
        if (count > 256)
                return -ENOMEM;
@@ -773,14 +781,14 @@ static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf,
 
 static void read_rxcmd_callback(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        int result;
-       dbg("%s - enter", __FUNCTION__);
+       dbg("%s - enter", __func__);
 
-       dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+       dbg("%s - urb->status = %d", __func__, urb->status);
 
        if (urb->status) {
-               dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+               dbg("%s - urb->status = %d", __func__, urb->status);
                /* error stop all */
                return;
        }
@@ -791,7 +799,7 @@ static void read_rxcmd_callback(struct urb *urb)
                          port->read_urb->transfer_buffer, 256,
                          iuu_uart_read_callback, port);
        result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-       dbg("%s - submit result = %d", __FUNCTION__, result);
+       dbg("%s - submit result = %d", __func__, result);
        return;
 }
 
@@ -812,13 +820,13 @@ static int iuu_uart_on(struct usb_serial_port *port)
 
        status = bulk_immediate(port, buf, 4);
        if (status != IUU_OPERATION_OK) {
-               dbg("%s - uart_on error", __FUNCTION__);
+               dbg("%s - uart_on error", __func__);
                goto uart_enable_failed;
        }
        /*  iuu_reset() the card after iuu_uart_on() */
        status = iuu_uart_flush(port);
        if (status != IUU_OPERATION_OK)
-               dbg("%s - uart_flush error", __FUNCTION__);
+               dbg("%s - uart_flush error", __func__);
 uart_enable_failed:
        kfree(buf);
        return status;
@@ -836,7 +844,7 @@ static int iuu_uart_off(struct usb_serial_port *port)
 
        status = bulk_immediate(port, buf, 1);
        if (status != IUU_OPERATION_OK)
-               dbg("%s - uart_off error", __FUNCTION__);
+               dbg("%s - uart_off error", __func__);
 
        kfree(buf);
        return status;
@@ -930,7 +938,7 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud,
 
        status = bulk_immediate(port, dataout, DataCount);
        if (status != IUU_OPERATION_OK)
-               dbg("%s - uart_off error", __FUNCTION__);
+               dbg("%s - uart_off error", __func__);
        kfree(dataout);
        return status;
 }
@@ -952,7 +960,7 @@ static void iuu_close(struct usb_serial_port *port, struct file *filp)
        if (!serial)
                return;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        iuu_uart_off(port);
        if (serial->dev) {
@@ -969,7 +977,7 @@ static void iuu_close(struct usb_serial_port *port, struct file *filp)
                }
                /* free writebuf */
                /* shutdown our urbs */
-               dbg("%s - shutting down urbs", __FUNCTION__);
+               dbg("%s - shutting down urbs", __func__);
                usb_kill_urb(port->write_urb);
                usb_kill_urb(port->read_urb);
                usb_kill_urb(port->interrupt_in_urb);
@@ -990,7 +998,7 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp)
        unsigned long flags;
        struct iuu_private *priv = usb_get_serial_port_data(port);
 
-       dbg("%s -  port %d", __FUNCTION__, port->number);
+       dbg("%s -  port %d", __func__, port->number);
        usb_clear_halt(serial->dev, port->write_urb->pipe);
        usb_clear_halt(serial->dev, port->read_urb->pipe);
 
@@ -1127,7 +1135,7 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp)
 
        iuu_uart_flush(port);
 
-       dbg("%s - initialization done", __FUNCTION__);
+       dbg("%s - initialization done", __func__);
 
        memset(port->write_urb->transfer_buffer, IUU_UART_RX, 1);
        usb_fill_bulk_urb(port->write_urb, port->serial->dev,
@@ -1139,11 +1147,11 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp)
 
        if (result) {
                dev_err(&port->dev, "%s - failed submitting read urb,"
-                       " error %d\n", __FUNCTION__, result);
+                       " error %d\n", __func__, result);
                iuu_close(port, NULL);
                return -EPROTO;
        } else {
-               dbg("%s - rxcmd OK", __FUNCTION__);
+               dbg("%s - rxcmd OK", __func__);
        }
        return result;
 }
@@ -1154,9 +1162,6 @@ static struct usb_serial_driver iuu_device = {
                   .name = "iuu_phoenix",
                   },
        .id_table = id_table,
-       .num_interrupt_in = NUM_DONT_CARE,
-       .num_bulk_in = 1,
-       .num_bulk_out = 1,
        .num_ports = 1,
        .open = iuu_open,
        .close = iuu_close,
index ea7bba69f4da129397e111463a0ec13995d0ac5a..3df8a66c5c3cd7ea57449069fa651c3643815352 100644 (file)
@@ -244,13 +244,13 @@ module_exit(keyspan_exit);
 
 static void keyspan_rx_throttle (struct usb_serial_port *port)
 {
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 }
 
 
 static void keyspan_rx_unthrottle (struct usb_serial_port *port)
 {
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 }
 
 
@@ -258,7 +258,7 @@ static void keyspan_break_ctl (struct usb_serial_port *port, int break_state)
 {
        struct keyspan_port_private     *p_priv;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        p_priv = usb_get_serial_port_data(port);
 
@@ -280,7 +280,7 @@ static void keyspan_set_termios (struct usb_serial_port *port,
        unsigned int                    cflag;
        struct tty_struct               *tty = port->tty;
 
-       dbg("%s", __FUNCTION__); 
+       dbg("%s", __func__);
 
        p_priv = usb_get_serial_port_data(port);
        d_details = p_priv->device_details;
@@ -377,7 +377,7 @@ static int keyspan_write(struct usb_serial_port *port,
        }
        
        dbg("%s - for port %d (%d chars), flip=%d",
-           __FUNCTION__, port->number, count, p_priv->out_flip);
+           __func__, port->number, count, p_priv->out_flip);
 
        for (left = count; left > 0; left -= todo) {
                todo = left;
@@ -389,11 +389,11 @@ static int keyspan_write(struct usb_serial_port *port,
                /* Check we have a valid urb/endpoint before we use it... */
                if ((this_urb = p_priv->out_urbs[flip]) == NULL) {
                        /* no bulk out, so return 0 bytes written */
-                       dbg("%s - no output urb :(", __FUNCTION__);
+                       dbg("%s - no output urb :(", __func__);
                        return count;
                }
 
-               dbg("%s - endpoint %d flip %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), flip);
+               dbg("%s - endpoint %d flip %d", __func__, usb_pipeendpoint(this_urb->pipe), flip);
 
                if (this_urb->status == -EINPROGRESS) {
                        if (time_before(jiffies, p_priv->tx_start_time[flip] + 10 * HZ))
@@ -435,17 +435,17 @@ static void       usa26_indat_callback(struct urb *urb)
        unsigned char           *data = urb->transfer_buffer;
        int status = urb->status;
 
-       dbg ("%s", __FUNCTION__); 
+       dbg ("%s", __func__);
 
        endpoint = usb_pipeendpoint(urb->pipe);
 
        if (status) {
                dbg("%s - nonzero status: %x on endpoint %d.",
-                   __FUNCTION__, status, endpoint);
+                   __func__, status, endpoint);
                return;
        }
 
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
        tty = port->tty;
        if (tty && urb->actual_length) {
                /* 0x80 bit is error flag */
@@ -459,7 +459,7 @@ static void usa26_indat_callback(struct urb *urb)
                        }
                } else {
                        /* some bytes had errors, every byte has status */
-                       dbg("%s - RX error!!!!", __FUNCTION__);
+                       dbg("%s - RX error!!!!", __func__);
                        for (i = 0; i + 1 < urb->actual_length; i += 2) {
                                int stat = data[i], flag = 0;
                                if (stat & RXERROR_OVERRUN)
@@ -479,7 +479,7 @@ static void usa26_indat_callback(struct urb *urb)
        urb->dev = port->serial->dev;
        if (port->open_count)
                if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
-                       dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+                       dbg("%s - resubmit read urb failed. (%d)", __func__, err);
                }
        return;
 }
@@ -490,9 +490,9 @@ static void usa2x_outdat_callback(struct urb *urb)
        struct usb_serial_port *port;
        struct keyspan_port_private *p_priv;
 
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
        p_priv = usb_get_serial_port_data(port);
-       dbg ("%s - urb %d", __FUNCTION__, urb == p_priv->out_urbs[1]); 
+       dbg ("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
 
        if (port->open_count)
                usb_serial_port_softint(port);
@@ -500,7 +500,7 @@ static void usa2x_outdat_callback(struct urb *urb)
 
 static void    usa26_inack_callback(struct urb *urb)
 {
-       dbg ("%s", __FUNCTION__); 
+       dbg ("%s", __func__);
        
 }
 
@@ -509,11 +509,11 @@ static void       usa26_outcont_callback(struct urb *urb)
        struct usb_serial_port *port;
        struct keyspan_port_private *p_priv;
 
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
        p_priv = usb_get_serial_port_data(port);
 
        if (p_priv->resend_cont) {
-               dbg ("%s - sending setup", __FUNCTION__); 
+               dbg ("%s - sending setup", __func__);
                keyspan_usa26_send_setup(port->serial, port, p_priv->resend_cont - 1);
        }
 }
@@ -528,14 +528,14 @@ static void       usa26_instat_callback(struct urb *urb)
        int old_dcd_state, err;
        int status = urb->status;
 
-       serial = (struct usb_serial *) urb->context;
+       serial =  urb->context;
 
        if (status) {
-               dbg("%s - nonzero status: %x", __FUNCTION__, status);
+               dbg("%s - nonzero status: %x", __func__, status);
                return;
        }
        if (urb->actual_length != 9) {
-               dbg("%s - %d byte report??", __FUNCTION__, urb->actual_length);
+               dbg("%s - %d byte report??", __func__, urb->actual_length);
                goto exit;
        }
 
@@ -543,7 +543,7 @@ static void usa26_instat_callback(struct urb *urb)
 
 #if 0
        dbg("%s - port status: port %d cts %d dcd %d dsr %d ri %d toff %d txoff %d rxen %d cr %d",
-           __FUNCTION__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, msg->ri, msg->_txOff,
+           __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, msg->ri, msg->_txOff,
            msg->_txXoff, msg->rxEnabled, msg->controlResponse);
 #endif
 
@@ -552,7 +552,7 @@ static void usa26_instat_callback(struct urb *urb)
 
        /* Check port number from message and retrieve private data */  
        if (msg->port >= serial->num_ports) {
-               dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port);
+               dbg ("%s - Unexpected port number %d", __func__, msg->port);
                goto exit;
        }
        port = serial->port[msg->port];
@@ -576,14 +576,14 @@ static void       usa26_instat_callback(struct urb *urb)
        /* Resubmit urb so we continue receiving */
        urb->dev = serial->dev;
        if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
-               dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+               dbg("%s - resubmit read urb failed. (%d)", __func__, err);
        }
 exit: ;
 }
 
 static void    usa26_glocont_callback(struct urb *urb)
 {
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
        
 }
 
@@ -597,9 +597,9 @@ static void usa28_indat_callback(struct urb *urb)
        struct keyspan_port_private             *p_priv;
        int status = urb->status;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
        p_priv = usb_get_serial_port_data(port);
        data = urb->transfer_buffer;
 
@@ -609,11 +609,11 @@ static void usa28_indat_callback(struct urb *urb)
        do {
                if (status) {
                        dbg("%s - nonzero status: %x on endpoint %d.",
-                           __FUNCTION__, status, usb_pipeendpoint(urb->pipe));
+                           __func__, status, usb_pipeendpoint(urb->pipe));
                        return;
                }
 
-               port = (struct usb_serial_port *) urb->context;
+               port =  urb->context;
                p_priv = usb_get_serial_port_data(port);
                data = urb->transfer_buffer;
 
@@ -629,7 +629,7 @@ static void usa28_indat_callback(struct urb *urb)
                urb->dev = port->serial->dev;
                if (port->open_count)
                        if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
-                               dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+                               dbg("%s - resubmit read urb failed. (%d)", __func__, err);
                        }
                p_priv->in_flip ^= 1;
 
@@ -639,7 +639,7 @@ static void usa28_indat_callback(struct urb *urb)
 
 static void    usa28_inack_callback(struct urb *urb)
 {
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 }
 
 static void    usa28_outcont_callback(struct urb *urb)
@@ -647,11 +647,11 @@ static void       usa28_outcont_callback(struct urb *urb)
        struct usb_serial_port *port;
        struct keyspan_port_private *p_priv;
 
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
        p_priv = usb_get_serial_port_data(port);
 
        if (p_priv->resend_cont) {
-               dbg ("%s - sending setup", __FUNCTION__);
+               dbg ("%s - sending setup", __func__);
                keyspan_usa28_send_setup(port->serial, port, p_priv->resend_cont - 1);
        }
 }
@@ -667,19 +667,19 @@ static void       usa28_instat_callback(struct urb *urb)
        int old_dcd_state;
        int status = urb->status;
 
-       serial = (struct usb_serial *) urb->context;
+       serial =  urb->context;
 
        if (status) {
-               dbg("%s - nonzero status: %x", __FUNCTION__, status);
+               dbg("%s - nonzero status: %x", __func__, status);
                return;
        }
 
        if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
-               dbg("%s - bad length %d", __FUNCTION__, urb->actual_length);
+               dbg("%s - bad length %d", __func__, urb->actual_length);
                goto exit;
        }
 
-       /*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __FUNCTION__
+       /*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__
            data[0], data[1], data[2], data[3], data[4], data[5],
            data[6], data[7], data[8], data[9], data[10], data[11]);*/
        
@@ -689,7 +689,7 @@ static void usa28_instat_callback(struct urb *urb)
 
                /* Check port number from message and retrieve private data */  
        if (msg->port >= serial->num_ports) {
-               dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port);
+               dbg ("%s - Unexpected port number %d", __func__, msg->port);
                goto exit;
        }
        port = serial->port[msg->port];
@@ -713,14 +713,14 @@ static void       usa28_instat_callback(struct urb *urb)
                /* Resubmit urb so we continue receiving */
        urb->dev = serial->dev;
        if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
-               dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+               dbg("%s - resubmit read urb failed. (%d)", __func__, err);
        }
 exit: ;
 }
 
 static void    usa28_glocont_callback(struct urb *urb)
 {
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 }
 
 
@@ -731,15 +731,15 @@ static void       usa49_glocont_callback(struct urb *urb)
        struct keyspan_port_private *p_priv;
        int i;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
-       serial = (struct usb_serial *) urb->context;
+       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__); 
+                       dbg ("%s - sending setup", __func__);
                        keyspan_usa49_send_setup(serial, port, p_priv->resend_cont - 1);
                        break;
                }
@@ -759,21 +759,21 @@ static void       usa49_instat_callback(struct urb *urb)
        int old_dcd_state;
        int status = urb->status;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
-       serial = (struct usb_serial *) urb->context;
+       serial =  urb->context;
 
        if (status) {
-               dbg("%s - nonzero status: %x", __FUNCTION__, status);
+               dbg("%s - nonzero status: %x", __func__, status);
                return;
        }
 
        if (urb->actual_length != sizeof(struct keyspan_usa49_portStatusMessage)) {
-               dbg("%s - bad length %d", __FUNCTION__, urb->actual_length);
+               dbg("%s - bad length %d", __func__, urb->actual_length);
                goto exit;
        }
 
-       /*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __FUNCTION__, 
+       /*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __func__,
            data[0], data[1], data[2], data[3], data[4], data[5],
            data[6], data[7], data[8], data[9], data[10]);*/
        
@@ -782,7 +782,7 @@ static void usa49_instat_callback(struct urb *urb)
 
                /* Check port number from message and retrieve private data */  
        if (msg->portNumber >= serial->num_ports) {
-               dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->portNumber);
+               dbg ("%s - Unexpected port number %d", __func__, msg->portNumber);
                goto exit;
        }
        port = serial->port[msg->portNumber];
@@ -807,14 +807,14 @@ static void       usa49_instat_callback(struct urb *urb)
        urb->dev = serial->dev;
 
        if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
-               dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+               dbg("%s - resubmit read urb failed. (%d)", __func__, err);
        }
 exit:  ;
 }
 
 static void    usa49_inack_callback(struct urb *urb)
 {
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 }
 
 static void    usa49_indat_callback(struct urb *urb)
@@ -826,17 +826,17 @@ static void       usa49_indat_callback(struct urb *urb)
        unsigned char           *data = urb->transfer_buffer;
        int status = urb->status;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        endpoint = usb_pipeendpoint(urb->pipe);
 
        if (status) {
-               dbg("%s - nonzero status: %x on endpoint %d.", __FUNCTION__,
+               dbg("%s - nonzero status: %x on endpoint %d.", __func__,
                    status, endpoint);
                return;
        }
 
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
        tty = port->tty;
        if (tty && urb->actual_length) {
                /* 0x80 bit is error flag */
@@ -866,7 +866,7 @@ static void usa49_indat_callback(struct urb *urb)
        urb->dev = port->serial->dev;
        if (port->open_count)
                if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
-                       dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+                       dbg("%s - resubmit read urb failed. (%d)", __func__, err);
                }
 }
 
@@ -879,12 +879,12 @@ static void usa49wg_indat_callback(struct urb *urb)
        unsigned char           *data = urb->transfer_buffer;
        int status = urb->status;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        serial = urb->context;
 
        if (status) {
-               dbg("%s - nonzero status: %x", __FUNCTION__, status);
+               dbg("%s - nonzero status: %x", __func__, status);
                return;
        }
 
@@ -898,7 +898,7 @@ static void usa49wg_indat_callback(struct urb *urb)
                        /* Check port number from message*/
                        if (data[i] >= serial->num_ports) {
                                dbg ("%s - Unexpected port number %d",
-                                       __FUNCTION__, data[i]);
+                                       __func__, data[i]);
                                return;
                        }
                        port = serial->port[data[i++]];
@@ -944,13 +944,13 @@ static void usa49wg_indat_callback(struct urb *urb)
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err != 0)
-               dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+               dbg("%s - resubmit read urb failed. (%d)", __func__, err);
 }
 
 /* not used, usa-49 doesn't have per-port control endpoints */
 static void usa49_outcont_callback(struct urb *urb)
 {
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 }
 
 static void usa90_indat_callback(struct urb *urb)
@@ -963,17 +963,17 @@ static void usa90_indat_callback(struct urb *urb)
        unsigned char           *data = urb->transfer_buffer;
        int status = urb->status;
 
-       dbg ("%s", __FUNCTION__); 
+       dbg ("%s", __func__);
 
        endpoint = usb_pipeendpoint(urb->pipe);
 
        if (status) {
                dbg("%s - nonzero status: %x on endpoint %d.",
-                   __FUNCTION__, status, endpoint);
+                   __func__, status, endpoint);
                return;
        }
 
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
        p_priv = usb_get_serial_port_data(port);
 
        tty = port->tty;
@@ -1000,7 +1000,7 @@ static void usa90_indat_callback(struct urb *urb)
                        } 
                        else {
                        /* some bytes had errors, every byte has status */
-                               dbg("%s - RX error!!!!", __FUNCTION__);
+                               dbg("%s - RX error!!!!", __func__);
                                for (i = 0; i + 1 < urb->actual_length; i += 2) {
                                        int stat = data[i], flag = 0;
                                        if (stat & RXERROR_OVERRUN)
@@ -1021,7 +1021,7 @@ static void usa90_indat_callback(struct urb *urb)
        urb->dev = port->serial->dev;
        if (port->open_count)
                if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
-                       dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+                       dbg("%s - resubmit read urb failed. (%d)", __func__, err);
                }
        return;
 }
@@ -1037,14 +1037,14 @@ static void     usa90_instat_callback(struct urb *urb)
        int old_dcd_state, err;
        int status = urb->status;
 
-       serial = (struct usb_serial *) urb->context;
+       serial =  urb->context;
 
        if (status) {
-               dbg("%s - nonzero status: %x", __FUNCTION__, status);
+               dbg("%s - nonzero status: %x", __func__, status);
                return;
        }
        if (urb->actual_length < 14) {
-               dbg("%s - %d byte report??", __FUNCTION__, urb->actual_length);
+               dbg("%s - %d byte report??", __func__, urb->actual_length);
                goto exit;
        }
 
@@ -1073,7 +1073,7 @@ static void       usa90_instat_callback(struct urb *urb)
        /* Resubmit urb so we continue receiving */
        urb->dev = serial->dev;
        if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
-               dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+               dbg("%s - resubmit read urb failed. (%d)", __func__, err);
        }
 exit:
        ;
@@ -1084,11 +1084,11 @@ static void     usa90_outcont_callback(struct urb *urb)
        struct usb_serial_port *port;
        struct keyspan_port_private *p_priv;
 
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
        p_priv = usb_get_serial_port_data(port);
 
        if (p_priv->resend_cont) {
-               dbg ("%s - sending setup", __FUNCTION__); 
+               dbg ("%s - sending setup", __func__);
                keyspan_usa90_send_setup(port->serial, port, p_priv->resend_cont - 1);
        }
 }
@@ -1105,17 +1105,17 @@ static void     usa67_instat_callback(struct urb *urb)
        int old_dcd_state;
        int status = urb->status;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        serial = urb->context;
 
        if (status) {
-               dbg("%s - nonzero status: %x", __FUNCTION__, status);
+               dbg("%s - nonzero status: %x", __func__, status);
                return;
        }
 
        if (urb->actual_length != sizeof(struct keyspan_usa67_portStatusMessage)) {
-               dbg("%s - bad length %d", __FUNCTION__, urb->actual_length);
+               dbg("%s - bad length %d", __func__, urb->actual_length);
                return;
        }
 
@@ -1125,7 +1125,7 @@ static void       usa67_instat_callback(struct urb *urb)
 
        /* Check port number from message and retrieve private data */
        if (msg->port >= serial->num_ports) {
-               dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port);
+               dbg ("%s - Unexpected port number %d", __func__, msg->port);
                return;
        }
 
@@ -1149,7 +1149,7 @@ static void       usa67_instat_callback(struct urb *urb)
        urb->dev = serial->dev;
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err != 0)
-               dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+               dbg("%s - resubmit read urb failed. (%d)", __func__, err);
 }
 
 static void usa67_glocont_callback(struct urb *urb)
@@ -1159,7 +1159,7 @@ static void usa67_glocont_callback(struct urb *urb)
        struct keyspan_port_private *p_priv;
        int i;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        serial = urb->context;
        for (i = 0; i < serial->num_ports; ++i) {
@@ -1167,7 +1167,7 @@ static void usa67_glocont_callback(struct urb *urb)
                p_priv = usb_get_serial_port_data(port);
 
                if (p_priv->resend_cont) {
-                       dbg ("%s - sending setup", __FUNCTION__);
+                       dbg ("%s - sending setup", __func__);
                        keyspan_usa67_send_setup(serial, port,
                                                p_priv->resend_cont - 1);
                        break;
@@ -1183,10 +1183,11 @@ static int keyspan_write_room (struct usb_serial_port *port)
        int                             data_len;
        struct urb                      *this_urb;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
        p_priv = usb_get_serial_port_data(port);
        d_details = p_priv->device_details;
 
+       /* FIXME: locking */
        if (d_details->msg_format == msg_usa90)
                data_len = 64;
        else
@@ -1203,13 +1204,13 @@ static int keyspan_write_room (struct usb_serial_port *port)
                        if (this_urb->status != -EINPROGRESS)
                                return (data_len);
        }
-       return (0);
+       return 0;
 }
 
 
 static int keyspan_chars_in_buffer (struct usb_serial_port *port)
 {
-       return (0);
+       return 0;
 }
 
 
@@ -1228,7 +1229,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
        p_priv = usb_get_serial_port_data(port);
        d_details = p_priv->device_details;
 
-       dbg("%s - port%d.", __FUNCTION__, port->number);
+       dbg("%s - port%d.", __func__, port->number);
 
        /* Set some sane defaults */
        p_priv->rts_state = 1;
@@ -1253,7 +1254,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
                usb_clear_halt(urb->dev, urb->pipe);
 
                if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
-                       dbg("%s - submit urb %d failed (%d)", __FUNCTION__, i, err);
+                       dbg("%s - submit urb %d failed (%d)", __func__, i, err);
                }
        }
 
@@ -1289,7 +1290,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
        //mdelay(100);
        //keyspan_set_termios(port, NULL);
 
-       return (0);
+       return 0;
 }
 
 static inline void stop_urb(struct urb *urb)
@@ -1305,7 +1306,7 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp)
        struct keyspan_serial_private   *s_priv;
        struct keyspan_port_private     *p_priv;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
        s_priv = usb_get_serial_data(serial);
        p_priv = usb_get_serial_port_data(port);
        
@@ -1320,7 +1321,7 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp)
        }
 
        /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
-               dbg("%s - urb in progress", __FUNCTION__);
+               dbg("%s - urb in progress", __func__);
        }*/
 
        p_priv->out_flip = 0;
@@ -1484,10 +1485,10 @@ static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint,
        if (endpoint == -1)
                return NULL;            /* endpoint not needed */
 
-       dbg ("%s - alloc for endpoint %d.", __FUNCTION__, endpoint);
+       dbg ("%s - alloc for endpoint %d.", __func__, endpoint);
        urb = usb_alloc_urb(0, GFP_KERNEL);             /* No ISO */
        if (urb == NULL) {
-               dbg ("%s - alloc for endpoint %d failed.", __FUNCTION__, endpoint);
+               dbg ("%s - alloc for endpoint %d failed.", __func__, endpoint);
                return NULL;
        }
 
@@ -1588,7 +1589,7 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
        struct callbacks                *cback;
        int                             endp;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        s_priv = usb_get_serial_data(serial);
        d_details = s_priv->device_details;
@@ -1662,7 +1663,7 @@ static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
                div,    /* divisor */   
                cnt;    /* inverse of divisor (programmed into 8051) */
                
-       dbg ("%s - %d.", __FUNCTION__, baud_rate);
+       dbg ("%s - %d.", __func__, baud_rate);
 
                /* prevent divide by zero...  */
        if( (b16 = (baud_rate * 16L)) == 0) {
@@ -1695,7 +1696,7 @@ static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
                *rate_hi = (u8) ((cnt >> 8) & 0xff);
        }
        if (rate_low && rate_hi) {
-               dbg ("%s - %d %02x %02x.", __FUNCTION__, baud_rate, *rate_hi, *rate_low);
+               dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low);
        }
        
        return (KEYSPAN_BAUD_RATE_OK);
@@ -1708,7 +1709,7 @@ static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
        u32     b16,    /* baud rate times 16 (actual rate used internally) */
                        div;    /* divisor */   
                
-       dbg ("%s - %d.", __FUNCTION__, baud_rate);
+       dbg ("%s - %d.", __func__, baud_rate);
 
                /* prevent divide by zero...  */
        if( (b16 = (baud_rate * 16L)) == 0) 
@@ -1731,7 +1732,7 @@ static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
                *rate_hi = (u8) ((div >> 8) & 0xff);
        
        if (rate_low && rate_hi) 
-               dbg ("%s - %d %02x %02x.", __FUNCTION__, baud_rate, *rate_hi, *rate_low);
+               dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low);
        
        return (KEYSPAN_BAUD_RATE_OK);
 }
@@ -1748,7 +1749,7 @@ static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
        u8      best_prescaler;
        int     i;
 
-       dbg ("%s - %d.", __FUNCTION__, baud_rate);
+       dbg ("%s - %d.", __func__, baud_rate);
 
                /* prevent divide by zero */
        if( (b16 = baud_rate * 16L) == 0) {
@@ -1796,7 +1797,7 @@ static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
        }
        if (prescaler) {
                *prescaler = best_prescaler;
-               /*  dbg("%s - %d %d", __FUNCTION__, *prescaler, div); */
+               /*  dbg("%s - %d %d", __func__, *prescaler, div); */
        }
        return (KEYSPAN_BAUD_RATE_OK);
 }
@@ -1809,7 +1810,7 @@ static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
                div,    /* divisor */   
                cnt;    /* inverse of divisor (programmed into 8051) */
 
-       dbg ("%s - %d.", __FUNCTION__, baud_rate);
+       dbg ("%s - %d.", __func__, baud_rate);
 
                /* prevent divide by zero */
        if ((b16 = baud_rate * 16L) == 0)
@@ -1848,7 +1849,7 @@ static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
        if (rate_hi) {
                *rate_hi = (u8) ((cnt >> 8) & 0xff);
        }
-       dbg ("%s - %d OK.", __FUNCTION__, baud_rate);
+       dbg ("%s - %d OK.", __func__, baud_rate);
        return (KEYSPAN_BAUD_RATE_OK);
 }
 
@@ -1864,7 +1865,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
        struct urb                              *this_urb;
        int                                     device_port, err;
 
-       dbg ("%s reset=%d", __FUNCTION__, reset_port); 
+       dbg ("%s reset=%d", __func__, reset_port);
 
        s_priv = usb_get_serial_data(serial);
        p_priv = usb_get_serial_port_data(port);
@@ -1874,11 +1875,11 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
        outcont_urb = d_details->outcont_endpoints[port->number];
        this_urb = p_priv->outcont_urb;
 
-       dbg("%s - endpoint %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe));
+       dbg("%s - endpoint %d", __func__, usb_pipeendpoint(this_urb->pipe));
 
                /* Make sure we have an urb then send the message */
        if (this_urb == NULL) {
-               dbg("%s - oops no urb.", __FUNCTION__);
+               dbg("%s - oops no urb.", __func__);
                return -1;
        }
 
@@ -1887,7 +1888,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
        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__); */
+               /*  dbg ("%s - already writing", __func__); */
                mdelay(5);
                return(-1);
        }
@@ -1901,7 +1902,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
                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__,
+                       dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
                            p_priv->baud);
                        msg.baudLo = 0;
                        msg.baudHi = 125;       /* Values for 9600 baud */
@@ -1996,17 +1997,17 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
 
        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);
+               dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
        }
 #if 0
        else {
-               dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __FUNCTION__
+               dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__
                    outcont_urb, this_urb->transfer_buffer_length,
                    usb_pipeendpoint(this_urb->pipe));
        }
 #endif
 
-       return (0);
+       return 0;
 }
 
 static int keyspan_usa28_send_setup(struct usb_serial *serial,
@@ -2020,7 +2021,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
        struct urb                              *this_urb;
        int                                     device_port, err;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        s_priv = usb_get_serial_data(serial);
        p_priv = usb_get_serial_port_data(port);
@@ -2029,7 +2030,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
 
        /* only do something if we have a bulk out endpoint */
        if ((this_urb = p_priv->outcont_urb) == NULL) {
-               dbg("%s - oops no urb.", __FUNCTION__);
+               dbg("%s - oops no urb.", __func__);
                return -1;
        }
 
@@ -2038,7 +2039,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
        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__);
+               dbg ("%s already writing", __func__);
                mdelay(5);
                return(-1);
        }
@@ -2048,7 +2049,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
        msg.setBaudRate = 1;
        if (d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
                &msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
-               dbg("%s - Invalid baud rate requested %d.", __FUNCTION__, p_priv->baud);
+               dbg("%s - Invalid baud rate requested %d.", __func__, p_priv->baud);
                msg.baudLo = 0xff;
                msg.baudHi = 0xb2;      /* Values for 9600 baud */
        }
@@ -2122,16 +2123,16 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
 
        this_urb->dev = serial->dev;
        if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
-               dbg("%s - usb_submit_urb(setup) failed", __FUNCTION__);
+               dbg("%s - usb_submit_urb(setup) failed", __func__);
        }
 #if 0
        else {
-               dbg("%s - usb_submit_urb(setup) OK %d bytes", __FUNCTION__,
+               dbg("%s - usb_submit_urb(setup) OK %d bytes", __func__,
                    this_urb->transfer_buffer_length);
        }
 #endif
 
-       return (0);
+       return 0;
 }
 
 static int keyspan_usa49_send_setup(struct usb_serial *serial,
@@ -2146,7 +2147,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
        struct urb                              *this_urb;
        int                                     err, device_port;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        s_priv = usb_get_serial_data(serial);
        p_priv = usb_get_serial_port_data(port);
@@ -2157,11 +2158,11 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
        /* 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);
+       dbg("%s - endpoint %d port %d (%d)",__func__, usb_pipeendpoint(this_urb->pipe), port->number, device_port);
 
                /* 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);
+               dbg("%s - oops no urb for port %d.", __func__, port->number);
                return -1;
        }
 
@@ -2171,7 +2172,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
                p_priv->resend_cont = reset_port + 1;
 
        if (this_urb->status == -EINPROGRESS) {
-               /*  dbg ("%s - already writing", __FUNCTION__); */
+               /*  dbg ("%s - already writing", __func__); */
                mdelay(5);
                return(-1);
        }
@@ -2188,7 +2189,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
                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__,
+                       dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
                            p_priv->baud);
                        msg.baudLo = 0;
                        msg.baudHi = 125;       /* Values for 9600 baud */
@@ -2307,17 +2308,17 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
                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);
+               dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
        }
 #if 0
        else {
-               dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __FUNCTION__,
+               dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__,
                           outcont_urb, this_urb->transfer_buffer_length,
                           usb_pipeendpoint(this_urb->pipe));
        }
 #endif
 
-       return (0);
+       return 0;
 }
 
 static int keyspan_usa90_send_setup(struct usb_serial *serial,
@@ -2332,7 +2333,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
        int                                     err;
        u8                                              prescaler;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        s_priv = usb_get_serial_data(serial);
        p_priv = usb_get_serial_port_data(port);
@@ -2340,7 +2341,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
 
        /* only do something if we have a bulk out endpoint */
        if ((this_urb = p_priv->outcont_urb) == NULL) {
-               dbg("%s - oops no urb.", __FUNCTION__);
+               dbg("%s - oops no urb.", __func__);
                return -1;
        }
 
@@ -2349,7 +2350,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
        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__);
+               dbg ("%s already writing", __func__);
                mdelay(5);
                return(-1);
        }
@@ -2363,7 +2364,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
                if (d_details->calculate_baud_rate
                    (p_priv->baud, d_details->baudclk, &msg.baudHi,
                     &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE ) {
-                       dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__,
+                       dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
                            p_priv->baud);
                        p_priv->baud = 9600;
                        d_details->calculate_baud_rate (p_priv->baud, d_details->baudclk, 
@@ -2453,9 +2454,9 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
 
        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);
+               dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
        }
-       return (0);
+       return 0;
 }
 
 static int keyspan_usa67_send_setup(struct usb_serial *serial,
@@ -2469,7 +2470,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
        struct urb                              *this_urb;
        int                                     err, device_port;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        s_priv = usb_get_serial_data(serial);
        p_priv = usb_get_serial_port_data(port);
@@ -2482,7 +2483,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
 
        /* Make sure we have an urb then send the message */
        if (this_urb == NULL) {
-               dbg("%s - oops no urb for port %d.", __FUNCTION__,
+               dbg("%s - oops no urb for port %d.", __func__,
                        port->number);
                return -1;
        }
@@ -2492,7 +2493,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
        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__); */
+               /*  dbg ("%s - already writing", __func__); */
                mdelay(5);
                return(-1);
        }
@@ -2508,7 +2509,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
                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__,
+                       dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
                            p_priv->baud);
                        msg.baudLo = 0;
                        msg.baudHi = 125;       /* Values for 9600 baud */
@@ -2601,9 +2602,9 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
 
        err = usb_submit_urb(this_urb, GFP_ATOMIC);
        if (err != 0)
-               dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__,
+               dbg("%s - usb_submit_urb(setup) failed (%d)", __func__,
                                err);
-       return (0);
+       return 0;
 }
 
 static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
@@ -2612,7 +2613,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
        struct keyspan_serial_private *s_priv;
        const struct keyspan_device_details *d_details;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        s_priv = usb_get_serial_data(serial);
        d_details = s_priv->device_details;
@@ -2647,20 +2648,20 @@ static int keyspan_startup (struct usb_serial *serial)
        struct keyspan_port_private     *p_priv;
        const struct keyspan_device_details     *d_details;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
                if (d_details->product_id == le16_to_cpu(serial->dev->descriptor.idProduct))
                        break;
        if (d_details == NULL) {
-               dev_err(&serial->dev->dev, "%s - unknown product id %x\n", __FUNCTION__, le16_to_cpu(serial->dev->descriptor.idProduct));
+               dev_err(&serial->dev->dev, "%s - unknown product id %x\n", __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
                return 1;
        }
 
        /* Setup private data for serial driver */
        s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
        if (!s_priv) {
-               dbg("%s - kmalloc for keyspan_serial_private failed.", __FUNCTION__);
+               dbg("%s - kmalloc for keyspan_serial_private failed.", __func__);
                return -ENOMEM;
        }
 
@@ -2672,7 +2673,7 @@ static int keyspan_startup (struct usb_serial *serial)
                port = serial->port[i];
                p_priv = kzalloc(sizeof(struct keyspan_port_private), GFP_KERNEL);
                if (!p_priv) {
-                       dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __FUNCTION__, i);
+                       dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __func__, i);
                        return (1);
                }
                p_priv->device_details = d_details;
@@ -2685,18 +2686,18 @@ static int keyspan_startup (struct usb_serial *serial)
                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__,
+                       dbg("%s - submit instat urb failed %d", __func__,
                                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__,
+                       dbg("%s - submit indat urb failed %d", __func__,
                                err);
        }
                        
-       return (0);
+       return 0;
 }
 
 static void keyspan_shutdown (struct usb_serial *serial)
@@ -2706,7 +2707,7 @@ static void keyspan_shutdown (struct usb_serial *serial)
        struct keyspan_serial_private   *s_priv;
        struct keyspan_port_private     *p_priv;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        s_priv = usb_get_serial_data(serial);
 
index 74ce8bca3e668422af542a6b709b3e762bc42418..8d6ed0293bfac1f6900d3a5be86781a523f80298 100644 (file)
@@ -636,10 +636,6 @@ static struct usb_serial_driver keyspan_pre_device = {
        },
        .description            = "Keyspan - (without firmware)",
        .id_table               = keyspan_pre_ids,
-       .num_interrupt_in       = NUM_DONT_CARE,
-       .num_interrupt_out      = NUM_DONT_CARE,
-       .num_bulk_in            = NUM_DONT_CARE,
-       .num_bulk_out           = NUM_DONT_CARE,
        .num_ports              = 1,
        .attach                 = keyspan_fake_startup,
 };
@@ -651,10 +647,6 @@ static struct usb_serial_driver keyspan_1port_device = {
        },
        .description            = "Keyspan 1 port adapter",
        .id_table               = keyspan_1port_ids,
-       .num_interrupt_in       = NUM_DONT_CARE,
-       .num_interrupt_out      = NUM_DONT_CARE,
-       .num_bulk_in            = NUM_DONT_CARE,
-       .num_bulk_out           = NUM_DONT_CARE,
        .num_ports              = 1,
        .open                   = keyspan_open,
        .close                  = keyspan_close,
@@ -679,10 +671,6 @@ static struct usb_serial_driver keyspan_2port_device = {
        },
        .description            = "Keyspan 2 port adapter",
        .id_table               = keyspan_2port_ids,
-       .num_interrupt_in       = NUM_DONT_CARE,
-       .num_interrupt_out      = NUM_DONT_CARE,
-       .num_bulk_in            = NUM_DONT_CARE,
-       .num_bulk_out           = NUM_DONT_CARE,
        .num_ports              = 2,
        .open                   = keyspan_open,
        .close                  = keyspan_close,
@@ -707,10 +695,6 @@ static struct usb_serial_driver keyspan_4port_device = {
        },
        .description            = "Keyspan 4 port adapter",
        .id_table               = keyspan_4port_ids,
-       .num_interrupt_in       = NUM_DONT_CARE,
-       .num_interrupt_out      = NUM_DONT_CARE,
-       .num_bulk_in            = NUM_DONT_CARE,
-       .num_bulk_out           = NUM_DONT_CARE,
        .num_ports              = 4,
        .open                   = keyspan_open,
        .close                  = keyspan_close,
index b1fa5a376e96798fc6871b6a47e93c7bed2378a9..ff54203944ca53ca32d1d40be2939dd2c21c2346 100644 (file)
@@ -208,13 +208,13 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work)
                                 2000);
        if (result < 0)
                dbg("%s - error %d from usb_control_msg", 
-                   __FUNCTION__, result);
+                   __func__, result);
 }
 
 
 static void keyspan_pda_rx_interrupt (struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
                struct tty_struct *tty = port->tty;
        unsigned char *data = urb->transfer_buffer;
        int i;
@@ -232,11 +232,11 @@ static void keyspan_pda_rx_interrupt (struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                goto exit;
        }
 
@@ -274,7 +274,7 @@ exit:
        retval = usb_submit_urb (urb, GFP_ATOMIC);
        if (retval)
                err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, retval);
+                    __func__, retval);
 }
 
 
@@ -358,7 +358,7 @@ static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state
                                value, 0, NULL, 0, 2000);
        if (result < 0)
                dbg("%s - error %d from usb_control_msg", 
-                   __FUNCTION__, result);
+                   __func__, result);
        /* there is something funky about this.. the TCSBRK that 'cu' performs
           ought to translate into a break_ctl(-1),break_ctl(0) pair HZ/4
           seconds apart, but it feels like the break sent isn't as long as it
@@ -608,7 +608,7 @@ exit:
 
 static void keyspan_pda_write_bulk_callback (struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct keyspan_pda_private *priv;
 
        port->write_urb_busy = 0;
@@ -636,14 +636,19 @@ static int keyspan_pda_write_room (struct usb_serial_port *port)
 static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port)
 {
        struct keyspan_pda_private *priv;
+       unsigned long flags;
+       int ret = 0;
 
        priv = usb_get_serial_port_data(port);
 
        /* when throttled, return at least WAKEUP_CHARS to tell select() (via
           n_tty.c:normal_poll() ) that we're not writeable. */
+
+       spin_lock_irqsave(&port->lock, flags);
        if (port->write_urb_busy || priv->tx_throttled)
-               return 256;
-       return 0;
+               ret = 256;
+       spin_unlock_irqrestore(&port->lock, flags);
+       return ret;
 }
 
 
@@ -665,11 +670,11 @@ static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp)
                             1,
                             2000);
        if (rc < 0) {
-               dbg("%s - roomquery failed", __FUNCTION__);
+               dbg("%s - roomquery failed", __func__);
                goto error;
        }
        if (rc == 0) {
-               dbg("%s - roomquery returned 0 bytes", __FUNCTION__);
+               dbg("%s - roomquery returned 0 bytes", __func__);
                rc = -EIO;
                goto error;
        }
@@ -688,7 +693,7 @@ static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp)
        port->interrupt_in_urb->dev = serial->dev;
        rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
        if (rc) {
-               dbg("%s - usb_submit_urb(read int) failed", __FUNCTION__);
+               dbg("%s - usb_submit_urb(read int) failed", __func__);
                goto error;
        }
 
@@ -732,7 +737,7 @@ static int keyspan_pda_fake_startup (struct usb_serial *serial)
                record = &xircom_pgs_firmware[0];
 #endif
        if (record == NULL) {
-               err("%s: unknown vendor, aborting.", __FUNCTION__);
+               err("%s: unknown vendor, aborting.", __func__);
                return -ENODEV;
        }
 
@@ -779,7 +784,7 @@ static int keyspan_pda_startup (struct usb_serial *serial)
 
 static void keyspan_pda_shutdown (struct usb_serial *serial)
 {
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
        
        kfree(usb_get_serial_port_data(serial->port[0]));
 }
@@ -793,9 +798,6 @@ static struct usb_serial_driver keyspan_pda_fake_device = {
        .description =          "Keyspan PDA - (prerenumeration)",
        .usb_driver =           &keyspan_pda_driver,
        .id_table =             id_table_fake,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          NUM_DONT_CARE,
-       .num_bulk_out =         NUM_DONT_CARE,
        .num_ports =            1,
        .attach =               keyspan_pda_fake_startup,
 };
@@ -810,9 +812,6 @@ static struct usb_serial_driver xircom_pgs_fake_device = {
        .description =          "Xircom / Entregra PGS - (prerenumeration)",
        .usb_driver =           &keyspan_pda_driver,
        .id_table =             id_table_fake_xircom,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          NUM_DONT_CARE,
-       .num_bulk_out =         NUM_DONT_CARE,
        .num_ports =            1,
        .attach =               keyspan_pda_fake_startup,
 };
@@ -826,9 +825,6 @@ static struct usb_serial_driver keyspan_pda_device = {
        .description =          "Keyspan PDA",
        .usb_driver =           &keyspan_pda_driver,
        .id_table =             id_table_std,
-       .num_interrupt_in =     1,
-       .num_bulk_in =          0,
-       .num_bulk_out =         1,
        .num_ports =            1,
        .open =                 keyspan_pda_open,
        .close =                keyspan_pda_close,
index 55736df7d2f4ed0232d2c33700d353a47336cafe..b395ac7598883a985e94cf485b22d27cf2fac97e 100644 (file)
@@ -126,9 +126,6 @@ static struct usb_serial_driver kl5kusb105d_device = {
        .description =       "KL5KUSB105D / PalmConnect",
        .usb_driver =        &kl5kusb105d_driver,
        .id_table =          id_table,
-       .num_interrupt_in =  1,
-       .num_bulk_in =       1,
-       .num_bulk_out =      1,
        .num_ports =         1,
        .open =              klsi_105_open,
        .close =             klsi_105_close,
@@ -194,7 +191,7 @@ static int klsi_105_chg_port_settings(struct usb_serial_port *port,
        if (rc < 0)
                err("Change port settings failed (error = %d)", rc);
        info("%s - %d byte block, baudrate %x, databits %d, u1 %d, u2 %d",
-           __FUNCTION__,
+           __func__,
            settings->pktlen,
            settings->baudrate, settings->databits,
            settings->unknown1, settings->unknown2);
@@ -225,7 +222,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
        __u8 status_buf[KLSI_STATUSBUF_LEN] = { -1,-1};
        __u16 status;
 
-       info("%s - sending SIO Poll request", __FUNCTION__);
+       info("%s - sending SIO Poll request", __func__);
         rc = usb_control_msg(port->serial->dev,
                             usb_rcvctrlpipe(port->serial->dev, 0),
                             KL5KUSB105A_SIO_POLL,
@@ -240,7 +237,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
        else {
                status = le16_to_cpu(*(u16 *)status_buf);
 
-               info("%s - read status %x %x", __FUNCTION__,
+               info("%s - read status %x %x", __func__,
                     status_buf[0], status_buf[1]);
 
                *line_state_p = klsi_105_status2linestate(status);
@@ -268,7 +265,7 @@ static int klsi_105_startup (struct usb_serial *serial)
                priv = kmalloc(sizeof(struct klsi_105_private),
                                                   GFP_KERNEL);
                if (!priv) {
-                       dbg("%skmalloc for klsi_105_private failed.", __FUNCTION__);
+                       dbg("%skmalloc for klsi_105_private failed.", __func__);
                        i--;
                        goto err_cleanup;
                }
@@ -298,7 +295,7 @@ static int klsi_105_startup (struct usb_serial *serial)
                        urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE,
                                                        GFP_KERNEL);
                        if (!urb->transfer_buffer) {
-                               err("%s - out of memory for urb buffers.", __FUNCTION__);
+                               err("%s - out of memory for urb buffers.", __func__);
                                goto err_cleanup;
                        }
                }
@@ -328,7 +325,7 @@ static void klsi_105_shutdown (struct usb_serial *serial)
 {
        int i;
        
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /* stop reads and writes on all ports */
        for (i=0; i < serial->num_ports; ++i) {
@@ -373,7 +370,7 @@ static int  klsi_105_open (struct usb_serial_port *port, struct file *filp)
        struct klsi_105_port_settings cfg;
        unsigned long flags;
 
-       dbg("%s port %d", __FUNCTION__, port->number);
+       dbg("%s port %d", __func__, port->number);
 
        /* force low_latency on so that our tty_push actually forces
         * the data through
@@ -419,7 +416,7 @@ static int  klsi_105_open (struct usb_serial_port *port, struct file *filp)
 
        rc = usb_submit_urb(port->read_urb, GFP_KERNEL);
        if (rc) {
-               err("%s - failed submitting read urb, error %d", __FUNCTION__, rc);
+               err("%s - failed submitting read urb, error %d", __func__, rc);
                retval = rc;
                goto exit;
        }
@@ -437,14 +434,14 @@ static int  klsi_105_open (struct usb_serial_port *port, struct file *filp)
                err("Enabling read failed (error = %d)", rc);
                retval = rc;
        } else 
-               dbg("%s - enabled reading", __FUNCTION__);
+               dbg("%s - enabled reading", __func__);
 
        rc = klsi_105_get_line_state(port, &line_state);
        if (rc >= 0) {
                spin_lock_irqsave (&priv->lock, flags);
                priv->line_state = line_state;
                spin_unlock_irqrestore (&priv->lock, flags);
-               dbg("%s - read line state 0x%lx", __FUNCTION__, line_state);
+               dbg("%s - read line state 0x%lx", __func__, line_state);
                retval = 0;
        } else
                retval = rc;
@@ -459,7 +456,7 @@ static void klsi_105_close (struct usb_serial_port *port, struct file *filp)
        struct klsi_105_private *priv = usb_get_serial_port_data(port);
        int rc;
 
-       dbg("%s port %d", __FUNCTION__, port->number);
+       dbg("%s port %d", __func__, port->number);
 
        mutex_lock(&port->serial->disc_mutex);
        if (!port->serial->disconnected) {
@@ -502,7 +499,7 @@ static int klsi_105_write (struct usb_serial_port *port,
        int result, size;
        int bytes_sent=0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        while (count > 0) {
                /* try to find a free urb (write 0 bytes if none) */
@@ -514,21 +511,21 @@ static int klsi_105_write (struct usb_serial_port *port,
                for (i=0; i<NUM_URBS; i++) {
                        if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
                                urb = priv->write_urb_pool[i];
-                               dbg("%s - using pool URB %d", __FUNCTION__, i);
+                               dbg("%s - using pool URB %d", __func__, i);
                                break;
                        }
                }
                spin_unlock_irqrestore (&priv->lock, flags);
 
                if (urb==NULL) {
-                       dbg("%s - no more free urbs", __FUNCTION__);
+                       dbg("%s - no more free urbs", __func__);
                        goto exit;
                }
 
                if (urb->transfer_buffer == NULL) {
                        urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
                        if (urb->transfer_buffer == NULL) {
-                               err("%s - no more kernel memory...", __FUNCTION__);
+                               err("%s - no more kernel memory...", __func__);
                                goto exit;
                        }
                }
@@ -554,7 +551,7 @@ static int klsi_105_write (struct usb_serial_port *port,
                /* send the data out the bulk port */
                result = usb_submit_urb(urb, GFP_ATOMIC);
                if (result) {
-                       err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
+                       err("%s - failed submitting write urb, error %d", __func__, result);
                        goto exit;
                }
                buf += size;
@@ -570,13 +567,13 @@ exit:
 
 static void klsi_105_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);
+       dbg("%s - port %d", __func__, port->number);
 
        if (status) {
-               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
+               dbg("%s - nonzero write bulk status received: %d", __func__,
                    status);
                return;
        }
@@ -603,7 +600,7 @@ static int klsi_105_chars_in_buffer (struct usb_serial_port *port)
 
        spin_unlock_irqrestore (&priv->lock, flags);
 
-       dbg("%s - returns %d", __FUNCTION__, chars);
+       dbg("%s - returns %d", __func__, chars);
        return (chars);
 }
 
@@ -623,7 +620,7 @@ static int klsi_105_write_room (struct usb_serial_port *port)
 
        spin_unlock_irqrestore (&priv->lock, flags);
 
-       dbg("%s - returns %d", __FUNCTION__, room);
+       dbg("%s - returns %d", __func__, room);
        return (room);
 }
 
@@ -631,18 +628,18 @@ static int klsi_105_write_room (struct usb_serial_port *port)
 
 static void klsi_105_read_bulk_callback (struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct klsi_105_private *priv = usb_get_serial_port_data(port);
        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", __func__, port->number);
 
        /* The urb might have been killed. */
        if (status) {
-               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__,
+               dbg("%s - nonzero read bulk status received: %d", __func__,
                    status);
                return;
        }
@@ -652,12 +649,12 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
         */
        if (urb->actual_length == 0) {
                /* empty urbs seem to happen, we ignore them */
-               /* dbg("%s - emtpy URB", __FUNCTION__); */
+               /* dbg("%s - emtpy URB", __func__); */
               ;
        } else if (urb->actual_length <= 2) {
-               dbg("%s - size %d URB not understood", __FUNCTION__,
+               dbg("%s - size %d URB not understood", __func__,
                    urb->actual_length);
-               usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+               usb_serial_debug_data(debug, &port->dev, __func__,
                                      urb->actual_length, data);
        } else {
                int bytes_sent = ((__u8 *) data)[0] +
@@ -669,12 +666,12 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
                 * intermixed tty_flip_buffer_push()s
                 * FIXME
                 */ 
-               usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+               usb_serial_debug_data(debug, &port->dev, __func__,
                                      urb->actual_length, data);
 
                if (bytes_sent + 2 > urb->actual_length) {
                        dbg("%s - trying to read more data than available"
-                           " (%d vs. %d)", __FUNCTION__,
+                           " (%d vs. %d)", __func__,
                            bytes_sent+2, urb->actual_length);
                        /* cap at implied limit */
                        bytes_sent = urb->actual_length - 2;
@@ -697,7 +694,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
                      port);
        rc = usb_submit_urb(port->read_urb, GFP_ATOMIC);
        if (rc)
-               err("%s - failed resubmitting read urb, error %d", __FUNCTION__, rc);
+               err("%s - failed resubmitting read urb, error %d", __func__, rc);
 } /* klsi_105_read_bulk_callback */
 
 
@@ -705,12 +702,14 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
                                  struct ktermios *old_termios)
 {
        struct klsi_105_private *priv = usb_get_serial_port_data(port);
-       unsigned int iflag = port->tty->termios->c_iflag;
+       struct tty_struct *tty = port->tty;
+       unsigned int iflag = tty->termios->c_iflag;
        unsigned int old_iflag = old_termios->c_iflag;
-       unsigned int cflag = port->tty->termios->c_cflag;
+       unsigned int cflag = tty->termios->c_cflag;
        unsigned int old_cflag = old_termios->c_cflag;
        struct klsi_105_port_settings cfg;
        unsigned long flags;
+       speed_t baud;
        
        /* lock while we are modifying the settings */
        spin_lock_irqsave (&priv->lock, flags);
@@ -718,10 +717,12 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
        /*
         * Update baud rate
         */
+       baud = tty_get_baud_rate(tty);
+
        if( (cflag & CBAUD) != (old_cflag & CBAUD) ) {
                /* reassert DTR and (maybe) RTS on transition from B0 */
                if( (old_cflag & CBAUD) == B0 ) {
-                       dbg("%s: baud was B0", __FUNCTION__);
+                       dbg("%s: baud was B0", __func__);
 #if 0
                        priv->control_state |= TIOCM_DTR;
                        /* don't set RTS if using hardware flow control */
@@ -731,8 +732,8 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
                        mct_u232_set_modem_ctrl(serial, priv->control_state);
 #endif
                }
-               
-               switch(tty_get_baud_rate(port->tty)) {
+       }
+       switch(baud) {
                case 0: /* handled below */
                        break;
                case 1200:
@@ -760,35 +761,36 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
                        priv->cfg.baudrate = kl5kusb105a_sio_b115200;
                        break;
                default:
-                       err("KLSI USB->Serial converter:"
+                       dbg("KLSI USB->Serial converter:"
                            " unsupported baudrate request, using default"
                            " of 9600");
                        priv->cfg.baudrate = kl5kusb105a_sio_b9600;
+                       baud = 9600;
                        break;
-               }
-               if ((cflag & CBAUD) == B0 ) {
-                       dbg("%s: baud is B0", __FUNCTION__);
-                       /* Drop RTS and DTR */
-                       /* maybe this should be simulated by sending read
-                        * disable and read enable messages?
-                        */
-                       ;
+       }
+       if ((cflag & CBAUD) == B0 ) {
+               dbg("%s: baud is B0", __func__);
+               /* Drop RTS and DTR */
+               /* maybe this should be simulated by sending read
+                * disable and read enable messages?
+                */
+               ;
 #if 0
-                       priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
-                       mct_u232_set_modem_ctrl(serial, priv->control_state);
+               priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+                       mct_u232_set_modem_ctrl(serial, priv->control_state);
 #endif
-               }
        }
+       tty_encode_baud_rate(tty, baud, baud);
 
        if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
                /* set the number of data bits */
                switch (cflag & CSIZE) {
                case CS5:
-                       dbg("%s - 5 bits/byte not supported", __FUNCTION__);
+                       dbg("%s - 5 bits/byte not supported", __func__);
                        spin_unlock_irqrestore (&priv->lock, flags);
                        return ;
                case CS6:
-                       dbg("%s - 6 bits/byte not supported", __FUNCTION__);
+                       dbg("%s - 6 bits/byte not supported", __func__);
                        spin_unlock_irqrestore (&priv->lock, flags);
                        return ;
                case CS7:
@@ -810,6 +812,8 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
        if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
            || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {
                
+               /* Not currently supported */
+               tty->termios->c_cflag &= ~(PARENB|PARODD|CSTOPB);
 #if 0
                priv->last_lcr = 0;
 
@@ -837,6 +841,8 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
            || (iflag & IXON) != (old_iflag & IXON)
            ||  (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) {
                
+               /* Not currently supported */
+               tty->termios->c_cflag &= ~CRTSCTS;
                /* Drop DTR/RTS if no flow control otherwise assert */
 #if 0
                if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) )
@@ -862,7 +868,7 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
        struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
        unsigned char lcr = priv->last_lcr;
 
-       dbg("%sstate=%d", __FUNCTION__, break_state);
+       dbg("%sstate=%d", __func__, break_state);
 
        if (break_state)
                lcr |= MCT_U232_SET_BREAK;
@@ -877,7 +883,7 @@ static int klsi_105_tiocmget (struct usb_serial_port *port, struct file *file)
        unsigned long flags;
        int rc;
        unsigned long line_state;
-       dbg("%s - request, just guessing", __FUNCTION__);
+       dbg("%s - request, just guessing", __func__);
 
        rc = klsi_105_get_line_state(port, &line_state);
        if (rc < 0) {
@@ -889,7 +895,7 @@ static int klsi_105_tiocmget (struct usb_serial_port *port, struct file *file)
        spin_lock_irqsave (&priv->lock, flags);
        priv->line_state = line_state;
        spin_unlock_irqrestore (&priv->lock, flags);
-       dbg("%s - read line state 0x%lx", __FUNCTION__, line_state);
+       dbg("%s - read line state 0x%lx", __func__, line_state);
        return (int)line_state;
 }
 
@@ -898,7 +904,7 @@ static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
 {
        int retval = -EINVAL;
        
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
 /* if this ever gets implemented, it should be done something like this:
        struct usb_serial *serial = port->serial;
@@ -924,7 +930,7 @@ static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
 
 static void klsi_105_throttle (struct usb_serial_port *port)
 {
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
        usb_kill_urb(port->read_urb);
 }
 
@@ -932,12 +938,12 @@ static void klsi_105_unthrottle (struct usb_serial_port *port)
 {
        int result;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        port->read_urb->dev = port->serial->dev;
        result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
        if (result)
-               err("%s - failed submitting read urb, error %d", __FUNCTION__,
+               err("%s - failed submitting read urb, error %d", __func__,
                    result);
 }
 
index 17b3baead4adec5acf81f4e9955d1c97f3bc59f0..693f00da7c038b0072d360b031479c0f1a30bea5 100644 (file)
@@ -113,10 +113,6 @@ static struct usb_serial_driver kobil_device = {
        .description =          "KOBIL USB smart card terminal",
        .usb_driver =           &kobil_driver,
        .id_table =             id_table,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_interrupt_out =    NUM_DONT_CARE,
-       .num_bulk_in =          0,
-       .num_bulk_out =         0,
        .num_ports =            1,
        .attach =               kobil_startup,
        .shutdown =             kobil_shutdown,
@@ -139,7 +135,6 @@ struct kobil_private {
        int filled;  // index of the last char in buf
        int cur_pos; // index of the next char to send in buf
        __u16 device_type;
-       int line_state;
 };
 
 
@@ -161,7 +156,6 @@ static int kobil_startup (struct usb_serial *serial)
        priv->filled = 0;
        priv->cur_pos = 0;
        priv->device_type = le16_to_cpu(serial->dev->descriptor.idProduct);
-       priv->line_state = 0;
 
        switch (priv->device_type){
        case KOBIL_ADAPTER_B_PRODUCT_ID:
@@ -189,11 +183,11 @@ static int kobil_startup (struct usb_serial *serial)
        for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
                endpoint = &altsetting->endpoint[i];
                if (usb_endpoint_is_int_out(&endpoint->desc)) {
-                       dbg("%s Found interrupt out endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress);
+                       dbg("%s Found interrupt out endpoint. Address: %d", __func__, endpoint->desc.bEndpointAddress);
                        priv->write_int_endpoint_address = endpoint->desc.bEndpointAddress;
                }
                if (usb_endpoint_is_int_in(&endpoint->desc)) {
-                       dbg("%s Found interrupt in  endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress);
+                       dbg("%s Found interrupt in  endpoint. Address: %d", __func__, endpoint->desc.bEndpointAddress);
                        priv->read_int_endpoint_address = endpoint->desc.bEndpointAddress;
                }
        }
@@ -204,7 +198,7 @@ static int kobil_startup (struct usb_serial *serial)
 static void kobil_shutdown (struct usb_serial *serial)
 {
        int i;
-       dbg("%s - port %d", __FUNCTION__, serial->port[0]->number);
+       dbg("%s - port %d", __func__, serial->port[0]->number);
 
        for (i=0; i < serial->num_ports; ++i) {
                while (serial->port[i]->open_count > 0) {
@@ -224,9 +218,8 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
        int transfer_buffer_length = 8;
        int write_urb_transfer_buffer_length = 8;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
        priv = usb_get_serial_port_data(port);
-       priv->line_state = 0;
 
        // someone sets the dev to 0 if the close method has been called
        port->interrupt_in_urb->dev = port->serial->dev;
@@ -252,10 +245,10 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
        
        // allocate write_urb
        if (!port->write_urb) { 
-               dbg("%s - port %d  Allocating port->write_urb", __FUNCTION__, port->number);
+               dbg("%s - port %d  Allocating port->write_urb", __func__, port->number);
                port->write_urb = usb_alloc_urb(0, GFP_KERNEL);  
                if (!port->write_urb) {
-                       dbg("%s - port %d usb_alloc_urb failed", __FUNCTION__, port->number);
+                       dbg("%s - port %d usb_alloc_urb failed", __func__, port->number);
                        kfree(transfer_buffer);
                        return -ENOMEM;
                }
@@ -281,7 +274,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
                                  transfer_buffer_length,
                                  KOBIL_TIMEOUT
                );
-       dbg("%s - port %d Send get_HW_version URB returns: %i", __FUNCTION__, port->number, result);
+       dbg("%s - port %d Send get_HW_version URB returns: %i", __func__, port->number, result);
        dbg("Harware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] );
        
        // get firmware version
@@ -295,7 +288,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
                                  transfer_buffer_length,
                                  KOBIL_TIMEOUT
                );
-       dbg("%s - port %d Send get_FW_version URB returns: %i", __FUNCTION__, port->number, result);
+       dbg("%s - port %d Send get_FW_version URB returns: %i", __func__, port->number, result);
        dbg("Firmware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] );
 
        if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
@@ -310,7 +303,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
                                          0,
                                          KOBIL_TIMEOUT
                        );
-               dbg("%s - port %d Send set_baudrate URB returns: %i", __FUNCTION__, port->number, result);
+               dbg("%s - port %d Send set_baudrate URB returns: %i", __func__, port->number, result);
                
                // reset all queues
                result = usb_control_msg( port->serial->dev, 
@@ -323,13 +316,13 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
                                          0,
                                          KOBIL_TIMEOUT
                        );
-               dbg("%s - port %d Send reset_all_queues URB returns: %i", __FUNCTION__, port->number, result);
+               dbg("%s - port %d Send reset_all_queues URB returns: %i", __func__, port->number, result);
        }
        if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
            priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
                // start reading (Adapter B 'cause PNP string)
                result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC  ); 
-               dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);
+               dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
        }
 
        kfree(transfer_buffer);
@@ -339,7 +332,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
 
 static void kobil_close (struct usb_serial_port *port, struct file *filp)
 {
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (port->write_urb) {
                usb_kill_urb(port->write_urb);
@@ -359,11 +352,11 @@ static void kobil_read_int_callback(struct urb *urb)
        int status = urb->status;
 //     char *dbg_data;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (status) {
                dbg("%s - port %d Read int status not zero: %d",
-                   __FUNCTION__, port->number, status);
+                   __func__, port->number, status);
                return;
        }
 
@@ -393,7 +386,7 @@ static void kobil_read_int_callback(struct urb *urb)
        port->interrupt_in_urb->dev = port->serial->dev;
 
        result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
-       dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);
+       dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
 }
 
 
@@ -411,21 +404,21 @@ static int kobil_write (struct usb_serial_port *port,
        struct kobil_private * priv;
 
        if (count == 0) {
-               dbg("%s - port %d write request of 0 bytes", __FUNCTION__, port->number);
+               dbg("%s - port %d write request of 0 bytes", __func__, port->number);
                return 0;
        }
 
        priv = usb_get_serial_port_data(port);
 
        if (count > (KOBIL_BUF_LENGTH - priv->filled)) {
-               dbg("%s - port %d Error: write request bigger than buffer size", __FUNCTION__, port->number);
+               dbg("%s - port %d Error: write request bigger than buffer size", __func__, port->number);
                return -ENOMEM;
        }
 
        // Copy data to buffer
        memcpy (priv->buf + priv->filled, buf, count);
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, priv->buf + priv->filled);
+       usb_serial_debug_data(debug, &port->dev, __func__, count, priv->buf + priv->filled);
 
        priv->filled = priv->filled + count;
 
@@ -457,7 +450,7 @@ static int kobil_write (struct usb_serial_port *port,
 
                        priv->cur_pos = priv->cur_pos + length;
                        result = usb_submit_urb( port->write_urb, GFP_NOIO );
-                       dbg("%s - port %d Send write URB returns: %i", __FUNCTION__, port->number, result);
+                       dbg("%s - port %d Send write URB returns: %i", __func__, port->number, result);
                        todo = priv->filled - priv->cur_pos;
 
                        if (todo > 0) {
@@ -478,7 +471,7 @@ static int kobil_write (struct usb_serial_port *port,
                        port->interrupt_in_urb->dev = port->serial->dev;
                        
                        result = usb_submit_urb( port->interrupt_in_urb, GFP_NOIO ); 
-                       dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);
+                       dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
                }
        }
        return count;
@@ -487,7 +480,7 @@ static int kobil_write (struct usb_serial_port *port,
 
 static int kobil_write_room (struct usb_serial_port *port)
 {
-       //dbg("%s - port %d", __FUNCTION__, port->number);
+       //dbg("%s - port %d", __func__, port->number);
        return 8;
 }
 
@@ -522,16 +515,13 @@ static int kobil_tiocmget(struct usb_serial_port *port, struct file *file)
                                  KOBIL_TIMEOUT);
 
        dbg("%s - port %d Send get_status_line_state URB returns: %i. Statusline: %02x", 
-           __FUNCTION__, port->number, result, transfer_buffer[0]);
-
-       if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0) {
-               priv->line_state |= TIOCM_DSR;
-       } else {
-               priv->line_state &= ~TIOCM_DSR; 
-       }
+           __func__, port->number, result, transfer_buffer[0]);
 
+       result = 0;
+       if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0)
+               result = TIOCM_DSR;
        kfree(transfer_buffer);
-       return priv->line_state;
+       return result;
 }
 
 static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
@@ -544,6 +534,7 @@ static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
        unsigned char *transfer_buffer;
        int transfer_buffer_length = 8;
 
+       /* FIXME: locking ? */
        priv = usb_get_serial_port_data(port);
        if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) {
                // This device doesn't support ioctl calls
@@ -567,9 +558,9 @@ static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
 
        if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) {
                if (dtr != 0)
-                       dbg("%s - port %d Setting DTR", __FUNCTION__, port->number);
+                       dbg("%s - port %d Setting DTR", __func__, port->number);
                else
-                       dbg("%s - port %d Clearing DTR", __FUNCTION__, port->number);
+                       dbg("%s - port %d Clearing DTR", __func__, port->number);
                result = usb_control_msg( port->serial->dev, 
                                          usb_rcvctrlpipe(port->serial->dev, 0 ), 
                                          SUSBCRequest_SetStatusLinesOrQueues,
@@ -581,9 +572,9 @@ static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
                                          KOBIL_TIMEOUT);
        } else {
                if (rts != 0)
-                       dbg("%s - port %d Setting RTS", __FUNCTION__, port->number);
+                       dbg("%s - port %d Setting RTS", __func__, port->number);
                else
-                       dbg("%s - port %d Clearing RTS", __FUNCTION__, port->number);
+                       dbg("%s - port %d Clearing RTS", __func__, port->number);
                result = usb_control_msg( port->serial->dev, 
                                          usb_rcvctrlpipe(port->serial->dev, 0 ), 
                                          SUSBCRequest_SetStatusLinesOrQueues,
@@ -594,7 +585,7 @@ static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
                                          0,
                                          KOBIL_TIMEOUT);
        }
-       dbg("%s - port %d Send set_status_line URB returns: %i", __FUNCTION__, port->number, result);
+       dbg("%s - port %d Send set_status_line URB returns: %i", __func__, port->number, result);
        kfree(transfer_buffer);
        return (result < 0) ? result : 0;
 }
@@ -687,7 +678,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file * file, unsigne
                                          KOBIL_TIMEOUT
                        );
                
-               dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __FUNCTION__, port->number, result);
+               dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __func__, port->number, result);
                kfree(transfer_buffer);
                return (result < 0) ? -EFAULT : 0;
        default:
index fc1cea4aba13979ff48ea6fbdd371787fc1cea5e..5fc2cef30e39f76603421616b3e4a06c9cebd586 100644 (file)
@@ -143,9 +143,6 @@ static struct usb_serial_driver mct_u232_device = {
        .description =       "MCT U232",
        .usb_driver =        &mct_u232_driver,
        .id_table =          id_table_combined,
-       .num_interrupt_in =  2,
-       .num_bulk_in =       0,
-       .num_bulk_out =      1,
        .num_ports =         1,
        .open =              mct_u232_open,
        .close =             mct_u232_close,
@@ -402,7 +399,7 @@ static void mct_u232_shutdown (struct usb_serial *serial)
        struct mct_u232_private *priv;
        int i;
        
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        for (i=0; i < serial->num_ports; ++i) {
                /* My special items, the standard routines free my urbs */
@@ -424,7 +421,7 @@ static int  mct_u232_open (struct usb_serial_port *port, struct file *filp)
        unsigned char last_lcr;
        unsigned char last_msr;
 
-       dbg("%s port %d", __FUNCTION__, port->number);
+       dbg("%s port %d", __func__, port->number);
 
        /* Compensate for a hardware bug: although the Sitecom U232-P25
         * device reports a maximum output packet size of 32 bytes,
@@ -489,7 +486,7 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
        unsigned int c_cflag;
        unsigned int control_state;
        struct mct_u232_private *priv = usb_get_serial_port_data(port);
-       dbg("%s port %d", __FUNCTION__, port->number);
+       dbg("%s port %d", __func__, port->number);
 
        if (port->tty) {
                c_cflag = port->tty->termios->c_cflag;
@@ -517,7 +514,7 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
 
 static void mct_u232_read_int_callback (struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct mct_u232_private *priv = usb_get_serial_port_data(port);
        struct usb_serial *serial = port->serial;
        struct tty_struct *tty;
@@ -535,21 +532,21 @@ static void mct_u232_read_int_callback (struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                goto exit;
        }
 
        if (!serial) {
-               dbg("%s - bad serial pointer, exiting", __FUNCTION__);
+               dbg("%s - bad serial pointer, exiting", __func__);
                return;
        }
 
-        dbg("%s - port %d", __FUNCTION__, port->number);
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+        dbg("%s - port %d", __func__, port->number);
+       usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
 
        /*
         * Work-a-round: handle the 'usual' bulk-in pipe here
@@ -606,7 +603,7 @@ exit:
        retval = usb_submit_urb (urb, GFP_ATOMIC);
        if (retval)
                err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, retval);
+                    __func__, retval);
 } /* mct_u232_read_int_callback */
 
 static void mct_u232_set_termios (struct usb_serial_port *port,
@@ -636,7 +633,7 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
 
         /* reassert DTR and RTS on transition from B0 */
        if ((old_cflag & CBAUD) == B0) {
-               dbg("%s: baud was B0", __FUNCTION__);
+               dbg("%s: baud was B0", __func__);
                control_state |= TIOCM_DTR | TIOCM_RTS;
                mct_u232_set_modem_ctrl(serial, control_state);
        }
@@ -644,7 +641,7 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
        mct_u232_set_baud_rate(serial, port, tty_get_baud_rate(port->tty));
 
        if ((cflag & CBAUD) == B0 ) {
-               dbg("%s: baud is B0", __FUNCTION__);
+               dbg("%s: baud is B0", __func__);
                /* Drop RTS and DTR */
                control_state &= ~(TIOCM_DTR | TIOCM_RTS);
                        mct_u232_set_modem_ctrl(serial, control_state);
@@ -699,7 +696,7 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
        unsigned char lcr;
        unsigned long flags;
 
-       dbg("%sstate=%d", __FUNCTION__, break_state);
+       dbg("%sstate=%d", __func__, break_state);
 
        spin_lock_irqsave(&priv->lock, flags);
        lcr = priv->last_lcr;
@@ -718,7 +715,7 @@ static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file)
        unsigned int control_state;
        unsigned long flags;
        
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        spin_lock_irqsave(&priv->lock, flags);
        control_state = priv->control_state;
@@ -735,7 +732,7 @@ static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file,
        unsigned int control_state;
        unsigned long flags;
        
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        spin_lock_irqsave(&priv->lock, flags);
        control_state = priv->control_state;
@@ -757,7 +754,7 @@ static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file,
 static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
                           unsigned int cmd, unsigned long arg)
 {
-       dbg("%scmd=0x%x", __FUNCTION__, cmd);
+       dbg("%scmd=0x%x", __func__, cmd);
 
        /* Based on code from acm.c and others */
        switch (cmd) {
@@ -772,7 +769,7 @@ static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
                return 0;
 
        default:
-               dbg("%s: arg not supported - 0x%04x", __FUNCTION__,cmd);
+               dbg("%s: arg not supported - 0x%04x", __func__,cmd);
                return(-ENOIOCTLCMD);
                break;
        }
@@ -787,7 +784,7 @@ static void mct_u232_throttle (struct usb_serial_port *port)
        struct tty_struct *tty;
 
        tty = port->tty;
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
        priv->rx_flags |= THROTTLED;
@@ -809,7 +806,7 @@ static void mct_u232_unthrottle (struct usb_serial_port *port)
        unsigned int control_state;
        struct tty_struct *tty;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        tty = port->tty;
        spin_lock_irqsave(&priv->lock, flags);
index 40f3a0188807d95c7e69a7a23001133678dbd9d1..50f1fe263338dc5fb736a4c8024ddd1afb4fb765 100644 (file)
@@ -118,11 +118,11 @@ static void mos7720_interrupt_callback(struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__,
+               dbg("%s - urb shutting down with status: %d", __func__,
                    status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__,
+               dbg("%s - nonzero urb status received: %d", __func__,
                    status);
                goto exit;
        }
@@ -183,7 +183,7 @@ exit:
        if (result)
                dev_err(&urb->dev->dev,
                        "%s - Error %d submitting control urb\n",
-                       __FUNCTION__, result);
+                       __func__, result);
        return;
 }
 
@@ -214,7 +214,7 @@ static void mos7720_bulk_in_callback(struct urb *urb)
 
        port = mos7720_port->port;
 
-       dbg("Entering...%s", __FUNCTION__);
+       dbg("Entering...%s", __func__);
 
        data = urb->transfer_buffer;
 
@@ -362,7 +362,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
                urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
                                               GFP_KERNEL);
                if (!urb->transfer_buffer) {
-                       err("%s-out of memory for urb buffers.", __FUNCTION__);
+                       err("%s-out of memory for urb buffers.", __func__);
                        usb_free_urb(mos7720_port->write_urb_pool[j]);
                        mos7720_port->write_urb_pool[j] = NULL;
                        continue;
@@ -479,7 +479,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
                if (response)
                        dev_err(&port->dev,
                                "%s - Error %d submitting control urb\n",
-                               __FUNCTION__, response);
+                               __func__, response);
        }
 
        /* set up our bulk in urb */
@@ -492,7 +492,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
        response = usb_submit_urb(port->read_urb, GFP_KERNEL);
        if (response)
                dev_err(&port->dev,
-                       "%s - Error %d submitting read urb\n", __FUNCTION__, response);
+                       "%s - Error %d submitting read urb\n", __func__, response);
 
        /* initialize our icount structure */
        memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount));
@@ -521,11 +521,11 @@ static int mos7720_chars_in_buffer(struct usb_serial_port *port)
        int chars = 0;
        struct moschip_port *mos7720_port;
 
-       dbg("%s:entering ...........", __FUNCTION__);
+       dbg("%s:entering ...........", __func__);
 
        mos7720_port = usb_get_serial_port_data(port);
        if (mos7720_port == NULL) {
-               dbg("%s:leaving ...........", __FUNCTION__);
+               dbg("%s:leaving ...........", __func__);
                return -ENODEV;
        }
 
@@ -533,7 +533,7 @@ static int mos7720_chars_in_buffer(struct usb_serial_port *port)
                if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status == -EINPROGRESS)
                        chars += URB_TRANSFER_BUFFER_SIZE;
        }
-       dbg("%s - returns %d", __FUNCTION__, chars);
+       dbg("%s - returns %d", __func__, chars);
        return chars;
 }
 
@@ -585,7 +585,7 @@ static void mos7720_close(struct usb_serial_port *port, struct file *filp)
        mutex_unlock(&serial->disc_mutex);
        mos7720_port->open = 0;
 
-       dbg("Leaving %s", __FUNCTION__);
+       dbg("Leaving %s", __func__);
 }
 
 static void mos7720_break(struct usb_serial_port *port, int break_state)
@@ -594,7 +594,7 @@ static void mos7720_break(struct usb_serial_port *port, int break_state)
        struct usb_serial *serial;
        struct moschip_port *mos7720_port;
 
-       dbg("Entering %s", __FUNCTION__);
+       dbg("Entering %s", __func__);
 
        serial = port->serial;
 
@@ -627,20 +627,21 @@ static int mos7720_write_room(struct usb_serial_port *port)
        int room = 0;
        int i;
 
-       dbg("%s:entering ...........", __FUNCTION__);
+       dbg("%s:entering ...........", __func__);
 
        mos7720_port = usb_get_serial_port_data(port);
        if (mos7720_port == NULL) {
-               dbg("%s:leaving ...........", __FUNCTION__);
+               dbg("%s:leaving ...........", __func__);
                return -ENODEV;
        }
 
+       /* FIXME: Locking */
        for (i = 0; i < NUM_URBS; ++i) {
                if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS)
                        room += URB_TRANSFER_BUFFER_SIZE;
        }
 
-       dbg("%s - returns %d", __FUNCTION__, room);
+       dbg("%s - returns %d", __func__, room);
        return room;
 }
 
@@ -657,7 +658,7 @@ static int mos7720_write(struct usb_serial_port *port,
        struct urb    *urb;
        const unsigned char *current_position = data;
 
-       dbg("%s:entering ...........", __FUNCTION__);
+       dbg("%s:entering ...........", __func__);
 
        serial = port->serial;
 
@@ -679,7 +680,7 @@ static int mos7720_write(struct usb_serial_port *port,
        }
 
        if (urb == NULL) {
-               dbg("%s - no more free urbs", __FUNCTION__);
+               dbg("%s - no more free urbs", __func__);
                goto exit;
        }
 
@@ -687,14 +688,14 @@ static int mos7720_write(struct usb_serial_port *port,
                urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
                                               GFP_KERNEL);
                if (urb->transfer_buffer == NULL) {
-                       err("%s no more kernel memory...", __FUNCTION__);
+                       err("%s no more kernel memory...", __func__);
                        goto exit;
                }
        }
        transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE);
 
        memcpy(urb->transfer_buffer, current_position, transfer_size);
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size,
+       usb_serial_debug_data(debug, &port->dev, __func__, transfer_size,
                              urb->transfer_buffer);
 
        /* fill urb with data and submit  */
@@ -708,7 +709,7 @@ static int mos7720_write(struct usb_serial_port *port,
        status = usb_submit_urb(urb,GFP_ATOMIC);
        if (status) {
                err("%s - usb_submit_urb(write bulk) failed with status = %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                bytes_sent = status;
                goto exit;
        }
@@ -724,7 +725,7 @@ static void mos7720_throttle(struct usb_serial_port *port)
        struct tty_struct *tty;
        int status;
 
-       dbg("%s- port %d\n", __FUNCTION__, port->number);
+       dbg("%s- port %d\n", __func__, port->number);
 
        mos7720_port = usb_get_serial_port_data(port);
 
@@ -736,11 +737,11 @@ static void mos7720_throttle(struct usb_serial_port *port)
                return;
        }
 
-       dbg("%s: Entering ..........", __FUNCTION__);
+       dbg("%s: Entering ..........", __func__);
 
        tty = port->tty;
        if (!tty) {
-               dbg("%s - no tty available", __FUNCTION__);
+               dbg("%s - no tty available", __func__);
                return;
        }
 
@@ -773,15 +774,15 @@ static void mos7720_unthrottle(struct usb_serial_port *port)
                return;
 
        if (!mos7720_port->open) {
-               dbg("%s - port not opened", __FUNCTION__);
+               dbg("%s - port not opened", __func__);
                return;
        }
 
-       dbg("%s: Entering ..........", __FUNCTION__);
+       dbg("%s: Entering ..........", __func__);
 
        tty = port->tty;
        if (!tty) {
-               dbg("%s - no tty available", __FUNCTION__);
+               dbg("%s - no tty available", __func__);
                return;
        }
 
@@ -922,7 +923,7 @@ static int calc_baud_rate_divisor(int baudrate, int *divisor)
        __u16 round;
 
 
-       dbg("%s - %d", __FUNCTION__, baudrate);
+       dbg("%s - %d", __func__, baudrate);
 
        for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {
                if (divisor_table[i].baudrate == baudrate) {
@@ -973,15 +974,15 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port,
        port = mos7720_port->port;
        serial = port->serial;
 
-       dbg("%s: Entering ..........", __FUNCTION__);
+       dbg("%s: Entering ..........", __func__);
 
        number = port->number - port->serial->minor;
-       dbg("%s - port = %d, baud = %d", __FUNCTION__, port->number, baudrate);
+       dbg("%s - port = %d, baud = %d", __func__, port->number, baudrate);
 
         /* Calculate the Divisor */
        status = calc_baud_rate_divisor(baudrate, &divisor);
        if (status) {
-               err("%s - bad baud rate", __FUNCTION__);
+               err("%s - bad baud rate", __func__);
                return status;
        }
 
@@ -1034,16 +1035,16 @@ static void change_port_settings(struct moschip_port *mos7720_port,
        serial = port->serial;
        port_number = port->number - port->serial->minor;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (!mos7720_port->open) {
-               dbg("%s - port not opened", __FUNCTION__);
+               dbg("%s - port not opened", __func__);
                return;
        }
 
        tty = mos7720_port->port->tty;
 
-       dbg("%s: Entering ..........", __FUNCTION__);
+       dbg("%s: Entering ..........", __func__);
 
        lData = UART_LCR_WLEN8;
        lStop = 0x00;   /* 1 stop bit */
@@ -1078,14 +1079,14 @@ static void change_port_settings(struct moschip_port *mos7720_port,
        if (cflag & PARENB) {
                if (cflag & PARODD) {
                        lParity = UART_LCR_PARITY;
-                       dbg("%s - parity = odd", __FUNCTION__);
+                       dbg("%s - parity = odd", __func__);
                } else {
                        lParity = (UART_LCR_EPAR | UART_LCR_PARITY);
-                       dbg("%s - parity = even", __FUNCTION__);
+                       dbg("%s - parity = even", __func__);
                }
 
        } else {
-               dbg("%s - parity = none", __FUNCTION__);
+               dbg("%s - parity = none", __func__);
        }
 
        if (cflag & CMSPAR)
@@ -1094,10 +1095,10 @@ static void change_port_settings(struct moschip_port *mos7720_port,
        /* Change the Stop bit */
        if (cflag & CSTOPB) {
                lStop = UART_LCR_STOP;
-               dbg("%s - stop bits = 2", __FUNCTION__);
+               dbg("%s - stop bits = 2", __func__);
        } else {
                lStop = 0x00;
-               dbg("%s - stop bits = 1", __FUNCTION__);
+               dbg("%s - stop bits = 1", __func__);
        }
 
 #define LCR_BITS_MASK          0x03    /* Mask for bits/char field */
@@ -1171,7 +1172,7 @@ static void change_port_settings(struct moschip_port *mos7720_port,
                return;
        }
 
-       dbg("%s - baud rate = %d", __FUNCTION__, baud);
+       dbg("%s - baud rate = %d", __func__, baud);
        status = send_cmd_write_baud_rate(mos7720_port, baud);
        /* FIXME: needs to write actual resulting baud back not just
           blindly do so */
@@ -1217,7 +1218,7 @@ static void mos7720_set_termios(struct usb_serial_port *port,
 
 
        if (!mos7720_port->open) {
-               dbg("%s - port not opened", __FUNCTION__);
+               dbg("%s - port not opened", __func__);
                return;
        }
 
@@ -1225,15 +1226,15 @@ static void mos7720_set_termios(struct usb_serial_port *port,
 
        cflag = tty->termios->c_cflag;
 
-       dbg("%s - cflag %08x iflag %08x", __FUNCTION__,
+       dbg("%s - cflag %08x iflag %08x", __func__,
            tty->termios->c_cflag,
            RELEVANT_IFLAG(tty->termios->c_iflag));
 
-       dbg("%s - old cflag %08x old iflag %08x", __FUNCTION__,
+       dbg("%s - old cflag %08x old iflag %08x", __func__,
            old_termios->c_cflag,
            RELEVANT_IFLAG(old_termios->c_iflag));
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /* change the port settings to the new ones specified */
        change_port_settings(mos7720_port, old_termios);
@@ -1271,7 +1272,7 @@ static int get_lsr_info(struct moschip_port *mos7720_port,
 
        count = mos7720_chars_in_buffer(mos7720_port->port);
        if (count == 0) {
-               dbg("%s -- Empty", __FUNCTION__);
+               dbg("%s -- Empty", __func__);
                result = TIOCSER_TEMT;
        }
 
@@ -1296,7 +1297,7 @@ static int get_number_bytes_avail(struct moschip_port *mos7720_port,
 
        result = tty->read_cnt;
 
-       dbg("%s(%d) = %d", __FUNCTION__,  mos7720_port->port->number, result);
+       dbg("%s(%d) = %d", __func__,  mos7720_port->port->number, result);
        if (copy_to_user(value, &result, sizeof(int)))
                return -EFAULT;
 
@@ -1374,7 +1375,7 @@ static int get_modem_info(struct moschip_port *mos7720_port,
                  | ((msr & UART_MSR_DSR)       ? TIOCM_DSR: 0);  /* 0x100 */
 
 
-       dbg("%s -- %x", __FUNCTION__, result);
+       dbg("%s -- %x", __func__, result);
 
        if (copy_to_user(value, &result, sizeof(int)))
                return -EFAULT;
@@ -1418,45 +1419,45 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
        if (mos7720_port == NULL)
                return -ENODEV;
 
-       dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
+       dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
 
        switch (cmd) {
        case TIOCINQ:
                /* return number of bytes available */
-               dbg("%s (%d) TIOCINQ", __FUNCTION__,  port->number);
+               dbg("%s (%d) TIOCINQ", __func__,  port->number);
                return get_number_bytes_avail(mos7720_port,
                                              (unsigned int __user *)arg);
                break;
 
        case TIOCSERGETLSR:
-               dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__,  port->number);
+               dbg("%s (%d) TIOCSERGETLSR", __func__,  port->number);
                return get_lsr_info(mos7720_port, (unsigned int __user *)arg);
                return 0;
 
        case TIOCMBIS:
        case TIOCMBIC:
        case TIOCMSET:
-               dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__,
+               dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __func__,
                    port->number);
                return set_modem_info(mos7720_port, cmd,
                                      (unsigned int __user *)arg);
 
        case TIOCMGET:
-               dbg("%s (%d) TIOCMGET", __FUNCTION__,  port->number);
+               dbg("%s (%d) TIOCMGET", __func__,  port->number);
                return get_modem_info(mos7720_port,
                                      (unsigned int __user *)arg);
 
        case TIOCGSERIAL:
-               dbg("%s (%d) TIOCGSERIAL", __FUNCTION__,  port->number);
+               dbg("%s (%d) TIOCGSERIAL", __func__,  port->number);
                return get_serial_info(mos7720_port,
                                       (struct serial_struct __user *)arg);
 
        case TIOCSSERIAL:
-               dbg("%s (%d) TIOCSSERIAL", __FUNCTION__,  port->number);
+               dbg("%s (%d) TIOCSSERIAL", __func__,  port->number);
                break;
 
        case TIOCMIWAIT:
-               dbg("%s (%d) TIOCMIWAIT", __FUNCTION__,  port->number);
+               dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
                cprev = mos7720_port->icount;
                while (1) {
                        if (signal_pending(current))
@@ -1490,7 +1491,7 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
                icount.brk = cnow.brk;
                icount.buf_overrun = cnow.buf_overrun;
 
-               dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
+               dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
                    port->number, icount.rx, icount.tx );
                if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
                        return -EFAULT;
@@ -1508,7 +1509,7 @@ static int mos7720_startup(struct usb_serial *serial)
        int i;
        char data;
 
-       dbg("%s: Entering ..........", __FUNCTION__);
+       dbg("%s: Entering ..........", __func__);
 
        if (!serial) {
                dbg("Invalid Handler");
@@ -1520,7 +1521,7 @@ static int mos7720_startup(struct usb_serial *serial)
        /* create our private serial structure */
        mos7720_serial = kzalloc(sizeof(struct moschip_serial), GFP_KERNEL);
        if (mos7720_serial == NULL) {
-               err("%s - Out of memory", __FUNCTION__);
+               err("%s - Out of memory", __func__);
                return -ENOMEM;
        }
 
@@ -1533,7 +1534,7 @@ static int mos7720_startup(struct usb_serial *serial)
        for (i = 0; i < serial->num_ports; ++i) {
                mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
                if (mos7720_port == NULL) {
-                       err("%s - Out of memory", __FUNCTION__);
+                       err("%s - Out of memory", __func__);
                        usb_set_serial_data(serial, NULL);
                        kfree(mos7720_serial);
                        return -ENOMEM;
@@ -1596,9 +1597,6 @@ static struct usb_serial_driver moschip7720_2port_driver = {
        .description            = "Moschip 2 port adapter",
        .usb_driver             = &usb_driver,
        .id_table               = moschip_port_id_table,
-       .num_interrupt_in       = 1,
-       .num_bulk_in            = 2,
-       .num_bulk_out           = 2,
        .num_ports              = 2,
        .open                   = mos7720_open,
        .close                  = mos7720_close,
@@ -1620,7 +1618,7 @@ static int __init moschip7720_init(void)
 {
        int retval;
 
-       dbg("%s: Entering ..........", __FUNCTION__);
+       dbg("%s: Entering ..........", __func__);
 
        /* Register with the usb serial */
        retval = usb_serial_register(&moschip7720_2port_driver);
index aeeb9cb209994d5a2f0a17c925509605c84d1184..6bcb82d3911a7baf386c0eda874cf3ea68ab1ba5 100644 (file)
@@ -403,7 +403,7 @@ static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
 {
        struct async_icount *icount;
 
-       dbg("%s - %02x", __FUNCTION__, new_lsr);
+       dbg("%s - %02x", __func__, new_lsr);
 
        if (new_lsr & SERIAL_LSR_BI) {
                //
@@ -449,7 +449,7 @@ static void mos7840_control_callback(struct urb *urb)
        int result = 0;
        int status = urb->status;
 
-       mos7840_port = (struct moschip_port *)urb->context;
+       mos7840_port = urb->context;
 
        switch (status) {
        case 0:
@@ -459,21 +459,21 @@ static void mos7840_control_callback(struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__,
+               dbg("%s - urb shutting down with status: %d", __func__,
                    status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__,
+               dbg("%s - nonzero urb status received: %d", __func__,
                    status);
                goto exit;
        }
 
-       dbg("%s urb buffer size is %d\n", __FUNCTION__, urb->actual_length);
-       dbg("%s mos7840_port->MsrLsr is %d port %d\n", __FUNCTION__,
+       dbg("%s urb buffer size is %d\n", __func__, urb->actual_length);
+       dbg("%s mos7840_port->MsrLsr is %d port %d\n", __func__,
            mos7840_port->MsrLsr, mos7840_port->port_num);
        data = urb->transfer_buffer;
        regval = (__u8) data[0];
-       dbg("%s data is %x\n", __FUNCTION__, regval);
+       dbg("%s data is %x\n", __func__, regval);
        if (mos7840_port->MsrLsr == 0)
                mos7840_handle_new_msr(mos7840_port, regval);
        else if (mos7840_port->MsrLsr == 1)
@@ -487,7 +487,7 @@ exit:
        if (result) {
                dev_err(&urb->dev->dev,
                        "%s - Error %d submitting interrupt urb\n",
-                       __FUNCTION__, result);
+                       __func__, result);
        }
 }
 
@@ -542,11 +542,11 @@ static void mos7840_interrupt_callback(struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__,
+               dbg("%s - urb shutting down with status: %d", __func__,
                    status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__,
+               dbg("%s - nonzero urb status received: %d", __func__,
                    status);
                goto exit;
        }
@@ -554,7 +554,7 @@ static void mos7840_interrupt_callback(struct urb *urb)
        length = urb->actual_length;
        data = urb->transfer_buffer;
 
-       serial = (struct usb_serial *)urb->context;
+       serial = urb->context;
 
        /* Moschip get 5 bytes
         * Byte 1 IIR Port 1 (port.number is 0)
@@ -614,7 +614,7 @@ exit:
        if (result) {
                dev_err(&urb->dev->dev,
                        "%s - Error %d submitting interrupt urb\n",
-                       __FUNCTION__, result);
+                       __func__, result);
        }
 }
 
@@ -685,19 +685,19 @@ static void mos7840_bulk_in_callback(struct urb *urb)
                return;
        }
 
-       mos7840_port = (struct moschip_port *)urb->context;
+       mos7840_port = urb->context;
        if (!mos7840_port) {
                dbg("%s", "NULL mos7840_port pointer \n");
                return;
        }
 
        port = (struct usb_serial_port *)mos7840_port->port;
-       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+       if (mos7840_port_paranoia_check(port, __func__)) {
                dbg("%s", "Port Paranoia failed \n");
                return;
        }
 
-       serial = mos7840_get_usb_serial(port, __FUNCTION__);
+       serial = mos7840_get_usb_serial(port, __func__);
        if (!serial) {
                dbg("%s\n", "Bad serial pointer ");
                return;
@@ -752,7 +752,7 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
        int status = urb->status;
        int i;
 
-       mos7840_port = (struct moschip_port *)urb->context;
+       mos7840_port = urb->context;
        spin_lock(&mos7840_port->pool_lock);
        for (i = 0; i < NUM_URBS; i++) {
                if (urb == mos7840_port->write_urb_pool[i]) {
@@ -767,7 +767,7 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
                return;
        }
 
-       if (mos7840_port_paranoia_check(mos7840_port->port, __FUNCTION__)) {
+       if (mos7840_port_paranoia_check(mos7840_port->port, __func__)) {
                dbg("%s", "Port Paranoia failed \n");
                return;
        }
@@ -815,14 +815,14 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
        struct moschip_port *mos7840_port;
        struct moschip_port *port0;
 
-       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+       if (mos7840_port_paranoia_check(port, __func__)) {
                dbg("%s", "Port Paranoia failed \n");
                return -ENODEV;
        }
 
        serial = port->serial;
 
-       if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
+       if (mos7840_serial_paranoia_check(serial, __func__)) {
                dbg("%s", "Serial Paranoia failed \n");
                return -ENODEV;
        }
@@ -851,7 +851,7 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
                if (!urb->transfer_buffer) {
                        usb_free_urb(urb);
                        mos7840_port->write_urb_pool[j] = NULL;
-                       err("%s-out of memory for urb buffers.", __FUNCTION__);
+                       err("%s-out of memory for urb buffers.", __func__);
                        continue;
                }
        }
@@ -1039,7 +1039,7 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
                                           GFP_KERNEL);
                        if (response) {
                                err("%s - Error %d submitting interrupt urb",
-                                   __FUNCTION__, response);
+                                   __func__, response);
                        }
 
                }
@@ -1072,7 +1072,7 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
            port->bulk_in_endpointAddress);
        response = usb_submit_urb(mos7840_port->read_urb, GFP_KERNEL);
        if (response) {
-               err("%s - Error %d submitting control urb", __FUNCTION__,
+               err("%s - Error %d submitting control urb", __func__,
                    response);
        }
 
@@ -1116,7 +1116,7 @@ static int mos7840_chars_in_buffer(struct usb_serial_port *port)
 
        dbg("%s \n", " mos7840_chars_in_buffer:entering ...........");
 
-       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+       if (mos7840_port_paranoia_check(port, __func__)) {
                dbg("%s", "Invalid port \n");
                return -1;
        }
@@ -1134,7 +1134,7 @@ static int mos7840_chars_in_buffer(struct usb_serial_port *port)
                }
        }
        spin_unlock_irqrestore(&mos7840_port->pool_lock,flags);
-       dbg("%s - returns %d", __FUNCTION__, chars);
+       dbg("%s - returns %d", __func__, chars);
        return chars;
 
 }
@@ -1171,7 +1171,7 @@ static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port)
                /* No activity.. count down section */
                wait--;
                if (wait == 0) {
-                       dbg("%s - TIMEOUT", __FUNCTION__);
+                       dbg("%s - TIMEOUT", __func__);
                        return;
                } else {
                        /* Reset timeout value back to seconds */
@@ -1195,12 +1195,12 @@ static void mos7840_close(struct usb_serial_port *port, struct file *filp)
 
        dbg("%s\n", "mos7840_close:entering...");
 
-       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+       if (mos7840_port_paranoia_check(port, __func__)) {
                dbg("%s", "Port Paranoia failed \n");
                return;
        }
 
-       serial = mos7840_get_usb_serial(port, __FUNCTION__);
+       serial = mos7840_get_usb_serial(port, __func__);
        if (!serial) {
                dbg("%s", "Serial Paranoia failed \n");
                return;
@@ -1314,7 +1314,7 @@ static void mos7840_block_until_chase_response(struct moschip_port
                /* No activity.. count down section */
                wait--;
                if (wait == 0) {
-                       dbg("%s - TIMEOUT", __FUNCTION__);
+                       dbg("%s - TIMEOUT", __func__);
                        return;
                } else {
                        /* Reset timeout value back to seconds */
@@ -1337,12 +1337,12 @@ static void mos7840_break(struct usb_serial_port *port, int break_state)
        dbg("%s \n", "Entering ...........");
        dbg("mos7840_break: Start\n");
 
-       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+       if (mos7840_port_paranoia_check(port, __func__)) {
                dbg("%s", "Port Paranoia failed \n");
                return;
        }
 
-       serial = mos7840_get_usb_serial(port, __FUNCTION__);
+       serial = mos7840_get_usb_serial(port, __func__);
        if (!serial) {
                dbg("%s", "Serial Paranoia failed \n");
                return;
@@ -1392,7 +1392,7 @@ static int mos7840_write_room(struct usb_serial_port *port)
 
        dbg("%s \n", " mos7840_write_room:entering ...........");
 
-       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+       if (mos7840_port_paranoia_check(port, __func__)) {
                dbg("%s", "Invalid port \n");
                dbg("%s \n", " mos7840_write_room:leaving ...........");
                return -1;
@@ -1413,7 +1413,7 @@ static int mos7840_write_room(struct usb_serial_port *port)
        spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
 
        room = (room == 0) ? 0 : room - URB_TRANSFER_BUFFER_SIZE + 1;
-       dbg("%s - returns %d", __FUNCTION__, room);
+       dbg("%s - returns %d", __func__, room);
        return room;
 
 }
@@ -1480,13 +1480,13 @@ static int mos7840_write(struct usb_serial_port *port,
        status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
 #endif
 
-       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+       if (mos7840_port_paranoia_check(port, __func__)) {
                dbg("%s", "Port Paranoia failed \n");
                return -1;
        }
 
        serial = port->serial;
-       if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
+       if (mos7840_serial_paranoia_check(serial, __func__)) {
                dbg("%s", "Serial Paranoia failed \n");
                return -1;
        }
@@ -1512,7 +1512,7 @@ static int mos7840_write(struct usb_serial_port *port,
        spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
 
        if (urb == NULL) {
-               dbg("%s - no more free urbs", __FUNCTION__);
+               dbg("%s - no more free urbs", __func__);
                goto exit;
        }
 
@@ -1521,7 +1521,7 @@ static int mos7840_write(struct usb_serial_port *port,
                    kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
 
                if (urb->transfer_buffer == NULL) {
-                       err("%s no more kernel memory...", __FUNCTION__);
+                       err("%s no more kernel memory...", __func__);
                        goto exit;
                }
        }
@@ -1547,7 +1547,7 @@ static int mos7840_write(struct usb_serial_port *port,
        if (status) {
                mos7840_port->busy[i] = 0;
                err("%s - usb_submit_urb(write bulk) failed with status = %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                bytes_sent = status;
                goto exit;
        }
@@ -1573,7 +1573,7 @@ static void mos7840_throttle(struct usb_serial_port *port)
        struct tty_struct *tty;
        int status;
 
-       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+       if (mos7840_port_paranoia_check(port, __func__)) {
                dbg("%s", "Invalid port \n");
                return;
        }
@@ -1594,7 +1594,7 @@ static void mos7840_throttle(struct usb_serial_port *port)
 
        tty = port->tty;
        if (!tty) {
-               dbg("%s - no tty available", __FUNCTION__);
+               dbg("%s - no tty available", __func__);
                return;
        }
 
@@ -1634,7 +1634,7 @@ static void mos7840_unthrottle(struct usb_serial_port *port)
        int status;
        struct moschip_port *mos7840_port = mos7840_get_port_private(port);
 
-       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+       if (mos7840_port_paranoia_check(port, __func__)) {
                dbg("%s", "Invalid port \n");
                return;
        }
@@ -1643,7 +1643,7 @@ static void mos7840_unthrottle(struct usb_serial_port *port)
                return;
 
        if (!mos7840_port->open) {
-               dbg("%s - port not opened", __FUNCTION__);
+               dbg("%s - port not opened", __func__);
                return;
        }
 
@@ -1651,7 +1651,7 @@ static void mos7840_unthrottle(struct usb_serial_port *port)
 
        tty = port->tty;
        if (!tty) {
-               dbg("%s - no tty available", __FUNCTION__);
+               dbg("%s - no tty available", __func__);
                return;
        }
 
@@ -1688,7 +1688,7 @@ static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file)
        int status = 0;
        mos7840_port = mos7840_get_port_private(port);
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (mos7840_port == NULL)
                return -ENODEV;
@@ -1703,7 +1703,7 @@ static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file)
            | ((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0)
            | ((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0);
 
-       dbg("%s - 0x%04X", __FUNCTION__, result);
+       dbg("%s - 0x%04X", __func__, result);
 
        return result;
 }
@@ -1715,13 +1715,14 @@ static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file,
        unsigned int mcr;
        unsigned int status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        mos7840_port = mos7840_get_port_private(port);
 
        if (mos7840_port == NULL)
                return -ENODEV;
 
+       /* FIXME: What locks the port registers ? */
        mcr = mos7840_port->shadowMCR;
        if (clear & TIOCM_RTS)
                mcr &= ~MCR_RTS;
@@ -1758,7 +1759,7 @@ static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor,
                                          __u16 * clk_sel_val)
 {
 
-       dbg("%s - %d", __FUNCTION__, baudRate);
+       dbg("%s - %d", __func__, baudRate);
 
        if (baudRate <= 115200) {
                *divisor = 115200 / baudRate;
@@ -1841,12 +1842,12 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
                return -1;
 
        port = (struct usb_serial_port *)mos7840_port->port;
-       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+       if (mos7840_port_paranoia_check(port, __func__)) {
                dbg("%s", "Invalid port \n");
                return -1;
        }
 
-       if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {
+       if (mos7840_serial_paranoia_check(port->serial, __func__)) {
                dbg("%s", "Invalid Serial \n");
                return -1;
        }
@@ -1855,7 +1856,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
 
        number = mos7840_port->port->number - mos7840_port->port->serial->minor;
 
-       dbg("%s - port = %d, baud = %d", __FUNCTION__,
+       dbg("%s - port = %d, baud = %d", __func__,
            mos7840_port->port->number, baudRate);
        //reset clk_uart_sel in spregOffset
        if (baudRate > 115200) {
@@ -1915,7 +1916,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
                /* Calculate the Divisor */
 
                if (status) {
-                       err("%s - bad baud rate", __FUNCTION__);
+                       err("%s - bad baud rate", __func__);
                        dbg("%s\n", "bad baud rate");
                        return status;
                }
@@ -1969,22 +1970,22 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
 
        port = (struct usb_serial_port *)mos7840_port->port;
 
-       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+       if (mos7840_port_paranoia_check(port, __func__)) {
                dbg("%s", "Invalid port \n");
                return;
        }
 
-       if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {
+       if (mos7840_serial_paranoia_check(port->serial, __func__)) {
                dbg("%s", "Invalid Serial \n");
                return;
        }
 
        serial = port->serial;
 
-       dbg("%s - port %d", __FUNCTION__, mos7840_port->port->number);
+       dbg("%s - port %d", __func__, mos7840_port->port->number);
 
        if (!mos7840_port->open) {
-               dbg("%s - port not opened", __FUNCTION__);
+               dbg("%s - port not opened", __func__);
                return;
        }
 
@@ -2023,14 +2024,14 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
        if (cflag & PARENB) {
                if (cflag & PARODD) {
                        lParity = LCR_PAR_ODD;
-                       dbg("%s - parity = odd", __FUNCTION__);
+                       dbg("%s - parity = odd", __func__);
                } else {
                        lParity = LCR_PAR_EVEN;
-                       dbg("%s - parity = even", __FUNCTION__);
+                       dbg("%s - parity = even", __func__);
                }
 
        } else {
-               dbg("%s - parity = none", __FUNCTION__);
+               dbg("%s - parity = none", __func__);
        }
 
        if (cflag & CMSPAR) {
@@ -2040,10 +2041,10 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
        /* Change the Stop bit */
        if (cflag & CSTOPB) {
                lStop = LCR_STOP_2;
-               dbg("%s - stop bits = 2", __FUNCTION__);
+               dbg("%s - stop bits = 2", __func__);
        } else {
                lStop = LCR_STOP_1;
-               dbg("%s - stop bits = 1", __FUNCTION__);
+               dbg("%s - stop bits = 1", __func__);
        }
 
        /* Update the LCR with the correct value */
@@ -2100,7 +2101,7 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
                baud = 9600;
        }
 
-       dbg("%s - baud rate = %d", __FUNCTION__, baud);
+       dbg("%s - baud rate = %d", __func__, baud);
        status = mos7840_send_cmd_write_baud_rate(mos7840_port, baud);
 
        /* Enable Interrupts */
@@ -2140,14 +2141,14 @@ static void mos7840_set_termios(struct usb_serial_port *port,
        struct moschip_port *mos7840_port;
        struct tty_struct *tty;
        dbg("mos7840_set_termios: START\n");
-       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+       if (mos7840_port_paranoia_check(port, __func__)) {
                dbg("%s", "Invalid port \n");
                return;
        }
 
        serial = port->serial;
 
-       if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
+       if (mos7840_serial_paranoia_check(serial, __func__)) {
                dbg("%s", "Invalid Serial \n");
                return;
        }
@@ -2160,7 +2161,7 @@ static void mos7840_set_termios(struct usb_serial_port *port,
        tty = port->tty;
 
        if (!mos7840_port->open) {
-               dbg("%s - port not opened", __FUNCTION__);
+               dbg("%s - port not opened", __func__);
                return;
        }
 
@@ -2168,11 +2169,11 @@ static void mos7840_set_termios(struct usb_serial_port *port,
 
        cflag = tty->termios->c_cflag;
 
-       dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
+       dbg("%s - clfag %08x iflag %08x", __func__,
            tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag));
-       dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
+       dbg("%s - old clfag %08x old iflag %08x", __func__,
            old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag));
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /* change the port settings to the new ones specified */
 
@@ -2213,7 +2214,7 @@ static int mos7840_get_lsr_info(struct moschip_port *mos7840_port,
 
        count = mos7840_chars_in_buffer(mos7840_port->port);
        if (count == 0) {
-               dbg("%s -- Empty", __FUNCTION__);
+               dbg("%s -- Empty", __func__);
                result = TIOCSER_TEMT;
        }
 
@@ -2240,7 +2241,7 @@ static int mos7840_set_modem_info(struct moschip_port *mos7840_port,
                return -1;
 
        port = (struct usb_serial_port *)mos7840_port->port;
-       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+       if (mos7840_port_paranoia_check(port, __func__)) {
                dbg("%s", "Invalid port \n");
                return -1;
        }
@@ -2314,7 +2315,7 @@ static int mos7840_get_modem_info(struct moschip_port *mos7840_port,
            |((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0)    /* 0x080 */
            |((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0); /* 0x100 */
 
-       dbg("%s -- %x", __FUNCTION__, result);
+       dbg("%s -- %x", __func__, result);
 
        if (copy_to_user(value, &result, sizeof(int)))
                return -EFAULT;
@@ -2371,7 +2372,7 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
        struct serial_icounter_struct icount;
        int mosret = 0;
 
-       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+       if (mos7840_port_paranoia_check(port, __func__)) {
                dbg("%s", "Invalid port \n");
                return -1;
        }
@@ -2383,39 +2384,39 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
 
        tty = mos7840_port->port->tty;
 
-       dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
+       dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
 
        switch (cmd) {
                /* return number of bytes available */
 
        case TIOCSERGETLSR:
-               dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
+               dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
                return mos7840_get_lsr_info(mos7840_port, argp);
                return 0;
 
        case TIOCMBIS:
        case TIOCMBIC:
        case TIOCMSET:
-               dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__,
+               dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __func__,
                    port->number);
                mosret =
                    mos7840_set_modem_info(mos7840_port, cmd, argp);
                return mosret;
 
        case TIOCMGET:
-               dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number);
+               dbg("%s (%d) TIOCMGET", __func__, port->number);
                return mos7840_get_modem_info(mos7840_port, argp);
 
        case TIOCGSERIAL:
-               dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number);
+               dbg("%s (%d) TIOCGSERIAL", __func__, port->number);
                return mos7840_get_serial_info(mos7840_port, argp);
 
        case TIOCSSERIAL:
-               dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number);
+               dbg("%s (%d) TIOCSSERIAL", __func__, port->number);
                break;
 
        case TIOCMIWAIT:
-               dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);
+               dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
                cprev = mos7840_port->icount;
                while (1) {
                        //interruptible_sleep_on(&mos7840_port->delta_msr_wait);
@@ -2458,7 +2459,7 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
                icount.brk = cnow.brk;
                icount.buf_overrun = cnow.buf_overrun;
 
-               dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
+               dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
                    port->number, icount.rx, icount.tx);
                if (copy_to_user(argp, &icount, sizeof(icount)))
                        return -EFAULT;
@@ -2521,7 +2522,7 @@ static int mos7840_startup(struct usb_serial *serial)
        for (i = 0; i < serial->num_ports; ++i) {
                mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
                if (mos7840_port == NULL) {
-                       err("%s - Out of memory", __FUNCTION__);
+                       err("%s - Out of memory", __func__);
                        status = -ENOMEM;
                        i--; /* don't follow NULL pointer cleaning up */
                        goto error;
@@ -2799,12 +2800,7 @@ static struct usb_serial_driver moschip7840_4port_device = {
        .description = DRIVER_DESC,
        .usb_driver = &io_driver,
        .id_table = moschip_port_id_table,
-       .num_interrupt_in = 1,  //NUM_DONT_CARE,//1,
-#ifdef check
-       .num_bulk_in = 4,
-       .num_bulk_out = 4,
        .num_ports = 4,
-#endif
        .open = mos7840_open,
        .close = mos7840_close,
        .write = mos7840_write,
index 7f337c9aeb5fe9ba13c5c58dd2bf1b3f2c5e4052..43c8894353bff422fbd93ae9a600efeb750f8bd0 100644 (file)
@@ -6,6 +6,10 @@
  *     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.
+ *
+ * TODO:
+ *     Add termios method that uses copy_hw but also kills all echo
+ *     flags as the navman is rx only so cannot echo.
  */
 
 #include <linux/kernel.h>
@@ -49,15 +53,15 @@ 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__, status);
+                   __func__, status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                goto exit;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+       usb_serial_debug_data(debug, &port->dev, __func__,
                              urb->actual_length, data);
 
        tty = port->tty;
@@ -72,29 +76,29 @@ exit:
        if (result)
                dev_err(&urb->dev->dev,
                        "%s - Error %d submitting interrupt urb\n",
-                       __FUNCTION__, result);
+                       __func__, result);
 }
 
 static int navman_open(struct usb_serial_port *port, struct file *filp)
 {
        int result = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (port->interrupt_in_urb) {
-               dbg("%s - adding interrupt input for treo", __FUNCTION__);
+               dbg("%s - adding interrupt input for treo", __func__);
                result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
                if (result)
                        dev_err(&port->dev,
                                "%s - failed submitting interrupt urb, error %d\n",
-                               __FUNCTION__, result);
+                               __func__, result);
        }
        return result;
 }
 
 static void navman_close(struct usb_serial_port *port, struct file *filp)
 {
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        usb_kill_urb(port->interrupt_in_urb);
 }
@@ -102,16 +106,12 @@ static void navman_close(struct usb_serial_port *port, struct file *filp)
 static int navman_write(struct usb_serial_port *port,
                        const unsigned char *buf, int count)
 {
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /*
         * This device can't write any data, only read from the device
-        * so we just silently eat all data sent to us and say it was
-        * successfully sent.
-        * Evil, I know, but do you have a better idea?
         */
-
-       return count;
+       return -EOPNOTSUPP;
 }
 
 static struct usb_serial_driver navman_device = {
@@ -121,9 +121,6 @@ static struct usb_serial_driver navman_device = {
        },
        .id_table =             id_table,
        .usb_driver =           &navman_driver,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          NUM_DONT_CARE,
-       .num_bulk_out =         NUM_DONT_CARE,
        .num_ports =            1,
        .open =                 navman_open,
        .close =                navman_close,
index ee94d9616d82c8ff64869b58b46c56d08e5599aa..7b7422f4947854008500f13cb3deabd2cde0be45 100644 (file)
@@ -95,9 +95,6 @@ static struct usb_serial_driver zyxel_omninet_device = {
        .description =          "ZyXEL - omni.net lcd plus usb",
        .usb_driver =           &omninet_driver,
        .id_table =             id_table,
-       .num_interrupt_in =     1,
-       .num_bulk_in =          1,
-       .num_bulk_out =         2,
        .num_ports =            1,
        .attach =               omninet_attach,
        .open =                 omninet_open,
@@ -153,7 +150,7 @@ static int omninet_attach (struct usb_serial *serial)
 
        od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
        if( !od ) {
-               err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct omninet_data));
+               err("%s- kmalloc(%Zd) failed.", __func__, sizeof(struct omninet_data));
                return -ENOMEM;
        }
        usb_set_serial_port_data(port, od);
@@ -166,7 +163,7 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
        struct usb_serial_port  *wport;
        int                     result = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        wport = serial->port[1];
        wport->tty = port->tty;
@@ -178,7 +175,7 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
                      omninet_read_bulk_callback, port);
        result = usb_submit_urb(port->read_urb, GFP_KERNEL);
        if (result) {
-               err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+               err("%s - failed submitting read urb, error %d", __func__, result);
        }
 
        return result;
@@ -186,7 +183,7 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
 
 static void omninet_close (struct usb_serial_port *port, struct file * filp)
 {
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
        usb_kill_urb(port->read_urb);
 }
 
@@ -197,18 +194,18 @@ static void omninet_close (struct usb_serial_port *port, struct file * filp)
 
 static void omninet_read_bulk_callback (struct urb *urb)
 {
-       struct usb_serial_port  *port   = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port  *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);
+       dbg("%s - port %d", __func__, port->number);
 
        if (status) {
                dbg("%s - nonzero read bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        }
 
@@ -236,7 +233,7 @@ static void omninet_read_bulk_callback (struct urb *urb)
                      omninet_read_bulk_callback, port);
        result = usb_submit_urb(urb, GFP_ATOMIC);
        if (result)
-               err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+               err("%s - failed resubmitting read urb, error %d", __func__, result);
 
        return;
 }
@@ -251,17 +248,17 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
 
        int                     result;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (count == 0) {
-               dbg("%s - write request of 0 bytes", __FUNCTION__);
+               dbg("%s - write request of 0 bytes", __func__);
                return (0);
        }
 
        spin_lock_bh(&wport->lock);
        if (wport->write_urb_busy) {
                spin_unlock_bh(&wport->lock);
-               dbg("%s - already writing", __FUNCTION__);
+               dbg("%s - already writing", __func__);
                return 0;
        }
        wport->write_urb_busy = 1;
@@ -271,7 +268,7 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
 
        memcpy (wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count);
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, wport->write_urb->transfer_buffer);
+       usb_serial_debug_data(debug, &port->dev, __func__, count, wport->write_urb->transfer_buffer);
 
        header->oh_seq  = od->od_outseq++;
        header->oh_len  = count;
@@ -285,7 +282,7 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
        result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
        if (result) {
                wport->write_urb_busy = 0;
-               err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
+               err("%s - failed submitting write urb, error %d", __func__, result);
        } else
                result = count;
 
@@ -298,12 +295,13 @@ static int omninet_write_room (struct usb_serial_port *port)
        struct usb_serial       *serial = port->serial;
        struct usb_serial_port  *wport  = serial->port[1];
 
-       int room = 0; // Default: no room
+       int room = 0; /* Default: no room */
 
+       /* FIXME: no consistent locking for write_urb_busy */
        if (wport->write_urb_busy)
                room = wport->bulk_out_size - OMNINET_HEADERLEN;
 
-       dbg("%s - returns %d", __FUNCTION__, room);
+       dbg("%s - returns %d", __func__, room);
 
        return (room);
 }
@@ -311,15 +309,15 @@ static int omninet_write_room (struct usb_serial_port *port)
 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;
+       struct usb_serial_port  *port   =  urb->context;
        int status = urb->status;
 
-       dbg("%s - port %0x\n", __FUNCTION__, port->number);
+       dbg("%s - port %0x\n", __func__, port->number);
 
        port->write_urb_busy = 0;
        if (status) {
                dbg("%s - nonzero write bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        }
 
@@ -331,7 +329,7 @@ static void omninet_shutdown (struct usb_serial *serial)
 {
        struct usb_serial_port *wport = serial->port[1];
        struct usb_serial_port *port = serial->port[0];
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        usb_kill_urb(wport->write_urb);
        kfree(usb_get_serial_port_data(port));
index d101025a4c637176a0503e5c71a0079700fc7e9a..e4be2d442b1ebbc6ea3bca507e85d4905d4f526f 100644 (file)
@@ -28,7 +28,7 @@
   device features.
 */
 
-#define DRIVER_VERSION "v0.7.1"
+#define DRIVER_VERSION "v0.7.2"
 #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
 #define DRIVER_DESC "USB Driver for GSM modems"
 
@@ -325,9 +325,6 @@ static struct usb_serial_driver option_1port_device = {
        .description       = "GSM modem (1-port)",
        .usb_driver        = &option_driver,
        .id_table          = option_ids,
-       .num_interrupt_in  = NUM_DONT_CARE,
-       .num_bulk_in       = NUM_DONT_CARE,
-       .num_bulk_out      = NUM_DONT_CARE,
        .num_ports         = 1,
        .open              = option_open,
        .close             = option_close,
@@ -411,24 +408,24 @@ module_exit(option_exit);
 
 static void option_rx_throttle(struct usb_serial_port *port)
 {
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 }
 
 static void option_rx_unthrottle(struct usb_serial_port *port)
 {
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 }
 
 static void option_break_ctl(struct usb_serial_port *port, int break_state)
 {
        /* Unfortunately, I don't know how to send a break */
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 }
 
 static void option_set_termios(struct usb_serial_port *port,
                        struct ktermios *old_termios)
 {
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
        /* Doesn't support option setting */
        tty_termios_copy_hw(port->tty->termios, old_termios);
        option_send_setup(port);
@@ -458,6 +455,7 @@ static int option_tiocmset(struct usb_serial_port *port, struct file *file,
 
        portdata = usb_get_serial_port_data(port);
 
+       /* FIXME: what locks portdata fields ? */
        if (set & TIOCM_RTS)
                portdata->rts_state = 1;
        if (set & TIOCM_DTR)
@@ -488,7 +486,7 @@ static int option_write(struct usb_serial_port *port,
 
        portdata = usb_get_serial_port_data(port);
 
-       dbg("%s: write (%d chars)", __FUNCTION__, count);
+       dbg("%s: write (%d chars)", __func__, count);
 
        i = 0;
        left = count;
@@ -509,7 +507,7 @@ static int option_write(struct usb_serial_port *port,
                        dbg("usb_write %p failed (err=%d)",
                                this_urb, this_urb->status);
 
-               dbg("%s: endpoint %d buf %d", __FUNCTION__,
+               dbg("%s: endpoint %d buf %d", __func__,
                        usb_pipeendpoint(this_urb->pipe), i);
 
                /* send the data */
@@ -531,7 +529,7 @@ static int option_write(struct usb_serial_port *port,
        }
 
        count -= left;
-       dbg("%s: wrote (did %d)", __FUNCTION__, count);
+       dbg("%s: wrote (did %d)", __func__, count);
        return count;
 }
 
@@ -544,14 +542,14 @@ static void option_indat_callback(struct urb *urb)
        unsigned char *data = urb->transfer_buffer;
        int status = urb->status;
 
-       dbg("%s: %p", __FUNCTION__, urb);
+       dbg("%s: %p", __func__, urb);
 
        endpoint = usb_pipeendpoint(urb->pipe);
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
 
        if (status) {
                dbg("%s: nonzero status: %d on endpoint %02x.",
-                   __FUNCTION__, status, endpoint);
+                   __func__, status, endpoint);
        } else {
                tty = port->tty;
                if (urb->actual_length) {
@@ -559,7 +557,7 @@ static void option_indat_callback(struct urb *urb)
                        tty_insert_flip_string(tty, data, urb->actual_length);
                        tty_flip_buffer_push(tty);
                } else {
-                       dbg("%s: empty read urb received", __FUNCTION__);
+                       dbg("%s: empty read urb received", __func__);
                }
 
                /* Resubmit urb so we continue receiving */
@@ -567,7 +565,7 @@ static void option_indat_callback(struct urb *urb)
                        err = usb_submit_urb(urb, GFP_ATOMIC);
                        if (err)
                                printk(KERN_ERR "%s: resubmit read urb failed. "
-                                       "(%d)", __FUNCTION__, err);
+                                       "(%d)", __func__, err);
                }
        }
        return;
@@ -579,9 +577,9 @@ static void option_outdat_callback(struct urb *urb)
        struct option_port_private *portdata;
        int i;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
 
        usb_serial_port_softint(port);
 
@@ -599,19 +597,19 @@ 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 usb_serial_port *port =  urb->context;
        struct option_port_private *portdata = usb_get_serial_port_data(port);
        struct usb_serial *serial = port->serial;
 
-       dbg("%s", __FUNCTION__);
-       dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
+       dbg("%s", __func__);
+       dbg("%s: urb %p port %p has data %p", __func__,urb,port,portdata);
 
        if (status == 0) {
                struct usb_ctrlrequest *req_pkt =
                                (struct usb_ctrlrequest *)urb->transfer_buffer;
 
                if (!req_pkt) {
-                       dbg("%s: NULL req_pkt\n", __FUNCTION__);
+                       dbg("%s: NULL req_pkt\n", __func__);
                        return;
                }
                if ((req_pkt->bRequestType == 0xA1) &&
@@ -621,7 +619,7 @@ static void option_instat_callback(struct urb *urb)
                                        urb->transfer_buffer +
                                        sizeof(struct usb_ctrlrequest));
 
-                       dbg("%s: signal x%x", __FUNCTION__, signals);
+                       dbg("%s: signal x%x", __func__, signals);
 
                        old_dcd_state = portdata->dcd_state;
                        portdata->cts_state = 1;
@@ -633,11 +631,11 @@ static void option_instat_callback(struct urb *urb)
                                        old_dcd_state && !portdata->dcd_state)
                                tty_hangup(port->tty);
                } else {
-                       dbg("%s: type %x req %x", __FUNCTION__,
+                       dbg("%s: type %x req %x", __func__,
                                req_pkt->bRequestType,req_pkt->bRequest);
                }
        } else
-               dbg("%s: error %d", __FUNCTION__, status);
+               dbg("%s: error %d", __func__, status);
 
        /* Resubmit urb so we continue receiving IRQ data */
        if (status != -ESHUTDOWN) {
@@ -645,7 +643,7 @@ static void option_instat_callback(struct urb *urb)
                err = usb_submit_urb(urb, GFP_ATOMIC);
                if (err)
                        dbg("%s: resubmit intr urb failed. (%d)",
-                               __FUNCTION__, err);
+                               __func__, err);
        }
 }
 
@@ -658,13 +656,14 @@ static int option_write_room(struct usb_serial_port *port)
 
        portdata = usb_get_serial_port_data(port);
 
+
        for (i=0; i < N_OUT_URB; i++) {
                this_urb = portdata->out_urbs[i];
                if (this_urb && !test_bit(i, &portdata->out_busy))
                        data_len += OUT_BUFLEN;
        }
 
-       dbg("%s: %d", __FUNCTION__, data_len);
+       dbg("%s: %d", __func__, data_len);
        return data_len;
 }
 
@@ -679,10 +678,12 @@ 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];
+               /* FIXME: This locking is insufficient as this_urb may
+                  go unused during the test */
                if (this_urb && test_bit(i, &portdata->out_busy))
                        data_len += this_urb->transfer_buffer_length;
        }
-       dbg("%s: %d", __FUNCTION__, data_len);
+       dbg("%s: %d", __func__, data_len);
        return data_len;
 }
 
@@ -695,7 +696,7 @@ static int option_open(struct usb_serial_port *port, struct file *filp)
 
        portdata = usb_get_serial_port_data(port);
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /* Set some sane defaults */
        portdata->rts_state = 1;
@@ -707,7 +708,7 @@ static int option_open(struct usb_serial_port *port, struct file *filp)
                if (! urb)
                        continue;
                if (urb->dev != serial->dev) {
-                       dbg("%s: dev %p != %p", __FUNCTION__,
+                       dbg("%s: dev %p != %p", __func__,
                                urb->dev, serial->dev);
                        continue;
                }
@@ -721,7 +722,7 @@ static int option_open(struct usb_serial_port *port, struct file *filp)
                err = usb_submit_urb(urb, GFP_KERNEL);
                if (err) {
                        dbg("%s: submit urb %d failed (%d) %d",
-                               __FUNCTION__, i, err,
+                               __func__, i, err,
                                urb->transfer_buffer_length);
                }
        }
@@ -749,7 +750,7 @@ static void option_close(struct usb_serial_port *port, struct file *filp)
        struct usb_serial *serial = port->serial;
        struct option_port_private *portdata;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
        portdata = usb_get_serial_port_data(port);
 
        portdata->rts_state = 0;
@@ -782,7 +783,7 @@ static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
 
        urb = usb_alloc_urb(0, GFP_KERNEL);             /* No ISO */
        if (urb == NULL) {
-               dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint);
+               dbg("%s: alloc for endpoint %d failed.", __func__, endpoint);
                return NULL;
        }
 
@@ -801,7 +802,7 @@ static void option_setup_urbs(struct usb_serial *serial)
        struct usb_serial_port *port;
        struct option_port_private *portdata;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        for (i = 0; i < serial->num_ports; i++) {
                port = serial->port[i];
@@ -823,15 +824,18 @@ static void option_setup_urbs(struct usb_serial *serial)
        }
 }
 
+
+/** send RTS/DTR state to the port.
+ *
+ * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
+ * CDC.
+*/
 static int option_send_setup(struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
        struct option_port_private *portdata;
-
-       dbg("%s", __FUNCTION__);
-
-       if (port->number != 0)
-               return 0;
+       int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+       dbg("%s", __func__);
 
        portdata = usb_get_serial_port_data(port);
 
@@ -844,7 +848,7 @@ static int option_send_setup(struct usb_serial_port *port)
 
                return usb_control_msg(serial->dev,
                                usb_rcvctrlpipe(serial->dev, 0),
-                               0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
+                               0x22,0x21,val,ifNum,NULL,0,USB_CTRL_SET_TIMEOUT);
        }
 
        return 0;
@@ -857,7 +861,7 @@ static int option_startup(struct usb_serial *serial)
        struct option_port_private *portdata;
        u8 *buffer;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /* Now setup per port private data */
        for (i = 0; i < serial->num_ports; i++) {
@@ -865,7 +869,7 @@ static int option_startup(struct usb_serial *serial)
                portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
                if (!portdata) {
                        dbg("%s: kmalloc for option_port_private (%d) failed!.",
-                                       __FUNCTION__, i);
+                                       __func__, i);
                        return (1);
                }
 
@@ -890,7 +894,7 @@ static int option_startup(struct usb_serial *serial)
                err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
                if (err)
                        dbg("%s: submit irq_in urb failed %d",
-                               __FUNCTION__, err);
+                               __func__, err);
        }
 
        option_setup_urbs(serial);
@@ -914,7 +918,7 @@ static void option_shutdown(struct usb_serial *serial)
        struct usb_serial_port *port;
        struct option_port_private *portdata;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /* Stop reading/writing urbs */
        for (i = 0; i < serial->num_ports; ++i) {
index a3847d6c946eac309fe899b8698cdb34bbe29276..d92bb6501c8443d2963054c1472dee893c4565db 100644 (file)
@@ -179,9 +179,6 @@ static struct usb_serial_driver oti6858_device = {
                .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,
@@ -238,10 +235,10 @@ static void setup_line(struct work_struct *work)
        unsigned long flags;
        int result;
 
-       dbg("%s(port = %d)", __FUNCTION__, port->number);
+       dbg("%s(port = %d)", __func__, port->number);
 
        if ((new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
-               dev_err(&port->dev, "%s(): out of memory!\n", __FUNCTION__);
+               dev_err(&port->dev, "%s(): out of memory!\n", __func__);
                /* we will try again */
                schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
                return;
@@ -256,7 +253,7 @@ static void setup_line(struct work_struct *work)
                                100);
 
        if (result != OTI6858_CTRL_PKT_SIZE) {
-               dev_err(&port->dev, "%s(): error reading status\n", __FUNCTION__);
+               dev_err(&port->dev, "%s(): error reading status\n", __func__);
                kfree(new_setup);
                /* we will try again */
                schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
@@ -289,12 +286,12 @@ static void setup_line(struct work_struct *work)
        priv->setup_done = 1;
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       dbg("%s(): submitting interrupt urb", __FUNCTION__);
+       dbg("%s(): submitting interrupt urb", __func__);
        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);
+                               " with error %d\n", __func__, result);
        }
 }
 
@@ -306,7 +303,7 @@ void send_data(struct work_struct *work)
        unsigned long flags;
        unsigned char allow;
 
-       dbg("%s(port = %d)", __FUNCTION__, port->number);
+       dbg("%s(port = %d)", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
        if (priv->flags.write_urb_in_use) {
@@ -334,12 +331,12 @@ void send_data(struct work_struct *work)
        if (count == 0) {
                priv->flags.write_urb_in_use = 0;
 
-               dbg("%s(): submitting interrupt urb", __FUNCTION__);
+               dbg("%s(): submitting interrupt urb", __func__);
                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);
+                               " with error %d\n", __func__, result);
                }
                return;
        }
@@ -353,7 +350,7 @@ void send_data(struct work_struct *work)
        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);
+                              " with error %d\n", __func__, result);
                priv->flags.write_urb_in_use = 0;
        }
 
@@ -404,7 +401,7 @@ static int oti6858_write(struct usb_serial_port *port,
        struct oti6858_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
 
-       dbg("%s(port = %d, count = %d)", __FUNCTION__, port->number, count);
+       dbg("%s(port = %d, count = %d)", __func__, port->number, count);
 
        if (!count)
                return count;
@@ -422,7 +419,7 @@ static int oti6858_write_room(struct usb_serial_port *port)
        int room = 0;
        unsigned long flags;
 
-       dbg("%s(port = %d)", __FUNCTION__, port->number);
+       dbg("%s(port = %d)", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
        room = oti6858_buf_space_avail(priv->buf);
@@ -437,7 +434,7 @@ static int oti6858_chars_in_buffer(struct usb_serial_port *port)
        int chars = 0;
        unsigned long flags;
 
-       dbg("%s(port = %d)", __FUNCTION__, port->number);
+       dbg("%s(port = %d)", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
        chars = oti6858_buf_data_avail(priv->buf);
@@ -456,10 +453,10 @@ static void oti6858_set_termios(struct usb_serial_port *port,
        u16 divisor;
        int br;
 
-       dbg("%s(port = %d)", __FUNCTION__, port->number);
+       dbg("%s(port = %d)", __func__, port->number);
 
        if (!port->tty || !port->tty->termios) {
-               dbg("%s(): no tty structures", __FUNCTION__);
+               dbg("%s(): no tty structures", __func__);
                return;
        }
 
@@ -575,7 +572,7 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
        unsigned long flags;
        int result;
 
-       dbg("%s(port = %d)", __FUNCTION__, port->number);
+       dbg("%s(port = %d)", __func__, port->number);
 
        usb_clear_halt(serial->dev, port->write_urb->pipe);
        usb_clear_halt(serial->dev, port->read_urb->pipe);
@@ -584,7 +581,7 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
                return 0;
 
        if ((buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
-               dev_err(&port->dev, "%s(): out of memory!\n", __FUNCTION__);
+               dev_err(&port->dev, "%s(): out of memory!\n", __func__);
                return -ENOMEM;
        }
 
@@ -613,12 +610,12 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
        spin_unlock_irqrestore(&priv->lock, flags);
        kfree(buf);
 
-       dbg("%s(): submitting interrupt urb", __FUNCTION__);
+       dbg("%s(): submitting interrupt urb", __func__);
        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);
+                              " with error %d\n", __func__, result);
                oti6858_close(port, NULL);
                return -EPROTO;
        }
@@ -637,14 +634,14 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
        long timeout;
        wait_queue_t wait;
 
-       dbg("%s(port = %d)", __FUNCTION__, port->number);
+       dbg("%s(port = %d)", __func__, 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__);
+       dbg("%s(): entering wait loop", __func__);
        for (;;) {
                set_current_state(TASK_INTERRUPTIBLE);
                if (oti6858_buf_data_avail(priv->buf) == 0
@@ -657,7 +654,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
        }
        set_current_state(TASK_RUNNING);
        remove_wait_queue(&port->tty->write_wait, &wait);
-       dbg("%s(): after wait loop", __FUNCTION__);
+       dbg("%s(): after wait loop", __func__);
 
        /* clear out any remaining data in the buffer */
        oti6858_buf_clear(priv->buf);
@@ -678,7 +675,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
        */
                timeout = 2*HZ;
        schedule_timeout_interruptible(timeout);
-       dbg("%s(): after schedule_timeout_interruptible()", __FUNCTION__);
+       dbg("%s(): after schedule_timeout_interruptible()", __func__);
 
        /* cancel scheduled setup */
        cancel_delayed_work(&priv->delayed_setup_work);
@@ -686,7 +683,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
        flush_scheduled_work();
 
        /* shutdown our urbs */
-       dbg("%s(): shutting down urbs", __FUNCTION__);
+       dbg("%s(): shutting down urbs", __func__);
        usb_kill_urb(port->write_urb);
        usb_kill_urb(port->read_urb);
        usb_kill_urb(port->interrupt_in_urb);
@@ -709,7 +706,7 @@ static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
        u8 control;
 
        dbg("%s(port = %d, set = 0x%08x, clear = 0x%08x)",
-                               __FUNCTION__, port->number, set, clear);
+                               __func__, port->number, set, clear);
 
        if (!usb_get_intfdata(port->serial->interface))
                return -ENODEV;
@@ -741,7 +738,7 @@ static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file)
        unsigned pin_state;
        unsigned result = 0;
 
-       dbg("%s(port = %d)", __FUNCTION__, port->number);
+       dbg("%s(port = %d)", __func__, port->number);
 
        if (!usb_get_intfdata(port->serial->interface))
                return -ENODEV;
@@ -764,7 +761,7 @@ static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file)
        if ((pin_state & PIN_DCD) != 0)
                result |= TIOCM_CD;
 
-       dbg("%s() = 0x%08x", __FUNCTION__, result);
+       dbg("%s() = 0x%08x", __func__, result);
 
        return result;
 }
@@ -811,13 +808,9 @@ static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
        unsigned int x;
 
        dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)",
-                               __FUNCTION__, port->number, cmd, arg);
+                               __func__, port->number, cmd, arg);
 
        switch (cmd) {
-               case TCFLSH:
-                       /* FIXME */
-                       return 0;
-
                case TIOCMBIS:
                        if (copy_from_user(&x, user_arg, sizeof(x)))
                                return -EFAULT;
@@ -829,11 +822,11 @@ static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
                        return oti6858_tiocmset(port, NULL, 0, x);
 
                case TIOCMIWAIT:
-                       dbg("%s(): TIOCMIWAIT", __FUNCTION__);
+                       dbg("%s(): TIOCMIWAIT", __func__);
                        return wait_modem_info(port, arg);
 
                default:
-                       dbg("%s(): 0x%04x not supported", __FUNCTION__, cmd);
+                       dbg("%s(): 0x%04x not supported", __func__, cmd);
                        break;
        }
 
@@ -844,10 +837,10 @@ static void oti6858_break_ctl(struct usb_serial_port *port, int break_state)
 {
        int state;
 
-       dbg("%s(port = %d)", __FUNCTION__, port->number);
+       dbg("%s(port = %d)", __func__, port->number);
 
        state = (break_state == 0) ? 0 : 1;
-       dbg("%s(): turning break %s", __FUNCTION__, state ? "on" : "off");
+       dbg("%s(): turning break %s", __func__, state ? "on" : "off");
 
        /* FIXME */
 /*
@@ -855,7 +848,7 @@ static void oti6858_break_ctl(struct usb_serial_port *port, int break_state)
                                  BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
                                  0, NULL, 0, 100);
        if (result != 0)
-               dbg("%s(): error sending break", __FUNCTION__);
+               dbg("%s(): error sending break", __func__);
  */
 }
 
@@ -864,7 +857,7 @@ static void oti6858_shutdown(struct usb_serial *serial)
        struct oti6858_private *priv;
        int i;
 
-       dbg("%s()", __FUNCTION__);
+       dbg("%s()", __func__);
 
        for (i = 0; i < serial->num_ports; ++i) {
                priv = usb_get_serial_port_data(serial->port[i]);
@@ -878,13 +871,13 @@ static void oti6858_shutdown(struct usb_serial *serial)
 
 static void oti6858_read_int_callback(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+       struct usb_serial_port *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);
+                               __func__, port->number, status);
 
        switch (status) {
        case 0:
@@ -895,11 +888,11 @@ static void oti6858_read_int_callback(struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s(): urb shutting down with status: %d",
-                                       __FUNCTION__, status);
+                                       __func__, status);
                return;
        default:
                dbg("%s(): nonzero urb status received: %d",
-                                       __FUNCTION__, status);
+                                       __func__, status);
                break;
        }
 
@@ -916,7 +909,7 @@ static void oti6858_read_int_callback(struct urb *urb)
                                        priv->setup_done = 0;
                                        resubmit = 0;
                                        dbg("%s(): scheduling setup_line()",
-                                           __FUNCTION__);
+                                           __func__);
                                        schedule_delayed_work(&priv->delayed_setup_work, 0);
                                }
                        }
@@ -931,7 +924,7 @@ static void oti6858_read_int_callback(struct urb *urb)
                                        priv->setup_done = 0;
                                        resubmit = 0;
                                        dbg("%s(): scheduling setup_line()",
-                                           __FUNCTION__);
+                                           __func__);
                                        schedule_delayed_work(&priv->delayed_setup_work, 0);
                                }
                        }
@@ -960,7 +953,7 @@ static void oti6858_read_int_callback(struct urb *urb)
                if (result != 0) {
                        priv->flags.read_urb_in_use = 0;
                        dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
-                                       " error %d\n", __FUNCTION__, result);
+                                       " error %d\n", __func__, result);
                } else {
                        resubmit = 0;
                }
@@ -979,20 +972,20 @@ static void oti6858_read_int_callback(struct urb *urb)
        if (resubmit) {
                int result;
 
-//             dbg("%s(): submitting interrupt urb", __FUNCTION__);
+//             dbg("%s(): submitting interrupt urb", __func__);
                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);
+                                       " error %d\n", __func__, result);
                }
        }
 }
 
 static void oti6858_read_bulk_callback(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+       struct usb_serial_port *port =  urb->context;
        struct oti6858_private *priv = usb_get_serial_port_data(port);
        struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
@@ -1001,7 +994,7 @@ static void oti6858_read_bulk_callback(struct urb *urb)
        int result;
 
        dbg("%s(port = %d, status = %d)",
-                               __FUNCTION__, port->number, status);
+                               __func__, port->number, status);
 
        spin_lock_irqsave(&priv->lock, flags);
        priv->flags.read_urb_in_use = 0;
@@ -1009,20 +1002,20 @@ static void oti6858_read_bulk_callback(struct urb *urb)
 
        if (status != 0) {
                if (!port->open_count) {
-                       dbg("%s(): port is closed, exiting", __FUNCTION__);
+                       dbg("%s(): port is closed, exiting", __func__);
                        return;
                }
                /*
                if (status == -EPROTO) {
                        // PL2303 mysteriously fails with -EPROTO reschedule the read
-                       dbg("%s - caught -EPROTO, resubmitting the urb", __FUNCTION__);
+                       dbg("%s - caught -EPROTO, resubmitting the urb", __func__);
                        result = usb_submit_urb(urb, GFP_ATOMIC);
                        if (result)
-                               dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+                               dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
                        return;
                }
                */
-               dbg("%s(): unable to handle the error, exiting", __FUNCTION__);
+               dbg("%s(): unable to handle the error, exiting", __func__);
                return;
        }
 
@@ -1038,20 +1031,20 @@ static void oti6858_read_bulk_callback(struct urb *urb)
                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);
+                                       " error %d\n", __func__, result);
                }
        }
 }
 
 static void oti6858_write_bulk_callback(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+       struct usb_serial_port *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);
+                               __func__, port->number, status);
 
        switch (status) {
        case 0:
@@ -1062,21 +1055,21 @@ static void oti6858_write_bulk_callback(struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s(): urb shutting down with status: %d",
-                                       __FUNCTION__, status);
+                                       __func__, 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__);
+                                       __func__, status);
+               dbg("%s(): overflow in write", __func__);
 
                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);
+                                       " error %d\n", __func__, result);
                } else {
                        return;
                }
@@ -1086,11 +1079,11 @@ static void oti6858_write_bulk_callback(struct urb *urb)
 
        // schedule the interrupt urb if we are still open */
        port->interrupt_in_urb->dev = port->serial->dev;
-       dbg("%s(): submitting interrupt urb", __FUNCTION__);
+       dbg("%s(): submitting interrupt urb", __func__);
        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);
+                                       " error %d\n", __func__, result);
        }
 }
 
index 2af778555bdc85496e3a3f02c9d8f3f977cda72f..c605fb68f807c460c41369f547946bf649192e3c 100644 (file)
@@ -410,7 +410,7 @@ static int set_control_lines(struct usb_device *dev, u8 value)
        retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                                 SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
                                 value, 0, NULL, 0, 100);
-       dbg("%s - value = %d, retval = %d", __FUNCTION__, value, retval);
+       dbg("%s - value = %d, retval = %d", __func__, value, retval);
        return retval;
 }
 
@@ -420,7 +420,7 @@ static void pl2303_send(struct usb_serial_port *port)
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
 
@@ -441,7 +441,7 @@ static void pl2303_send(struct usb_serial_port *port)
 
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count,
+       usb_serial_debug_data(debug, &port->dev, __func__, count,
                              port->write_urb->transfer_buffer);
 
        port->write_urb->transfer_buffer_length = count;
@@ -449,7 +449,7 @@ static void pl2303_send(struct usb_serial_port *port)
        result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
        if (result) {
                dev_err(&port->dev, "%s - failed submitting write urb,"
-                       " error %d\n", __FUNCTION__, result);
+                       " error %d\n", __func__, result);
                priv->write_urb_in_use = 0;
                // TODO: reschedule pl2303_send
        }
@@ -463,7 +463,7 @@ static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf,
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
 
-       dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
+       dbg("%s - port %d, %d bytes", __func__, port->number, count);
 
        if (!count)
                return count;
@@ -483,13 +483,13 @@ static int pl2303_write_room(struct usb_serial_port *port)
        int room = 0;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
        room = pl2303_buf_space_avail(priv->buf);
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       dbg("%s - returns %d", __FUNCTION__, room);
+       dbg("%s - returns %d", __func__, room);
        return room;
 }
 
@@ -499,13 +499,13 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port)
        int chars = 0;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
        chars = pl2303_buf_data_avail(priv->buf);
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       dbg("%s - returns %d", __FUNCTION__, chars);
+       dbg("%s - returns %d", __func__, chars);
        return chars;
 }
 
@@ -521,7 +521,7 @@ static void pl2303_set_termios(struct usb_serial_port *port,
        int i;
        u8 control;
 
-       dbg("%s -  port %d", __FUNCTION__, port->number);
+       dbg("%s -  port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
        if (!priv->termios_initialized) {
@@ -545,7 +545,9 @@ static void pl2303_set_termios(struct usb_serial_port *port,
 
        buf = kzalloc(7, GFP_KERNEL);
        if (!buf) {
-               dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
+               dev_err(&port->dev, "%s - out of memory.\n", __func__);
+               /* Report back no change occurred */
+               *port->tty->termios = *old_termios;
                return;
        }
 
@@ -563,11 +565,11 @@ static void pl2303_set_termios(struct usb_serial_port *port,
                        default:
                        case CS8:       buf[6] = 8;     break;
                }
-               dbg("%s - data bits = %d", __FUNCTION__, buf[6]);
+               dbg("%s - data bits = %d", __func__, buf[6]);
        }
 
        baud = tty_get_baud_rate(port->tty);;
-       dbg("%s - baud = %d", __FUNCTION__, baud);
+       dbg("%s - baud = %d", __func__, baud);
        if (baud) {
                buf[0] = baud & 0xff;
                buf[1] = (baud >> 8) & 0xff;
@@ -580,10 +582,10 @@ static void pl2303_set_termios(struct usb_serial_port *port,
        /* For reference buf[4]=2 is 2 stop bits */
        if (cflag & CSTOPB) {
                buf[4] = 2;
-               dbg("%s - stop bits = 2", __FUNCTION__);
+               dbg("%s - stop bits = 2", __func__);
        } else {
                buf[4] = 0;
-               dbg("%s - stop bits = 1", __FUNCTION__);
+               dbg("%s - stop bits = 1", __func__);
        }
 
        if (cflag & PARENB) {
@@ -594,14 +596,14 @@ static void pl2303_set_termios(struct usb_serial_port *port,
                /* For reference buf[5]=4 is space parity */
                if (cflag & PARODD) {
                        buf[5] = 1;
-                       dbg("%s - parity = odd", __FUNCTION__);
+                       dbg("%s - parity = odd", __func__);
                } else {
                        buf[5] = 2;
-                       dbg("%s - parity = even", __FUNCTION__);
+                       dbg("%s - parity = even", __func__);
                }
        } else {
                buf[5] = 0;
-               dbg("%s - parity = none", __FUNCTION__);
+               dbg("%s - parity = none", __func__);
        }
 
        i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
@@ -657,7 +659,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
        long timeout;
        wait_queue_t wait;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /* wait for data to drain from the buffer */
        spin_lock_irqsave(&priv->lock, flags);
@@ -695,7 +697,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
        schedule_timeout_interruptible(timeout);
 
        /* shutdown our urbs */
-       dbg("%s - shutting down urbs", __FUNCTION__);
+       dbg("%s - shutting down urbs", __func__);
        usb_kill_urb(port->write_urb);
        usb_kill_urb(port->read_urb);
        usb_kill_urb(port->interrupt_in_urb);
@@ -719,7 +721,7 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        int result;
 
-       dbg("%s -  port %d", __FUNCTION__, port->number);
+       dbg("%s -  port %d", __func__, port->number);
 
        if (priv->type != HX) {
                usb_clear_halt(serial->dev, port->write_urb->pipe);
@@ -737,22 +739,22 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
 
        //FIXME: need to assert RTS and DTR if CRTSCTS off
 
-       dbg("%s - submitting read urb", __FUNCTION__);
+       dbg("%s - submitting read urb", __func__);
        port->read_urb->dev = serial->dev;
        result = usb_submit_urb(port->read_urb, GFP_KERNEL);
        if (result) {
                dev_err(&port->dev, "%s - failed submitting read urb,"
-                       " error %d\n", __FUNCTION__, result);
+                       " error %d\n", __func__, result);
                pl2303_close(port, NULL);
                return -EPROTO;
        }
 
-       dbg("%s - submitting interrupt urb", __FUNCTION__);
+       dbg("%s - submitting interrupt urb", __func__);
        port->interrupt_in_urb->dev = serial->dev;
        result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
        if (result) {
                dev_err(&port->dev, "%s - failed submitting interrupt urb,"
-                       " error %d\n", __FUNCTION__, result);
+                       " error %d\n", __func__, result);
                pl2303_close(port, NULL);
                return -EPROTO;
        }
@@ -792,7 +794,7 @@ static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file)
        unsigned int status;
        unsigned int result;
 
-       dbg("%s (%d)", __FUNCTION__, port->number);
+       dbg("%s (%d)", __func__, port->number);
 
        if (!usb_get_intfdata(port->serial->interface))
                return -ENODEV;
@@ -809,7 +811,7 @@ static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file)
                  | ((status & UART_RING)       ? TIOCM_RI  : 0)
                  | ((status & UART_DCD)        ? TIOCM_CD  : 0);
 
-       dbg("%s - result = %x", __FUNCTION__, result);
+       dbg("%s - result = %x", __func__, result);
 
        return result;
 }
@@ -853,15 +855,15 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
 static int pl2303_ioctl(struct usb_serial_port *port, struct file *file,
                        unsigned int cmd, unsigned long arg)
 {
-       dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd);
+       dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
 
        switch (cmd) {
                case TIOCMIWAIT:
-                       dbg("%s (%d) TIOCMIWAIT", __FUNCTION__,  port->number);
+                       dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
                        return wait_modem_info(port, arg);
 
                default:
-                       dbg("%s not supported = 0x%04x", __FUNCTION__, cmd);
+                       dbg("%s not supported = 0x%04x", __func__, cmd);
                        break;
        }
 
@@ -874,19 +876,19 @@ static void pl2303_break_ctl(struct usb_serial_port *port, int break_state)
        u16 state;
        int result;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (break_state == 0)
                state = BREAK_OFF;
        else
                state = BREAK_ON;
-       dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on");
+       dbg("%s - turning break %s", __func__, state==BREAK_OFF ? "off" : "on");
 
        result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                                 BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
                                 0, NULL, 0, 100);
        if (result)
-               dbg("%s - error sending break = %d", __FUNCTION__, result);
+               dbg("%s - error sending break = %d", __func__, result);
 }
 
 static void pl2303_shutdown(struct usb_serial *serial)
@@ -894,7 +896,7 @@ static void pl2303_shutdown(struct usb_serial *serial)
        int i;
        struct pl2303_private *priv;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        for (i = 0; i < serial->num_ports; ++i) {
                priv = usb_get_serial_port_data(serial->port[i]);
@@ -943,13 +945,13 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
 
 static void pl2303_read_int_callback(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+       struct usb_serial_port *port =  urb->context;
        unsigned char *data = urb->transfer_buffer;
        unsigned int actual_length = urb->actual_length;
        int status = urb->status;
        int retval;
 
-       dbg("%s (%d)", __FUNCTION__, port->number);
+       dbg("%s (%d)", __func__, port->number);
 
        switch (status) {
        case 0:
@@ -959,16 +961,16 @@ static void pl2303_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__,
+               dbg("%s - urb shutting down with status: %d", __func__,
                    status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__,
+               dbg("%s - nonzero urb status received: %d", __func__,
                    status);
                goto exit;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+       usb_serial_debug_data(debug, &port->dev, __func__,
                              urb->actual_length, urb->transfer_buffer);
 
        pl2303_update_line_status(port, data, actual_length);
@@ -978,12 +980,12 @@ exit:
        if (retval)
                dev_err(&urb->dev->dev,
                        "%s - usb_submit_urb failed with result %d\n",
-                       __FUNCTION__, retval);
+                       __func__, retval);
 }
 
 static void pl2303_read_bulk_callback(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+       struct usb_serial_port *port =  urb->context;
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
@@ -994,32 +996,32 @@ static void pl2303_read_bulk_callback(struct urb *urb)
        u8 line_status;
        char tty_flag;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (status) {
-               dbg("%s - urb status = %d", __FUNCTION__, status);
+               dbg("%s - urb status = %d", __func__, status);
                if (!port->open_count) {
-                       dbg("%s - port is closed, exiting.", __FUNCTION__);
+                       dbg("%s - port is closed, exiting.", __func__);
                        return;
                }
                if (status == -EPROTO) {
                        /* PL2303 mysteriously fails with -EPROTO reschedule
                         * the read */
                        dbg("%s - caught -EPROTO, resubmitting the urb",
-                           __FUNCTION__);
+                           __func__);
                        urb->dev = port->serial->dev;
                        result = usb_submit_urb(urb, GFP_ATOMIC);
                        if (result)
                                dev_err(&urb->dev->dev, "%s - failed"
                                        " resubmitting read urb, error %d\n",
-                                       __FUNCTION__, result);
+                                       __func__, result);
                        return;
                }
-               dbg("%s - unable to handle the error, exiting.", __FUNCTION__);
+               dbg("%s - unable to handle the error, exiting.", __func__);
                return;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+       usb_serial_debug_data(debug, &port->dev, __func__,
                              urb->actual_length, data);
 
        /* get tty_flag from status */
@@ -1039,7 +1041,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
                tty_flag = TTY_PARITY;
        else if (line_status & UART_FRAME_ERROR)
                tty_flag = TTY_FRAME;
-       dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag);
+       dbg("%s - tty_flag = %d", __func__, tty_flag);
 
        tty = port->tty;
        if (tty && urb->actual_length) {
@@ -1058,7 +1060,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
                result = usb_submit_urb(urb, GFP_ATOMIC);
                if (result)
                        dev_err(&urb->dev->dev, "%s - failed resubmitting"
-                               " read urb, error %d\n", __FUNCTION__, result);
+                               " read urb, error %d\n", __func__, result);
        }
 
        return;
@@ -1066,12 +1068,12 @@ static void pl2303_read_bulk_callback(struct urb *urb)
 
 static void pl2303_write_bulk_callback(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+       struct usb_serial_port *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);
+       dbg("%s - port %d", __func__, port->number);
 
        switch (status) {
        case 0:
@@ -1081,21 +1083,21 @@ static void pl2303_write_bulk_callback(struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__,
+               dbg("%s - urb shutting down with status: %d", __func__,
                    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__,
+               dbg("%s - Overflow in write", __func__);
+               dbg("%s - nonzero write bulk status received: %d", __func__,
                    status);
                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(&urb->dev->dev, "%s - failed resubmitting write"
-                               " urb, error %d\n", __FUNCTION__, result);
+                               " urb, error %d\n", __func__, result);
                else
                        return;
        }
@@ -1114,9 +1116,6 @@ static struct usb_serial_driver pl2303_device = {
        },
        .id_table =             id_table,
        .usb_driver =           &pl2303_driver,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          1,
-       .num_bulk_out =         1,
        .num_ports =            1,
        .open =                 pl2303_open,
        .close =                pl2303_close,
index 4e6dcc199be9a3119800dcf82845858b64d41ad9..94bddf06ea4fb8f7d6849b99a5abfd53bb7729b8 100644 (file)
@@ -195,18 +195,17 @@ static __u16 __inline__ fcs_compute10 (unsigned char *sp, int len, __u16 fcs)
 
 static void safe_read_bulk_callback (struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+       struct usb_serial_port *port =  urb->context;
        unsigned char *data = urb->transfer_buffer;
        unsigned char length = urb->actual_length;
-       int i;
        int result;
        int status = urb->status;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        if (status) {
                dbg("%s - nonzero read bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        }
 
@@ -227,28 +226,20 @@ static void safe_read_bulk_callback (struct urb *urb)
        if (safe) {
                __u16 fcs;
                if (!(fcs = fcs_compute10 (data, length, CRC10_INITFCS))) {
-
                        int actual_length = data[length - 2] >> 2;
-
                        if (actual_length <= (length - 2)) {
-
-                               info ("%s - actual: %d", __FUNCTION__, actual_length);
-
-                               for (i = 0; i < actual_length; i++) {
-                                       tty_insert_flip_char (port->tty, data[i], 0);
-                               }
+                               info ("%s - actual: %d", __func__, actual_length);
+                               tty_insert_flip_string(port->tty, data, actual_length);
                                tty_flip_buffer_push (port->tty);
                        } else {
-                               err ("%s - inconsistent lengths %d:%d", __FUNCTION__,
+                               err ("%s - inconsistent lengths %d:%d", __func__,
                                     actual_length, length);
                        }
                } else {
-                       err ("%s - bad CRC %x", __FUNCTION__, fcs);
+                       err ("%s - bad CRC %x", __func__, fcs);
                }
        } else {
-               for (i = 0; i < length; i++) {
-                       tty_insert_flip_char (port->tty, data[i], 0);
-               }
+               tty_insert_flip_string(port->tty, data, length);
                tty_flip_buffer_push (port->tty);
        }
 
@@ -259,7 +250,8 @@ static void safe_read_bulk_callback (struct urb *urb)
                       safe_read_bulk_callback, port);
 
        if ((result = usb_submit_urb (urb, GFP_ATOMIC))) {
-               err ("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+               err ("%s - failed resubmitting read urb, error %d", __func__, result);
+               /* FIXME: Need a mechanism to retry later if this happens */
        }
 }
 
@@ -274,25 +266,25 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i
             count);
 
        if (!port->write_urb) {
-               dbg ("%s - write urb NULL", __FUNCTION__);
-               return (0);
+               dbg ("%s - write urb NULL", __func__);
+               return 0;
        }
 
        dbg ("safe_write write_urb: %d transfer_buffer_length",
             port->write_urb->transfer_buffer_length);
 
        if (!port->write_urb->transfer_buffer_length) {
-               dbg ("%s - write urb transfer_buffer_length zero", __FUNCTION__);
-               return (0);
+               dbg ("%s - write urb transfer_buffer_length zero", __func__);
+               return 0;
        }
        if (count == 0) {
-               dbg ("%s - write request of 0 bytes", __FUNCTION__);
-               return (0);
+               dbg ("%s - write request of 0 bytes", __func__);
+               return 0;
        }
        spin_lock_bh(&port->lock);
        if (port->write_urb_busy) {
                spin_unlock_bh(&port->lock);
-               dbg("%s - already writing", __FUNCTION__);
+               dbg("%s - already writing", __func__);
                return 0;
        }
        port->write_urb_busy = 1;
@@ -332,7 +324,7 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i
                port->write_urb->transfer_buffer_length = count;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer);
+       usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer);
 #ifdef ECHO_TX
        {
                int i;
@@ -349,28 +341,31 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i
        port->write_urb->dev = port->serial->dev;
        if ((result = usb_submit_urb (port->write_urb, GFP_KERNEL))) {
                port->write_urb_busy = 0;
-               err ("%s - failed submitting write urb, error %d", __FUNCTION__, result);
+               err ("%s - failed submitting write urb, error %d", __func__, result);
                return 0;
        }
-       dbg ("%s urb: %p submitted", __FUNCTION__, port->write_urb);
+       dbg ("%s urb: %p submitted", __func__, port->write_urb);
 
        return (count);
 }
 
 static int safe_write_room (struct usb_serial_port *port)
 {
-       int room = 0;           // Default: no room
+       int room = 0;           /* Default: no room */
+       unsigned long flags;
 
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
+       spin_lock_irqsave(&port->lock, flags);
        if (port->write_urb_busy)
                room = port->bulk_out_size - (safe ? 2 : 0);
+       spin_unlock_irqrestore(&port->lock, flags);
 
        if (room) {
                dbg ("safe_write_room returns %d", room);
        }
 
-       return (room);
+       return room;
 }
 
 static int safe_startup (struct usb_serial *serial)
@@ -394,9 +389,6 @@ static struct usb_serial_driver safe_device = {
        },
        .id_table =             id_table,
        .usb_driver =           &safe_driver,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          NUM_DONT_CARE,
-       .num_bulk_out =         NUM_DONT_CARE,
        .num_ports =            1,
        .write =                safe_write,
        .write_room =           safe_write_room,
index ed678811e6a6d0ed54e3f6db2c9c1b343bcdba69..29074c1ba22b6dd504218328e11c177ae4a76ab6 100644 (file)
@@ -1,7 +1,7 @@
 /*
   USB Driver for Sierra Wireless
 
-  Copyright (C) 2006, 2007, 2008  Kevin Lloyd <linux@sierrawireless.com>
+  Copyright (C) 2006, 2007, 2008  Kevin Lloyd <klloyd@sierrawireless.com>
 
   IMPORTANT DISCLAIMER: This driver is not commercially supported by
   Sierra Wireless. Use at your own risk.
@@ -14,8 +14,8 @@
   Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
 */
 
-#define DRIVER_VERSION "v.1.2.8"
-#define DRIVER_AUTHOR "Kevin Lloyd <linux@sierrawireless.com>"
+#define DRIVER_VERSION "v.1.2.9c"
+#define DRIVER_AUTHOR "Kevin Lloyd <klloyd@sierrawireless.com>"
 #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
 
 #include <linux/kernel.h>
@@ -31,7 +31,6 @@
 #define SWIMS_USB_REQUEST_SetPower     0x00
 #define SWIMS_USB_REQUEST_SetNmea      0x07
 #define SWIMS_USB_REQUEST_SetMode      0x0B
-#define SWIMS_USB_REQUEST_TYPE_VSC_SET 0x40
 #define SWIMS_SET_MODE_Modem           0x0001
 
 /* per port private data */
@@ -55,7 +54,7 @@ static int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
        dev_dbg(&udev->dev, "%s", "SET POWER STATE\n");
        result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                        SWIMS_USB_REQUEST_SetPower,     /* __u8 request      */
-                       SWIMS_USB_REQUEST_TYPE_VSC_SET, /* __u8 request type */
+                       USB_TYPE_VENDOR,                /* __u8 request type */
                        swiState,                       /* __u16 value       */
                        0,                              /* __u16 index       */
                        NULL,                           /* void *data        */
@@ -70,7 +69,7 @@ static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSWocMode)
        dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH\n");
        result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                        SWIMS_USB_REQUEST_SetMode,      /* __u8 request      */
-                       SWIMS_USB_REQUEST_TYPE_VSC_SET, /* __u8 request type */
+                       USB_TYPE_VENDOR,                /* __u8 request type */
                        eSWocMode,                      /* __u16 value       */
                        0x0000,                         /* __u16 index       */
                        NULL,                           /* void *data        */
@@ -85,7 +84,7 @@ static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable)
        dev_dbg(&udev->dev, "%s", "NMEA Enable sent\n");
        result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                        SWIMS_USB_REQUEST_SetNmea,      /* __u8 request      */
-                       SWIMS_USB_REQUEST_TYPE_VSC_SET, /* __u8 request type */
+                       USB_TYPE_VENDOR,                /* __u8 request type */
                        enable,                         /* __u16 value       */
                        0x0000,                         /* __u16 index       */
                        NULL,                           /* void *data        */
@@ -109,6 +108,26 @@ static int sierra_calc_num_ports(struct usb_serial *serial)
        return result;
 }
 
+static int sierra_calc_interface(struct usb_serial *serial)
+{
+               int interface;
+               struct usb_interface *p_interface;
+               struct usb_host_interface *p_host_interface;
+
+               /* Get the interface structure pointer from the serial struct */
+               p_interface = serial->interface;
+
+               /* Get a pointer to the host interface structure */
+               p_host_interface = p_interface->cur_altsetting;
+
+               /* read the interface descriptor for this active altsetting
+                * to find out the interface number we are on
+               */
+               interface = p_host_interface->desc.bInterfaceNumber;
+
+               return interface;
+}
+
 static int sierra_probe(struct usb_serial *serial,
                        const struct usb_device_id *id)
 {
@@ -124,6 +143,22 @@ static int sierra_probe(struct usb_serial *serial,
        ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
        udev = serial->dev;
 
+               /* Figure out the interface number from the serial structure */
+               ifnum = sierra_calc_interface(serial);
+
+               /*
+                * If this interface supports more than 1 alternate
+                * select the 2nd one
+                */
+               if (serial->interface->num_altsetting == 2) {
+                       dev_dbg(&udev->dev,
+                               "Selecting alt setting for interface %d\n",
+                               ifnum);
+
+                       /* We know the alternate setting is 1 for the MC8785 */
+                       usb_set_interface(udev, ifnum, 1);
+               }
+
        /* Check if in installer mode */
        if (truinstall && id->driver_info == DEVICE_INSTALLER) {
                dev_dbg(&udev->dev, "%s", "FOUND TRU-INSTALL DEVICE(SW)\n");
@@ -156,7 +191,7 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
        { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
        { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */
-       { USB_DEVICE(0x1199, 0x0023) }, /* Sierra Wireless AirCard */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) }, /* Sierra Wireless C597 */
 
        { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
        { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
@@ -164,15 +199,20 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */
        { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 (Thinkpad internal) */
        { USB_DEVICE(0x1199, 0x6815) }, /* Sierra Wireless MC8775 */
+       { USB_DEVICE(0x03f0, 0x1e1d) }, /* HP hs2300 a.k.a MC8775 */
        { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */
+       { USB_DEVICE(0x1199, 0x6821) }, /* Sierra Wireless AirCard 875U */
        { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780*/
        { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781*/
+       { USB_DEVICE(0x1199, 0x683B), .driver_info = DEVICE_1_PORT },   /* Sierra Wireless MC8785 Composite*/
        { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */
        { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */
        { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880 E */
        { USB_DEVICE(0x1199, 0x6853) }, /* Sierra Wireless AirCard 881 E */
        { USB_DEVICE(0x1199, 0x6855) }, /* Sierra Wireless AirCard 880 U */
        { USB_DEVICE(0x1199, 0x6856) }, /* Sierra Wireless AirCard 881 U */
+       { USB_DEVICE(0x1199, 0x6859), .driver_info = DEVICE_1_PORT },   /* Sierra Wireless AirCard 885 E */
+       { USB_DEVICE(0x1199, 0x685A), .driver_info = DEVICE_1_PORT },   /* Sierra Wireless AirCard 885 E */
 
        { USB_DEVICE(0x1199, 0x6468) }, /* Sierra Wireless MP3G - EVDO */
        { USB_DEVICE(0x1199, 0x6469) }, /* Sierra Wireless MP3G - UMTS/HSPA */
@@ -216,7 +256,7 @@ static int sierra_send_setup(struct usb_serial_port *port)
        struct sierra_port_private *portdata;
        __u16 interface = 0;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        portdata = usb_get_serial_port_data(port);
 
@@ -246,24 +286,24 @@ static int sierra_send_setup(struct usb_serial_port *port)
 
 static void sierra_rx_throttle(struct usb_serial_port *port)
 {
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 }
 
 static void sierra_rx_unthrottle(struct usb_serial_port *port)
 {
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 }
 
 static void sierra_break_ctl(struct usb_serial_port *port, int break_state)
 {
        /* Unfortunately, I don't know how to send a break */
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 }
 
 static void sierra_set_termios(struct usb_serial_port *port,
                        struct ktermios *old_termios)
 {
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
        tty_termios_copy_hw(port->tty->termios, old_termios);
        sierra_send_setup(port);
 }
@@ -317,14 +357,14 @@ static void sierra_outdat_callback(struct urb *urb)
        int status = urb->status;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, 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);
+                   __func__, status);
 
        spin_lock_irqsave(&portdata->lock, flags);
        --portdata->outstanding_urbs;
@@ -346,12 +386,12 @@ static int sierra_write(struct usb_serial_port *port,
 
        portdata = usb_get_serial_port_data(port);
 
-       dbg("%s: write (%d chars)", __FUNCTION__, count);
+       dbg("%s: write (%d chars)", __func__, count);
 
        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__);
+               dbg("%s - write limit hit\n", __func__);
                return 0;
        }
        portdata->outstanding_urbs++;
@@ -373,7 +413,7 @@ static int sierra_write(struct usb_serial_port *port,
 
        memcpy(buffer, buf, count);
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
+       usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
 
        usb_fill_bulk_urb(urb, serial->dev,
                          usb_sndbulkpipe(serial->dev,
@@ -384,7 +424,7 @@ static int sierra_write(struct usb_serial_port *port,
        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);
+                       "with status = %d\n", __func__, status);
                count = status;
                goto error;
        }
@@ -414,14 +454,14 @@ static void sierra_indat_callback(struct urb *urb)
        unsigned char *data = urb->transfer_buffer;
        int status = urb->status;
 
-       dbg("%s: %p", __FUNCTION__, urb);
+       dbg("%s: %p", __func__, urb);
 
        endpoint = usb_pipeendpoint(urb->pipe);
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
 
        if (status) {
                dbg("%s: nonzero status: %d on endpoint %02x.",
-                   __FUNCTION__, status, endpoint);
+                   __func__, status, endpoint);
        } else {
                tty = port->tty;
                if (urb->actual_length) {
@@ -429,7 +469,7 @@ static void sierra_indat_callback(struct urb *urb)
                        tty_insert_flip_string(tty, data, urb->actual_length);
                        tty_flip_buffer_push(tty);
                } else {
-                       dbg("%s: empty read urb received", __FUNCTION__);
+                       dbg("%s: empty read urb received", __func__);
                }
 
                /* Resubmit urb so we continue receiving */
@@ -447,19 +487,19 @@ 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 usb_serial_port *port =  urb->context;
        struct sierra_port_private *portdata = usb_get_serial_port_data(port);
        struct usb_serial *serial = port->serial;
 
-       dbg("%s", __FUNCTION__);
-       dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
+       dbg("%s", __func__);
+       dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata);
 
        if (status == 0) {
                struct usb_ctrlrequest *req_pkt =
                                (struct usb_ctrlrequest *)urb->transfer_buffer;
 
                if (!req_pkt) {
-                       dbg("%s: NULL req_pkt\n", __FUNCTION__);
+                       dbg("%s: NULL req_pkt\n", __func__);
                        return;
                }
                if ((req_pkt->bRequestType == 0xA1) &&
@@ -469,7 +509,7 @@ static void sierra_instat_callback(struct urb *urb)
                                        urb->transfer_buffer +
                                        sizeof(struct usb_ctrlrequest));
 
-                       dbg("%s: signal x%x", __FUNCTION__, signals);
+                       dbg("%s: signal x%x", __func__, signals);
 
                        old_dcd_state = portdata->dcd_state;
                        portdata->cts_state = 1;
@@ -481,11 +521,11 @@ static void sierra_instat_callback(struct urb *urb)
                                        old_dcd_state && !portdata->dcd_state)
                                tty_hangup(port->tty);
                } else {
-                       dbg("%s: type %x req %x", __FUNCTION__,
-                               req_pkt->bRequestType,req_pkt->bRequest);
+                       dbg("%s: type %x req %x", __func__,
+                               req_pkt->bRequestType, req_pkt->bRequest);
                }
        } else
-               dbg("%s: error %d", __FUNCTION__, status);
+               dbg("%s: error %d", __func__, status);
 
        /* Resubmit urb so we continue receiving IRQ data */
        if (status != -ESHUTDOWN) {
@@ -493,7 +533,7 @@ static void sierra_instat_callback(struct urb *urb)
                err = usb_submit_urb(urb, GFP_ATOMIC);
                if (err)
                        dbg("%s: resubmit intr urb failed. (%d)",
-                               __FUNCTION__, err);
+                               __func__, err);
        }
 }
 
@@ -502,14 +542,14 @@ static int sierra_write_room(struct usb_serial_port *port)
        struct sierra_port_private *portdata = usb_get_serial_port_data(port);
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /* 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__);
+               dbg("%s - write limit hit\n", __func__);
                return 0;
        }
        spin_unlock_irqrestore(&portdata->lock, flags);
@@ -519,13 +559,15 @@ static int sierra_write_room(struct usb_serial_port *port)
 
 static int sierra_chars_in_buffer(struct usb_serial_port *port)
 {
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, 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.
+        *
+        * FIXME: should walk the outstanding urbs info
         */
        return 0;
 }
@@ -540,7 +582,7 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
 
        portdata = usb_get_serial_port_data(port);
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /* Set some sane defaults */
        portdata->rts_state = 1;
@@ -552,7 +594,7 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
                if (!urb)
                        continue;
                if (urb->dev != serial->dev) {
-                       dbg("%s: dev %p != %p", __FUNCTION__,
+                       dbg("%s: dev %p != %p", __func__,
                                urb->dev, serial->dev);
                        continue;
                }
@@ -590,7 +632,7 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp)
        struct usb_serial *serial = port->serial;
        struct sierra_port_private *portdata;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
        portdata = usb_get_serial_port_data(port);
 
        portdata->rts_state = 0;
@@ -620,7 +662,7 @@ static int sierra_startup(struct usb_serial *serial)
        int i;
        int j;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /* Set Device mode to D0 */
        sierra_set_power_state(serial->dev, 0x0000);
@@ -635,7 +677,7 @@ static int sierra_startup(struct usb_serial *serial)
                portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
                if (!portdata) {
                        dbg("%s: kmalloc for sierra_port_private (%d) failed!.",
-                                       __FUNCTION__, i);
+                                       __func__, i);
                        return -ENOMEM;
                }
                spin_lock_init(&portdata->lock);
@@ -656,7 +698,7 @@ static int sierra_startup(struct usb_serial *serial)
                        urb = usb_alloc_urb(0, GFP_KERNEL);
                        if (urb == NULL) {
                                dbg("%s: alloc for in port failed.",
-                                   __FUNCTION__);
+                                   __func__);
                                continue;
                        }
                        /* Fill URB using supplied data. */
@@ -678,7 +720,7 @@ static void sierra_shutdown(struct usb_serial *serial)
        struct usb_serial_port *port;
        struct sierra_port_private *portdata;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        for (i = 0; i < serial->num_ports; ++i) {
                port = serial->port[i];
@@ -706,9 +748,6 @@ static struct usb_serial_driver sierra_device = {
        .description       = "Sierra USB modem",
        .id_table          = id_table,
        .usb_driver        = &sierra_driver,
-       .num_interrupt_in  = NUM_DONT_CARE,
-       .num_bulk_in       = NUM_DONT_CARE,
-       .num_bulk_out      = NUM_DONT_CARE,
        .calc_num_ports    = sierra_calc_num_ports,
        .probe             = sierra_probe,
        .open              = sierra_open,
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
new file mode 100644 (file)
index 0000000..2282d62
--- /dev/null
@@ -0,0 +1,1072 @@
+/*
+ * spcp8x5 USB to serial adaptor driver
+ *
+ * Copyright (C) 2006 Linxb (xubin.lin@worldplus.com.cn)
+ * Copyright (C) 2006 S1 Corp.
+ *
+ * Original driver for 2.6.10 pl2303 driver by
+ *   Greg Kroah-Hartman (greg@kroah.com)
+ * Changes for 2.6.20 by Harald Klein <hari@vt100.at>
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+
+/* Version Information */
+#define DRIVER_VERSION         "v0.04"
+#define DRIVER_DESC    "SPCP8x5 USB to serial adaptor driver"
+
+static int debug;
+
+#define SPCP8x5_007_VID                0x04FC
+#define SPCP8x5_007_PID                0x0201
+#define SPCP8x5_008_VID                0x04fc
+#define SPCP8x5_008_PID                0x0235
+#define SPCP8x5_PHILIPS_VID    0x0471
+#define SPCP8x5_PHILIPS_PID    0x081e
+#define SPCP8x5_INTERMATIC_VID 0x04FC
+#define SPCP8x5_INTERMATIC_PID 0x0204
+#define SPCP8x5_835_VID                0x04fc
+#define SPCP8x5_835_PID                0x0231
+
+static struct usb_device_id id_table [] = {
+       { USB_DEVICE(SPCP8x5_PHILIPS_VID , SPCP8x5_PHILIPS_PID)},
+       { USB_DEVICE(SPCP8x5_INTERMATIC_VID, SPCP8x5_INTERMATIC_PID)},
+       { USB_DEVICE(SPCP8x5_835_VID, SPCP8x5_835_PID)},
+       { USB_DEVICE(SPCP8x5_008_VID, SPCP8x5_008_PID)},
+       { USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID)},
+       { }                                     /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+struct spcp8x5_usb_ctrl_arg {
+       u8      type;
+       u8      cmd;
+       u8      cmd_type;
+       u16     value;
+       u16     index;
+       u16     length;
+};
+
+/* wait 30s before close */
+#define SPCP8x5_CLOSING_WAIT   (30*HZ)
+
+#define SPCP8x5_BUF_SIZE       1024
+
+
+/* spcp8x5 spec register define */
+#define MCR_CONTROL_LINE_RTS           0x02
+#define MCR_CONTROL_LINE_DTR           0x01
+#define MCR_DTR                                0x01
+#define MCR_RTS                                0x02
+
+#define MSR_STATUS_LINE_DCD            0x80
+#define MSR_STATUS_LINE_RI             0x40
+#define MSR_STATUS_LINE_DSR            0x20
+#define MSR_STATUS_LINE_CTS            0x10
+
+/* verdor command here , we should define myself */
+#define SET_DEFAULT                    0x40
+#define SET_DEFAULT_TYPE               0x20
+
+#define SET_UART_FORMAT                        0x40
+#define SET_UART_FORMAT_TYPE           0x21
+#define SET_UART_FORMAT_SIZE_5         0x00
+#define SET_UART_FORMAT_SIZE_6         0x01
+#define SET_UART_FORMAT_SIZE_7         0x02
+#define SET_UART_FORMAT_SIZE_8         0x03
+#define SET_UART_FORMAT_STOP_1         0x00
+#define SET_UART_FORMAT_STOP_2         0x04
+#define SET_UART_FORMAT_PAR_NONE       0x00
+#define SET_UART_FORMAT_PAR_ODD                0x10
+#define SET_UART_FORMAT_PAR_EVEN       0x30
+#define SET_UART_FORMAT_PAR_MASK       0xD0
+#define SET_UART_FORMAT_PAR_SPACE      0x90
+
+#define GET_UART_STATUS_TYPE           0xc0
+#define GET_UART_STATUS                        0x22
+#define GET_UART_STATUS_MSR            0x06
+
+#define SET_UART_STATUS                        0x40
+#define SET_UART_STATUS_TYPE           0x23
+#define SET_UART_STATUS_MCR            0x0004
+#define SET_UART_STATUS_MCR_DTR                0x01
+#define SET_UART_STATUS_MCR_RTS                0x02
+#define SET_UART_STATUS_MCR_LOOP       0x10
+
+#define SET_WORKING_MODE               0x40
+#define SET_WORKING_MODE_TYPE          0x24
+#define SET_WORKING_MODE_U2C           0x00
+#define SET_WORKING_MODE_RS485         0x01
+#define SET_WORKING_MODE_PDMA          0x02
+#define SET_WORKING_MODE_SPP           0x03
+
+#define SET_FLOWCTL_CHAR               0x40
+#define SET_FLOWCTL_CHAR_TYPE          0x25
+
+#define GET_VERSION                    0xc0
+#define GET_VERSION_TYPE               0x26
+
+#define SET_REGISTER                   0x40
+#define SET_REGISTER_TYPE              0x27
+
+#define        GET_REGISTER                    0xc0
+#define GET_REGISTER_TYPE              0x28
+
+#define SET_RAM                                0x40
+#define SET_RAM_TYPE                   0x31
+
+#define GET_RAM                                0xc0
+#define GET_RAM_TYPE                   0x32
+
+/* how come ??? */
+#define UART_STATE                     0x08
+#define UART_STATE_TRANSIENT_MASK      0x74
+#define UART_DCD                       0x01
+#define UART_DSR                       0x02
+#define UART_BREAK_ERROR               0x04
+#define UART_RING                      0x08
+#define UART_FRAME_ERROR               0x10
+#define UART_PARITY_ERROR              0x20
+#define UART_OVERRUN_ERROR             0x40
+#define UART_CTS                       0x80
+
+enum spcp8x5_type {
+       SPCP825_007_TYPE,
+       SPCP825_008_TYPE,
+       SPCP825_PHILIP_TYPE,
+       SPCP825_INTERMATIC_TYPE,
+       SPCP835_TYPE,
+};
+
+/* 1st in 1st out buffer 4 driver */
+struct ringbuf {
+       unsigned int    buf_size;
+       char            *buf_buf;
+       char            *buf_get;
+       char            *buf_put;
+};
+
+/* alloc the ring buf and alloc the buffer itself */
+static inline struct ringbuf *alloc_ringbuf(unsigned int size)
+{
+       struct ringbuf *pb;
+
+       if (size == 0)
+               return NULL;
+
+       pb = kmalloc(sizeof(*pb), 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;
+}
+
+/* free the ring buf and the buffer itself */
+static inline void free_ringbuf(struct ringbuf *pb)
+{
+       if (pb != NULL) {
+               kfree(pb->buf_buf);
+               kfree(pb);
+       }
+}
+
+/* clear pipo , juest repoint the pointer here */
+static inline void clear_ringbuf(struct ringbuf *pb)
+{
+       if (pb != NULL)
+               pb->buf_get = pb->buf_put;
+}
+
+/* get the number of data in the pipo */
+static inline unsigned int ringbuf_avail_data(struct ringbuf *pb)
+{
+       if (pb == NULL)
+               return 0;
+       return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
+}
+
+/* get the number of space in the pipo */
+static inline unsigned int ringbuf_avail_space(struct ringbuf *pb)
+{
+       if (pb == NULL)
+               return 0;
+       return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
+}
+
+/* put count data into pipo */
+static unsigned int put_ringbuf(struct ringbuf *pb, const char *buf,
+                               unsigned int count)
+{
+       unsigned int len;
+
+       if (pb == NULL)
+               return 0;
+
+       len  = ringbuf_avail_space(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;
+}
+
+/* get count data from pipo */
+static unsigned int get_ringbuf(struct ringbuf *pb, char *buf,
+                               unsigned int count)
+{
+       unsigned int len;
+
+       if (pb == NULL || buf == NULL)
+               return 0;
+
+       len = ringbuf_avail_data(pb);
+       if (count > len)
+               count = len;
+
+       if (count == 0)
+               return 0;
+
+       len = pb->buf_buf + pb->buf_size - pb->buf_get;
+       if (count > len) {
+               memcpy(buf, pb->buf_get, len);
+               memcpy(buf+len, pb->buf_buf, count - len);
+               pb->buf_get = pb->buf_buf + count - len;
+       } else {
+               memcpy(buf, pb->buf_get, count);
+               if (count < len)
+                       pb->buf_get += count;
+               else /* count == len */
+                       pb->buf_get = pb->buf_buf;
+       }
+
+       return count;
+}
+
+static struct usb_driver spcp8x5_driver = {
+       .name =                 "spcp8x5",
+       .probe =                usb_serial_probe,
+       .disconnect =           usb_serial_disconnect,
+       .id_table =             id_table,
+       .no_dynamic_id =        1,
+};
+
+
+struct spcp8x5_private {
+       spinlock_t      lock;
+       struct ringbuf  *buf;
+       int             write_urb_in_use;
+       enum spcp8x5_type       type;
+       wait_queue_head_t       delta_msr_wait;
+       u8                      line_control;
+       u8                      line_status;
+       u8                      termios_initialized;
+};
+
+/* desc : when device plug in,this function would be called.
+ * thanks to usb_serial subsystem,then do almost every things for us. And what
+ * we should do just alloc the buffer */
+static int spcp8x5_startup(struct usb_serial *serial)
+{
+       struct spcp8x5_private *priv;
+       int i;
+       enum spcp8x5_type type = SPCP825_007_TYPE;
+
+       if (serial->dev->descriptor.idProduct == 0x0201)
+               type = SPCP825_007_TYPE;
+       else if (serial->dev->descriptor.idProduct == 0x0231)
+               type = SPCP835_TYPE;
+       else if (serial->dev->descriptor.idProduct == 0x0235)
+               type = SPCP825_008_TYPE;
+       else if (serial->dev->descriptor.idProduct == 0x0204)
+               type = SPCP825_INTERMATIC_TYPE;
+       else if (serial->dev->descriptor.idProduct == 0x0471 &&
+                serial->dev->descriptor.idVendor == 0x081e)
+               type = SPCP825_PHILIP_TYPE;
+       dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type);
+
+       for (i = 0; i < serial->num_ports; ++i) {
+               priv = kzalloc(sizeof(struct spcp8x5_private), GFP_KERNEL);
+               if (!priv)
+                       goto cleanup;
+
+               spin_lock_init(&priv->lock);
+               priv->buf = alloc_ringbuf(SPCP8x5_BUF_SIZE);
+               if (priv->buf == NULL)
+                       goto cleanup2;
+
+               init_waitqueue_head(&priv->delta_msr_wait);
+               priv->type = type;
+               usb_set_serial_port_data(serial->port[i] , priv);
+
+       }
+
+       return 0;
+
+cleanup2:
+       kfree(priv);
+cleanup:
+       for (--i; i >= 0; --i) {
+               priv = usb_get_serial_port_data(serial->port[i]);
+               free_ringbuf(priv->buf);
+               kfree(priv);
+               usb_set_serial_port_data(serial->port[i] , NULL);
+       }
+       return -ENOMEM;
+}
+
+/* call when the device plug out. free all the memory alloced by probe */
+static void spcp8x5_shutdown(struct usb_serial *serial)
+{
+       int i;
+       struct spcp8x5_private *priv;
+
+       for (i = 0; i < serial->num_ports; i++) {
+               priv = usb_get_serial_port_data(serial->port[i]);
+               if (priv) {
+                       free_ringbuf(priv->buf);
+                       kfree(priv);
+                       usb_set_serial_port_data(serial->port[i] , NULL);
+               }
+       }
+}
+
+/* set the modem control line of the device.
+ * NOTE spcp825-007 not supported this */
+static int spcp8x5_set_ctrlLine(struct usb_device *dev, u8 value,
+                               enum spcp8x5_type type)
+{
+       int retval;
+       u8 mcr = 0 ;
+
+       if (type == SPCP825_007_TYPE)
+               return -EPERM;
+
+       mcr = (unsigned short)value;
+       retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                                SET_UART_STATUS_TYPE, SET_UART_STATUS,
+                                mcr, 0x04, NULL, 0, 100);
+       if (retval != 0)
+               dev_dbg(&dev->dev, "usb_control_msg return %#x\n", retval);
+       return retval;
+}
+
+/* get the modem status register of the device
+ * NOTE spcp825-007 not supported this */
+static int spcp8x5_get_msr(struct usb_device *dev, u8 *status,
+                          enum spcp8x5_type type)
+{
+       u8 *status_buffer;
+       int ret;
+
+       /* I return Permited not support here but seem inval device
+        * is more fix */
+       if (type == SPCP825_007_TYPE)
+               return -EPERM;
+       if (status == NULL)
+               return -EINVAL;
+
+       status_buffer = kmalloc(1, GFP_KERNEL);
+       if (!status_buffer)
+               return -ENOMEM;
+       status_buffer[0] = status[0];
+
+       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+                             GET_UART_STATUS, GET_UART_STATUS_TYPE,
+                             0, GET_UART_STATUS_MSR, status_buffer, 1, 100);
+       if (ret < 0)
+               dev_dbg(&dev->dev, "Get MSR = 0x%p failed (error = %d)",
+                       status_buffer, ret);
+
+       dev_dbg(&dev->dev, "0xc0:0x22:0:6  %d - 0x%p ", ret, status_buffer);
+       status[0] = status_buffer[0];
+       kfree(status_buffer);
+
+       return ret;
+}
+
+/* select the work mode.
+ * NOTE this function not supported by spcp825-007 */
+static void spcp8x5_set_workMode(struct usb_device *dev, u16 value,
+                                u16 index, enum spcp8x5_type type)
+{
+       int ret;
+
+       /* I return Permited not support here but seem inval device
+        * is more fix */
+       if (type == SPCP825_007_TYPE)
+               return;
+
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                             SET_WORKING_MODE_TYPE, SET_WORKING_MODE,
+                             value, index, NULL, 0, 100);
+       dev_dbg(&dev->dev, "value = %#x , index = %#x\n", value, index);
+       if (ret < 0)
+               dev_dbg(&dev->dev,
+                       "RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret);
+}
+
+/* close the serial port. We should wait for data sending to device 1st and
+ * then kill all urb. */
+static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
+{
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       unsigned int c_cflag;
+       int bps;
+       long timeout;
+       wait_queue_t wait;
+       int result;
+
+       dbg("%s - port %d", __func__, port->number);
+
+       /* wait for data to drain from the buffer */
+       spin_lock_irqsave(&priv->lock, flags);
+       timeout = SPCP8x5_CLOSING_WAIT;
+       init_waitqueue_entry(&wait, current);
+       add_wait_queue(&port->tty->write_wait, &wait);
+       for (;;) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (ringbuf_avail_data(priv->buf) == 0 ||
+                   timeout == 0 || signal_pending(current))
+                       break;
+               spin_unlock_irqrestore(&priv->lock, flags);
+               timeout = schedule_timeout(timeout);
+               spin_lock_irqsave(&priv->lock, flags);
+       }
+       set_current_state(TASK_RUNNING);
+       remove_wait_queue(&port->tty->write_wait, &wait);
+
+       /* clear out any remaining data in the buffer */
+       clear_ringbuf(priv->buf);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       /* wait for characters to drain from the device (this is long enough
+        * for the entire all byte spcp8x5 hardware buffer to drain with no
+        * flow control for data rates of 1200 bps or more, for lower rates we
+        * should really know how much data is in the buffer to compute a delay
+        * that is not unnecessarily long) */
+       bps = tty_get_baud_rate(port->tty);
+       if (bps > 1200)
+               timeout = max((HZ*2560) / bps, HZ/10);
+       else
+               timeout = 2*HZ;
+       set_current_state(TASK_INTERRUPTIBLE);
+       schedule_timeout(timeout);
+
+       /* clear control lines */
+       if (port->tty) {
+               c_cflag = port->tty->termios->c_cflag;
+               if (c_cflag & HUPCL) {
+                       spin_lock_irqsave(&priv->lock, flags);
+                       priv->line_control = 0;
+                       spin_unlock_irqrestore(&priv->lock, flags);
+                       spcp8x5_set_ctrlLine(port->serial->dev, 0 , priv->type);
+               }
+       }
+
+       /* kill urb */
+       if (port->write_urb != NULL) {
+               result = usb_unlink_urb(port->write_urb);
+               if (result)
+                       dev_dbg(&port->dev,
+                               "usb_unlink_urb(write_urb) = %d\n", result);
+       }
+       result = usb_unlink_urb(port->read_urb);
+       if (result)
+               dev_dbg(&port->dev, "usb_unlink_urb(read_urb) = %d\n", result);
+}
+
+/* set the serial param for transfer. we should check if we really need to
+ * transfer. then if be set flow contorl we should do this too. */
+static void spcp8x5_set_termios(struct usb_serial_port *port,
+                               struct ktermios *old_termios)
+{
+       struct usb_serial *serial = port->serial;
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       unsigned int cflag = port->tty->termios->c_cflag;
+       unsigned int old_cflag = old_termios->c_cflag;
+       unsigned short uartdata;
+       unsigned char buf[2] = {0, 0};
+       int baud;
+       int i;
+       u8 control;
+
+       if ((!port->tty) || (!port->tty->termios))
+               return;
+
+       /* for the 1st time call this function */
+       spin_lock_irqsave(&priv->lock, flags);
+       if (!priv->termios_initialized) {
+               *(port->tty->termios) = tty_std_termios;
+               port->tty->termios->c_cflag = B115200 | CS8 | CREAD |
+                                             HUPCL | CLOCAL;
+               priv->termios_initialized = 1;
+       }
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       /* check that they really want us to change something */
+       if (!tty_termios_hw_change(port->tty->termios, old_termios))
+               return;
+
+       /* set DTR/RTS active */
+       spin_lock_irqsave(&priv->lock, flags);
+       control = priv->line_control;
+       if ((old_cflag & CBAUD) == B0) {
+               priv->line_control |= MCR_DTR;
+               if (!(old_cflag & CRTSCTS))
+                       priv->line_control |= MCR_RTS;
+       }
+       if (control != priv->line_control) {
+               control = priv->line_control;
+               spin_unlock_irqrestore(&priv->lock, flags);
+               spcp8x5_set_ctrlLine(serial->dev, control , priv->type);
+       } else {
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
+
+       /* Set Baud Rate */
+       baud = tty_get_baud_rate(port->tty);;
+       switch (baud) {
+       case 300:       buf[0] = 0x00;  break;
+       case 600:       buf[0] = 0x01;  break;
+       case 1200:      buf[0] = 0x02;  break;
+       case 2400:      buf[0] = 0x03;  break;
+       case 4800:      buf[0] = 0x04;  break;
+       case 9600:      buf[0] = 0x05;  break;
+       case 19200:     buf[0] = 0x07;  break;
+       case 38400:     buf[0] = 0x09;  break;
+       case 57600:     buf[0] = 0x0a;  break;
+       case 115200:    buf[0] = 0x0b;  break;
+       case 230400:    buf[0] = 0x0c;  break;
+       case 460800:    buf[0] = 0x0d;  break;
+       case 921600:    buf[0] = 0x0e;  break;
+/*     case 1200000:   buf[0] = 0x0f;  break; */
+/*     case 2400000:   buf[0] = 0x10;  break; */
+       case 3000000:   buf[0] = 0x11;  break;
+/*     case 6000000:   buf[0] = 0x12;  break; */
+       case 0:
+       case 1000000:
+                       buf[0] = 0x0b;  break;
+       default:
+               err("spcp825 driver does not support the baudrate "
+                   "requested, using default of 9600.");
+       }
+
+       /* Set Data Length : 00:5bit, 01:6bit, 10:7bit, 11:8bit */
+       if (cflag & CSIZE) {
+               switch (cflag & CSIZE) {
+               case CS5:
+                       buf[1] |= SET_UART_FORMAT_SIZE_5;
+                       break;
+               case CS6:
+                       buf[1] |= SET_UART_FORMAT_SIZE_6;
+                       break;
+               case CS7:
+                       buf[1] |= SET_UART_FORMAT_SIZE_7;
+                       break;
+               default:
+               case CS8:
+                       buf[1] |= SET_UART_FORMAT_SIZE_8;
+                       break;
+               }
+       }
+
+       /* Set Stop bit2 : 0:1bit 1:2bit */
+       buf[1] |= (cflag & CSTOPB) ? SET_UART_FORMAT_STOP_2 :
+                                    SET_UART_FORMAT_STOP_1;
+
+       /* Set Parity bit3-4 01:Odd 11:Even */
+       if (cflag & PARENB) {
+               buf[1] |= (cflag & PARODD) ?
+               SET_UART_FORMAT_PAR_ODD : SET_UART_FORMAT_PAR_EVEN ;
+       } else
+               buf[1] |= SET_UART_FORMAT_PAR_NONE;
+
+       uartdata = buf[0] | buf[1]<<8;
+
+       i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                           SET_UART_FORMAT_TYPE, SET_UART_FORMAT,
+                           uartdata, 0, NULL, 0, 100);
+       if (i < 0)
+               err("Set UART format %#x failed (error = %d)", uartdata, i);
+       dbg("0x21:0x40:0:0  %d\n", i);
+
+       if (cflag & CRTSCTS) {
+               /* enable hardware flow control */
+               spcp8x5_set_workMode(serial->dev, 0x000a,
+                                    SET_WORKING_MODE_U2C, priv->type);
+       }
+       return;
+}
+
+/* open the serial port. do some usb system call. set termios and get the line
+ * status of the device. then submit the read urb */
+static int spcp8x5_open(struct usb_serial_port *port, struct file *filp)
+{
+       struct ktermios tmp_termios;
+       struct usb_serial *serial = port->serial;
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       int ret;
+       unsigned long flags;
+       u8 status = 0x30;
+       /* status 0x30 means DSR and CTS = 1 other CDC RI and delta = 0 */
+
+       dbg("%s -  port %d", __func__, port->number);
+
+       usb_clear_halt(serial->dev, port->write_urb->pipe);
+       usb_clear_halt(serial->dev, port->read_urb->pipe);
+
+       ret = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                             0x09, 0x00,
+                             0x01, 0x00, NULL, 0x00, 100);
+       if (ret)
+               return ret;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (port->tty->termios->c_cflag & CBAUD)
+               priv->line_control = MCR_DTR | MCR_RTS;
+       else
+               priv->line_control = 0;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
+
+       /* Setup termios */
+       if (port->tty)
+               spcp8x5_set_termios(port, &tmp_termios);
+
+       spcp8x5_get_msr(serial->dev, &status, priv->type);
+
+       /* may be we should update uart status here but now we did not do */
+       spin_lock_irqsave(&priv->lock, flags);
+       priv->line_status = status & 0xf0 ;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       /* FIXME: need to assert RTS and DTR if CRTSCTS off */
+
+       dbg("%s - submitting read urb", __func__);
+       port->read_urb->dev = serial->dev;
+       ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
+       if (ret) {
+               spcp8x5_close(port, NULL);
+               return -EPROTO;
+       }
+       return 0;
+}
+
+/* bulk read call back function. check the status of the urb. if transfer
+ * failed return. then update the status and the tty send data to tty subsys.
+ * submit urb again.
+ */
+static void spcp8x5_read_bulk_callback(struct urb *urb)
+{
+       struct usb_serial_port *port = urb->context;
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       struct tty_struct *tty;
+       unsigned char *data = urb->transfer_buffer;
+       unsigned long flags;
+       int i;
+       int result;
+       u8 status = 0;
+       char tty_flag;
+
+       dev_dbg(&port->dev, "start, urb->status = %d, "
+               "urb->actual_length = %d\n,", urb->status, urb->actual_length);
+
+       /* check the urb status */
+       if (urb->status) {
+               if (!port->open_count)
+                       return;
+               if (urb->status == -EPROTO) {
+                       /* spcp8x5 mysteriously fails with -EPROTO */
+                       /* reschedule the read */
+                       urb->status = 0;
+                       urb->dev = port->serial->dev;
+                       result = usb_submit_urb(urb , GFP_ATOMIC);
+                       if (result)
+                               dev_dbg(&port->dev,
+                                       "failed submitting read urb %d\n",
+                                       result);
+                       return;
+               }
+               dev_dbg(&port->dev, "unable to handle the error, exiting.\n");
+               return;
+       }
+
+       /* get tty_flag from status */
+       tty_flag = TTY_NORMAL;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       status = priv->line_status;
+       priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
+       spin_unlock_irqrestore(&priv->lock, flags);
+       /* wake up the wait for termios */
+       wake_up_interruptible(&priv->delta_msr_wait);
+
+       /* 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;
+       dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);
+
+       tty = port->tty;
+       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)
+                       tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+               for (i = 0; i < urb->actual_length; ++i)
+                       tty_insert_flip_char(tty, data[i], tty_flag);
+               tty_flip_buffer_push(tty);
+       }
+
+       /* Schedule the next read _if_ we are still open */
+       if (port->open_count) {
+               urb->dev = port->serial->dev;
+               result = usb_submit_urb(urb , GFP_ATOMIC);
+               if (result)
+                       dev_dbg(&port->dev, "failed submitting read urb %d\n",
+                               result);
+       }
+
+       return;
+}
+
+/* get data from ring buffer and then write to usb bus */
+static void spcp8x5_send(struct usb_serial_port *port)
+{
+       int count, result;
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->lock, flags);
+
+       if (priv->write_urb_in_use) {
+               dev_dbg(&port->dev, "write urb still used\n");
+               spin_unlock_irqrestore(&priv->lock, flags);
+               return;
+       }
+
+       /* send the 1st urb for writting */
+       memset(port->write_urb->transfer_buffer , 0x00 , port->bulk_out_size);
+       count = get_ringbuf(priv->buf, port->write_urb->transfer_buffer,
+               port->bulk_out_size);
+
+       if (count == 0) {
+               spin_unlock_irqrestore(&priv->lock, flags);
+               return;
+       }
+
+       /* update the urb status */
+       priv->write_urb_in_use = 1;
+
+       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) {
+               dev_dbg(&port->dev, "failed submitting write urb, error %d\n",
+                       result);
+               priv->write_urb_in_use = 0;
+               /* TODO: reschedule spcp8x5_send */
+       }
+
+
+       schedule_work(&port->work);
+}
+
+/* this is the call back function for write urb. NOTE we should not sleep in
+ * this routine. check the urb return code and then submit the write urb again
+ * to hold the write loop */
+static void spcp8x5_write_bulk_callback(struct urb *urb)
+{
+       struct usb_serial_port *port = urb->context;
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       int result;
+
+       switch (urb->status) {
+       case 0:
+               /* success */
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               dev_dbg(&port->dev, "urb shutting down with status: %d\n",
+                       urb->status);
+               priv->write_urb_in_use = 0;
+               return;
+       default:
+               /* error in the urb, so we have to resubmit it */
+               dbg("%s - Overflow in write", __func__);
+               dbg("%s - nonzero write bulk status received: %d",
+                       __func__, urb->status);
+               port->write_urb->transfer_buffer_length = 1;
+               port->write_urb->dev = port->serial->dev;
+               result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+               if (result)
+                       dev_dbg(&port->dev,
+                               "failed resubmitting write urb %d\n", result);
+               else
+                       return;
+       }
+
+       priv->write_urb_in_use = 0;
+
+       /* send any buffered data */
+       spcp8x5_send(port);
+}
+
+/* write data to ring buffer. and then start the write transfer */
+static int spcp8x5_write(struct usb_serial_port *port,
+                        const unsigned char *buf, int count)
+{
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+
+       dev_dbg(&port->dev, "%d bytes\n", count);
+
+       if (!count)
+               return count;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       count = put_ringbuf(priv->buf, buf, count);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       spcp8x5_send(port);
+
+       return count;
+}
+
+static int spcp8x5_wait_modem_info(struct usb_serial_port *port,
+                                  unsigned int arg)
+{
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       unsigned int prevstatus;
+       unsigned int status;
+       unsigned int changed;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       prevstatus = priv->line_status;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       while (1) {
+               /* wake up in bulk read */
+               interruptible_sleep_on(&priv->delta_msr_wait);
+
+               /* see if a signal did it */
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
+
+               spin_lock_irqsave(&priv->lock, flags);
+               status = priv->line_status;
+               spin_unlock_irqrestore(&priv->lock, flags);
+
+               changed = prevstatus^status;
+
+               if (((arg & TIOCM_RNG) && (changed & MSR_STATUS_LINE_RI)) ||
+                   ((arg & TIOCM_DSR) && (changed & MSR_STATUS_LINE_DSR)) ||
+                   ((arg & TIOCM_CD)  && (changed & MSR_STATUS_LINE_DCD)) ||
+                   ((arg & TIOCM_CTS) && (changed & MSR_STATUS_LINE_CTS)))
+                       return 0;
+
+               prevstatus = status;
+       }
+       /* NOTREACHED */
+       return 0;
+}
+
+static int spcp8x5_ioctl(struct usb_serial_port *port, struct file *file,
+                        unsigned int cmd, unsigned long arg)
+{
+       dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
+
+       switch (cmd) {
+       case TIOCMIWAIT:
+               dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
+               return spcp8x5_wait_modem_info(port, arg);
+
+       default:
+               dbg("%s not supported = 0x%04x", __func__, cmd);
+               break;
+       }
+
+       return -ENOIOCTLCMD;
+}
+
+static int spcp8x5_tiocmset(struct usb_serial_port *port, struct file *file,
+                           unsigned int set, unsigned int clear)
+{
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       u8 control;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (set & TIOCM_RTS)
+               priv->line_control |= MCR_RTS;
+       if (set & TIOCM_DTR)
+               priv->line_control |= MCR_DTR;
+       if (clear & TIOCM_RTS)
+               priv->line_control &= ~MCR_RTS;
+       if (clear & TIOCM_DTR)
+               priv->line_control &= ~MCR_DTR;
+       control = priv->line_control;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
+}
+
+static int spcp8x5_tiocmget(struct usb_serial_port *port, struct file *file)
+{
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       unsigned int mcr;
+       unsigned int status;
+       unsigned int result;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       mcr = priv->line_control;
+       status = priv->line_status;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       result = ((mcr & MCR_DTR)                       ? TIOCM_DTR : 0)
+                 | ((mcr & MCR_RTS)                    ? TIOCM_RTS : 0)
+                 | ((status & MSR_STATUS_LINE_CTS)     ? TIOCM_CTS : 0)
+                 | ((status & MSR_STATUS_LINE_DSR)     ? TIOCM_DSR : 0)
+                 | ((status & MSR_STATUS_LINE_RI)      ? TIOCM_RI  : 0)
+                 | ((status & MSR_STATUS_LINE_DCD)     ? TIOCM_CD  : 0);
+
+       return result;
+}
+
+/* get the avail space room in ring buffer */
+static int spcp8x5_write_room(struct usb_serial_port *port)
+{
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       int room = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       room = ringbuf_avail_space(priv->buf);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return room;
+}
+
+/* get the number of avail data in write ring buffer */
+static int spcp8x5_chars_in_buffer(struct usb_serial_port *port)
+{
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       int chars = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       chars = ringbuf_avail_data(priv->buf);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return chars;
+}
+
+/* All of the device info needed for the spcp8x5 SIO serial converter */
+static struct usb_serial_driver spcp8x5_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "SPCP8x5",
+       },
+       .id_table               = id_table,
+       .num_ports              = 1,
+       .open                   = spcp8x5_open,
+       .close                  = spcp8x5_close,
+       .write                  = spcp8x5_write,
+       .set_termios            = spcp8x5_set_termios,
+       .ioctl                  = spcp8x5_ioctl,
+       .tiocmget               = spcp8x5_tiocmget,
+       .tiocmset               = spcp8x5_tiocmset,
+       .write_room             = spcp8x5_write_room,
+       .read_bulk_callback     = spcp8x5_read_bulk_callback,
+       .write_bulk_callback    = spcp8x5_write_bulk_callback,
+       .chars_in_buffer        = spcp8x5_chars_in_buffer,
+       .attach                 = spcp8x5_startup,
+       .shutdown               = spcp8x5_shutdown,
+};
+
+static int __init spcp8x5_init(void)
+{
+       int retval;
+       retval = usb_serial_register(&spcp8x5_device);
+       if (retval)
+               goto failed_usb_serial_register;
+       retval = usb_register(&spcp8x5_driver);
+       if (retval)
+               goto failed_usb_register;
+       info(DRIVER_DESC " " DRIVER_VERSION);
+       return 0;
+failed_usb_register:
+       usb_serial_deregister(&spcp8x5_device);
+failed_usb_serial_register:
+       return retval;
+}
+
+static void __exit spcp8x5_exit(void)
+{
+       usb_deregister(&spcp8x5_driver);
+       usb_serial_deregister(&spcp8x5_device);
+}
+
+module_init(spcp8x5_init);
+module_exit(spcp8x5_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
index 3a3776677339bd7e546ea05a1acc62e0abc3aa85..a1c8aef014171e4334913a79d1f907984dd6b93b 100644 (file)
@@ -264,9 +264,6 @@ static struct usb_serial_driver ti_1port_device = {
        .description            = "TI USB 3410 1 port adapter",
        .usb_driver             = &ti_usb_driver,
        .id_table               = ti_id_table_3410,
-       .num_interrupt_in       = NUM_DONT_CARE,
-       .num_bulk_in            = NUM_DONT_CARE,
-       .num_bulk_out           = 1,
        .num_ports              = 1,
        .attach                 = ti_startup,
        .shutdown               = ti_shutdown,
@@ -295,9 +292,6 @@ static struct usb_serial_driver ti_2port_device = {
        .description            = "TI USB 5052 2 port adapter",
        .usb_driver             = &ti_usb_driver,
        .id_table               = ti_id_table_5052,
-       .num_interrupt_in       = 1,
-       .num_bulk_in            = 2,
-       .num_bulk_out           = 2,
        .num_ports              = 2,
        .attach                 = ti_startup,
        .shutdown               = ti_shutdown,
@@ -414,14 +408,14 @@ static int ti_startup(struct usb_serial *serial)
 
 
        dbg("%s - product 0x%4X, num configurations %d, configuration value %d",
-           __FUNCTION__, le16_to_cpu(dev->descriptor.idProduct),
+           __func__, le16_to_cpu(dev->descriptor.idProduct),
            dev->descriptor.bNumConfigurations,
            dev->actconfig->desc.bConfigurationValue);
 
        /* create device structure */
        tdev = kzalloc(sizeof(struct ti_device), GFP_KERNEL);
        if (tdev == NULL) {
-               dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
+               dev_err(&dev->dev, "%s - out of memory\n", __func__);
                return -ENOMEM;
        }
        mutex_init(&tdev->td_open_close_lock);
@@ -431,7 +425,7 @@ static int ti_startup(struct usb_serial *serial)
        /* determine device type */
        if (usb_match_id(serial->interface, ti_id_table_3410))
                tdev->td_is_3410 = 1;
-       dbg("%s - device type is %s", __FUNCTION__, tdev->td_is_3410 ? "3410" : "5052");
+       dbg("%s - device type is %s", __func__, tdev->td_is_3410 ? "3410" : "5052");
 
        /* if we have only 1 configuration, download firmware */
        if (dev->descriptor.bNumConfigurations == 1) {
@@ -465,7 +459,7 @@ static int ti_startup(struct usb_serial *serial)
        for (i = 0; i < serial->num_ports; ++i) {
                tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL);
                if (tport == NULL) {
-                       dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
+                       dev_err(&dev->dev, "%s - out of memory\n", __func__);
                        status = -ENOMEM;
                        goto free_tports;
                }
@@ -477,7 +471,7 @@ static int ti_startup(struct usb_serial *serial)
                init_waitqueue_head(&tport->tp_write_wait);
                tport->tp_write_buf = ti_buf_alloc();
                if (tport->tp_write_buf == NULL) {
-                       dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
+                       dev_err(&dev->dev, "%s - out of memory\n", __func__);
                        kfree(tport);
                        status = -ENOMEM;
                        goto free_tports;
@@ -510,7 +504,7 @@ static void ti_shutdown(struct usb_serial *serial)
        struct ti_device *tdev = usb_get_serial_data(serial);
        struct ti_port *tport;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        for (i=0; i < serial->num_ports; ++i) {
                tport = usb_get_serial_port_data(serial->port[i]);
@@ -538,7 +532,7 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
                             TI_PIPE_TIMEOUT_ENABLE | 
                             (TI_TRANSFER_TIMEOUT << 2));
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (tport == NULL)
                return -ENODEV;
@@ -563,10 +557,10 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
 
        /* start interrupt urb the first time a port is opened on this device */
        if (tdev->td_open_port_count == 0) {
-               dbg("%s - start interrupt in urb", __FUNCTION__);
+               dbg("%s - start interrupt in urb", __func__);
                urb = tdev->td_serial->port[0]->interrupt_in_urb;
                if (!urb) {
-                       dev_err(&port->dev, "%s - no interrupt urb\n", __FUNCTION__);
+                       dev_err(&port->dev, "%s - no interrupt urb\n", __func__);
                        status = -EINVAL;
                        goto release_lock;
                }
@@ -575,40 +569,40 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
                urb->dev = dev;
                status = usb_submit_urb(urb, GFP_KERNEL);
                if (status) {
-                       dev_err(&port->dev, "%s - submit interrupt urb failed, %d\n", __FUNCTION__, status);
+                       dev_err(&port->dev, "%s - submit interrupt urb failed, %d\n", __func__, status);
                        goto release_lock;
                }
        }
 
        ti_set_termios(port, port->tty->termios);
 
-       dbg("%s - sending TI_OPEN_PORT", __FUNCTION__);
+       dbg("%s - sending TI_OPEN_PORT", __func__);
        status = ti_command_out_sync(tdev, TI_OPEN_PORT,
                (__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
        if (status) {
-               dev_err(&port->dev, "%s - cannot send open command, %d\n", __FUNCTION__, status);
+               dev_err(&port->dev, "%s - cannot send open command, %d\n", __func__, status);
                goto unlink_int_urb;
        }
 
-       dbg("%s - sending TI_START_PORT", __FUNCTION__);
+       dbg("%s - sending TI_START_PORT", __func__);
        status = ti_command_out_sync(tdev, TI_START_PORT,
                (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
        if (status) {
-               dev_err(&port->dev, "%s - cannot send start command, %d\n", __FUNCTION__, status);
+               dev_err(&port->dev, "%s - cannot send start command, %d\n", __func__, status);
                goto unlink_int_urb;
        }
 
-       dbg("%s - sending TI_PURGE_PORT", __FUNCTION__);
+       dbg("%s - sending TI_PURGE_PORT", __func__);
        status = ti_command_out_sync(tdev, TI_PURGE_PORT,
                (__u8)(TI_UART1_PORT + port_number), TI_PURGE_INPUT, NULL, 0);
        if (status) {
-               dev_err(&port->dev, "%s - cannot clear input buffers, %d\n", __FUNCTION__, status);
+               dev_err(&port->dev, "%s - cannot clear input buffers, %d\n", __func__, status);
                goto unlink_int_urb;
        }
        status = ti_command_out_sync(tdev, TI_PURGE_PORT,
                (__u8)(TI_UART1_PORT + port_number), TI_PURGE_OUTPUT, NULL, 0);
        if (status) {
-               dev_err(&port->dev, "%s - cannot clear output buffers, %d\n", __FUNCTION__, status);
+               dev_err(&port->dev, "%s - cannot clear output buffers, %d\n", __func__, status);
                goto unlink_int_urb;
        }
 
@@ -619,27 +613,27 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
 
        ti_set_termios(port, port->tty->termios);
 
-       dbg("%s - sending TI_OPEN_PORT (2)", __FUNCTION__);
+       dbg("%s - sending TI_OPEN_PORT (2)", __func__);
        status = ti_command_out_sync(tdev, TI_OPEN_PORT,
                (__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
        if (status) {
-               dev_err(&port->dev, "%s - cannot send open command (2), %d\n", __FUNCTION__, status);
+               dev_err(&port->dev, "%s - cannot send open command (2), %d\n", __func__, status);
                goto unlink_int_urb;
        }
 
-       dbg("%s - sending TI_START_PORT (2)", __FUNCTION__);
+       dbg("%s - sending TI_START_PORT (2)", __func__);
        status = ti_command_out_sync(tdev, TI_START_PORT,
                (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
        if (status) {
-               dev_err(&port->dev, "%s - cannot send start command (2), %d\n", __FUNCTION__, status);
+               dev_err(&port->dev, "%s - cannot send start command (2), %d\n", __func__, status);
                goto unlink_int_urb;
        }
 
        /* start read urb */
-       dbg("%s - start read urb", __FUNCTION__);
+       dbg("%s - start read urb", __func__);
        urb = port->read_urb;
        if (!urb) {
-               dev_err(&port->dev, "%s - no read urb\n", __FUNCTION__);
+               dev_err(&port->dev, "%s - no read urb\n", __func__);
                status = -EINVAL;
                goto unlink_int_urb;
        }
@@ -649,7 +643,7 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
        urb->dev = dev;
        status = usb_submit_urb(urb, GFP_KERNEL);
        if (status) {
-               dev_err(&port->dev, "%s - submit read urb failed, %d\n", __FUNCTION__, status);
+               dev_err(&port->dev, "%s - submit read urb failed, %d\n", __func__, status);
                goto unlink_int_urb;
        }
 
@@ -663,7 +657,7 @@ unlink_int_urb:
                usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
 release_lock:
        mutex_unlock(&tdev->td_open_close_lock);
-       dbg("%s - exit %d", __FUNCTION__, status);
+       dbg("%s - exit %d", __func__, status);
        return status;
 }
 
@@ -676,7 +670,7 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
        int status;
        int do_unlock;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
                         
        tdev = usb_get_serial_data(port->serial);
        tport = usb_get_serial_port_data(port);
@@ -693,11 +687,11 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
 
        port_number = port->number - port->serial->minor;
 
-       dbg("%s - sending TI_CLOSE_PORT", __FUNCTION__);
+       dbg("%s - sending TI_CLOSE_PORT", __func__);
        status = ti_command_out_sync(tdev, TI_CLOSE_PORT,
                     (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
        if (status)
-               dev_err(&port->dev, "%s - cannot send close port command, %d\n" , __FUNCTION__, status);
+               dev_err(&port->dev, "%s - cannot send close port command, %d\n" , __func__, status);
 
        /* if mutex_lock is interrupted, continue anyway */
        do_unlock = !mutex_lock_interruptible(&tdev->td_open_close_lock);
@@ -710,7 +704,7 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
        if (do_unlock)
                mutex_unlock(&tdev->td_open_close_lock);
 
-       dbg("%s - exit", __FUNCTION__);
+       dbg("%s - exit", __func__);
 }
 
 
@@ -720,10 +714,10 @@ static int ti_write(struct usb_serial_port *port, const unsigned char *data,
        struct ti_port *tport = usb_get_serial_port_data(port);
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (count == 0) {
-               dbg("%s - write request of 0 bytes", __FUNCTION__);
+               dbg("%s - write request of 0 bytes", __func__);
                return 0;
        }
 
@@ -746,7 +740,7 @@ static int ti_write_room(struct usb_serial_port *port)
        int room = 0;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (tport == NULL)
                return -ENODEV;
@@ -755,7 +749,7 @@ static int ti_write_room(struct usb_serial_port *port)
        room = ti_buf_space_avail(tport->tp_write_buf);
        spin_unlock_irqrestore(&tport->tp_lock, flags);
 
-       dbg("%s - returns %d", __FUNCTION__, room);
+       dbg("%s - returns %d", __func__, room);
        return room;
 }
 
@@ -766,7 +760,7 @@ static int ti_chars_in_buffer(struct usb_serial_port *port)
        int chars = 0;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (tport == NULL)
                return -ENODEV;
@@ -775,7 +769,7 @@ static int ti_chars_in_buffer(struct usb_serial_port *port)
        chars = ti_buf_data_avail(tport->tp_write_buf);
        spin_unlock_irqrestore(&tport->tp_lock, flags);
 
-       dbg("%s - returns %d", __FUNCTION__, chars);
+       dbg("%s - returns %d", __func__, chars);
        return chars;
 }
 
@@ -785,14 +779,14 @@ static void ti_throttle(struct usb_serial_port *port)
        struct ti_port *tport = usb_get_serial_port_data(port);
        struct tty_struct *tty;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (tport == NULL)
                return;
 
        tty = port->tty;
        if (!tty) {
-               dbg("%s - no tty", __FUNCTION__);
+               dbg("%s - no tty", __func__);
                return;
        }
 
@@ -808,21 +802,21 @@ static void ti_unthrottle(struct usb_serial_port *port)
        struct tty_struct *tty;
        int status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (tport == NULL)
                return;
 
        tty = port->tty;
        if (!tty) {
-               dbg("%s - no tty", __FUNCTION__);
+               dbg("%s - no tty", __func__);
                return;
        }
 
        if (I_IXOFF(tty) || C_CRTSCTS(tty)) {
                status = ti_restart_read(tport, tty);
                if (status)
-                       dev_err(&port->dev, "%s - cannot restart read, %d\n", __FUNCTION__, status);
+                       dev_err(&port->dev, "%s - cannot restart read, %d\n", __func__, status);
        }
 }
 
@@ -834,24 +828,24 @@ static int ti_ioctl(struct usb_serial_port *port, struct file *file,
        struct async_icount cnow;
        struct async_icount cprev;
 
-       dbg("%s - port %d, cmd = 0x%04X", __FUNCTION__, port->number, cmd);
+       dbg("%s - port %d, cmd = 0x%04X", __func__, port->number, cmd);
 
        if (tport == NULL)
                return -ENODEV;
 
        switch (cmd) {
                case TIOCGSERIAL:
-                       dbg("%s - (%d) TIOCGSERIAL", __FUNCTION__, port->number);
+                       dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
                        return ti_get_serial_info(tport, (struct serial_struct __user *)arg);
                        break;
 
                case TIOCSSERIAL:
-                       dbg("%s - (%d) TIOCSSERIAL", __FUNCTION__, port->number);
+                       dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
                        return ti_set_serial_info(tport, (struct serial_struct __user *)arg);
                        break;
 
                case TIOCMIWAIT:
-                       dbg("%s - (%d) TIOCMIWAIT", __FUNCTION__, port->number);
+                       dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
                        cprev = tport->tp_icount;
                        while (1) {
                                interruptible_sleep_on(&tport->tp_msr_wait);
@@ -872,7 +866,7 @@ static int ti_ioctl(struct usb_serial_port *port, struct file *file,
                        break;
 
                case TIOCGICOUNT:
-                       dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__, port->number, tport->tp_icount.rx, tport->tp_icount.tx);
+                       dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, port->number, tport->tp_icount.rx, tport->tp_icount.tx);
                        if (copy_to_user((void __user *)arg, &tport->tp_icount, sizeof(tport->tp_icount)))
                                return -EFAULT;
                        return 0;
@@ -894,20 +888,20 @@ static void ti_set_termios(struct usb_serial_port *port,
        int port_number = port->number - port->serial->minor;
        unsigned int mcr;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        cflag = tty->termios->c_cflag;
        iflag = tty->termios->c_iflag;
 
-       dbg("%s - cflag %08x, iflag %08x", __FUNCTION__, cflag, iflag);
-       dbg("%s - old clfag %08x, old iflag %08x", __FUNCTION__, old_termios->c_cflag, old_termios->c_iflag);
+       dbg("%s - cflag %08x, iflag %08x", __func__, cflag, iflag);
+       dbg("%s - old clfag %08x, old iflag %08x", __func__, old_termios->c_cflag, old_termios->c_iflag);
 
        if (tport == NULL)
                return;
 
        config = kmalloc(sizeof(*config), GFP_KERNEL);
        if (!config) {
-               dev_err(&port->dev, "%s - out of memory\n", __FUNCTION__);
+               dev_err(&port->dev, "%s - out of memory\n", __func__);
                return;
        }
 
@@ -991,7 +985,7 @@ static void ti_set_termios(struct usb_serial_port *port,
                tty_encode_baud_rate(tty, baud, baud);
 
        dbg("%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d",
-       __FUNCTION__, baud, config->wBaudRate, config->wFlags, config->bDataBits, config->bParity, config->bStopBits, config->cXon, config->cXoff, config->bUartMode);
+       __func__, baud, config->wBaudRate, config->wFlags, config->bDataBits, config->bParity, config->bStopBits, config->cXon, config->cXoff, config->bUartMode);
 
        cpu_to_be16s(&config->wBaudRate);
        cpu_to_be16s(&config->wFlags);
@@ -1000,7 +994,7 @@ static void ti_set_termios(struct usb_serial_port *port,
                (__u8)(TI_UART1_PORT + port_number), 0, (__u8 *)config,
                sizeof(*config));
        if (status)
-               dev_err(&port->dev, "%s - cannot set config on port %d, %d\n", __FUNCTION__, port_number, status);
+               dev_err(&port->dev, "%s - cannot set config on port %d, %d\n", __func__, port_number, status);
 
        /* SET_CONFIG asserts RTS and DTR, reset them correctly */
        mcr = tport->tp_shadow_mcr;
@@ -1009,7 +1003,7 @@ static void ti_set_termios(struct usb_serial_port *port,
                mcr &= ~(TI_MCR_DTR | TI_MCR_RTS);
        status = ti_set_mcr(tport, mcr);
        if (status)
-               dev_err(&port->dev, "%s - cannot set modem control on port %d, %d\n", __FUNCTION__, port_number, status);
+               dev_err(&port->dev, "%s - cannot set modem control on port %d, %d\n", __func__, port_number, status);
 
        kfree(config);
 }
@@ -1021,14 +1015,17 @@ static int ti_tiocmget(struct usb_serial_port *port, struct file *file)
        unsigned int result;
        unsigned int msr;
        unsigned int mcr;
+       unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (tport == NULL)
                return -ENODEV;
 
+       spin_lock_irqsave(&tport->tp_lock, flags);
        msr = tport->tp_msr;
        mcr = tport->tp_shadow_mcr;
+       spin_unlock_irqrestore(&tport->tp_lock, flags);
 
        result = ((mcr & TI_MCR_DTR) ? TIOCM_DTR : 0)
                | ((mcr & TI_MCR_RTS) ? TIOCM_RTS : 0)
@@ -1038,7 +1035,7 @@ static int ti_tiocmget(struct usb_serial_port *port, struct file *file)
                | ((msr & TI_MSR_RI) ? TIOCM_RI : 0)
                | ((msr & TI_MSR_DSR) ? TIOCM_DSR : 0);
 
-       dbg("%s - 0x%04X", __FUNCTION__, result);
+       dbg("%s - 0x%04X", __func__, result);
 
        return result;
 }
@@ -1049,12 +1046,14 @@ static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
 {
        struct ti_port *tport = usb_get_serial_port_data(port);
        unsigned int mcr;
+       unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (tport == NULL)
                return -ENODEV;
 
+       spin_lock_irqsave(&tport->tp_lock, flags);
        mcr = tport->tp_shadow_mcr;
 
        if (set & TIOCM_RTS)
@@ -1070,6 +1069,7 @@ static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
                mcr &= ~TI_MCR_DTR;
        if (clear & TIOCM_LOOP)
                mcr &= ~TI_MCR_LOOP;
+       spin_unlock_irqrestore(&tport->tp_lock, flags);
 
        return ti_set_mcr(tport, mcr);
 }
@@ -1080,7 +1080,7 @@ static void ti_break(struct usb_serial_port *port, int break_state)
        struct ti_port *tport = usb_get_serial_port_data(port);
        int status;
 
-       dbg("%s - state = %d", __FUNCTION__, break_state);
+       dbg("%s - state = %d", __func__, break_state);
 
        if (tport == NULL)
                return;
@@ -1092,13 +1092,13 @@ static void ti_break(struct usb_serial_port *port, int break_state)
                TI_LCR_BREAK, break_state == -1 ? TI_LCR_BREAK : 0);
 
        if (status)
-               dbg("%s - error setting break, %d", __FUNCTION__, status);
+               dbg("%s - error setting break, %d", __func__, status);
 }
 
 
 static void ti_interrupt_callback(struct urb *urb)
 {
-       struct ti_device *tdev = (struct ti_device *)urb->context;
+       struct ti_device *tdev = urb->context;
        struct usb_serial_port *port;
        struct usb_serial *serial = tdev->td_serial;
        struct ti_port *tport;
@@ -1111,7 +1111,7 @@ static void ti_interrupt_callback(struct urb *urb)
        int retval;
        __u8 msr;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        switch (status) {
        case 0:
@@ -1119,33 +1119,33 @@ static void ti_interrupt_callback(struct urb *urb)
        case -ECONNRESET:
        case -ENOENT:
        case -ESHUTDOWN:
-               dbg("%s - urb shutting down, %d", __FUNCTION__, status);
+               dbg("%s - urb shutting down, %d", __func__, status);
                tdev->td_urb_error = 1;
                return;
        default:
                dev_err(dev, "%s - nonzero urb status, %d\n",
-                       __FUNCTION__, status);
+                       __func__, status);
                tdev->td_urb_error = 1;
                goto exit;
        }
 
        if (length != 2) {
-               dbg("%s - bad packet size, %d", __FUNCTION__, length);
+               dbg("%s - bad packet size, %d", __func__, length);
                goto exit;
        }
 
        if (data[0] == TI_CODE_HARDWARE_ERROR) {
-               dev_err(dev, "%s - hardware error, %d\n", __FUNCTION__, data[1]);
+               dev_err(dev, "%s - hardware error, %d\n", __func__, data[1]);
                goto exit;
        }
 
        port_number = TI_GET_PORT_FROM_CODE(data[0]);
        function = TI_GET_FUNC_FROM_CODE(data[0]);
 
-       dbg("%s - port_number %d, function %d, data 0x%02X", __FUNCTION__, port_number, function, data[1]);
+       dbg("%s - port_number %d, function %d, data 0x%02X", __func__, port_number, function, data[1]);
 
        if (port_number >= serial->num_ports) {
-               dev_err(dev, "%s - bad port number, %d\n", __FUNCTION__, port_number);
+               dev_err(dev, "%s - bad port number, %d\n", __func__, port_number);
                goto exit;
        }
 
@@ -1157,17 +1157,17 @@ static void ti_interrupt_callback(struct urb *urb)
 
        switch (function) {
        case TI_CODE_DATA_ERROR:
-               dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n", __FUNCTION__, port_number, data[1]);
+               dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n", __func__, port_number, data[1]);
                break;
 
        case TI_CODE_MODEM_STATUS:
                msr = data[1];
-               dbg("%s - port %d, msr 0x%02X", __FUNCTION__, port_number, msr);
+               dbg("%s - port %d, msr 0x%02X", __func__, port_number, msr);
                ti_handle_new_msr(tport, msr);
                break;
 
        default:
-               dev_err(dev, "%s - unknown interrupt code, 0x%02X\n", __FUNCTION__, data[1]);
+               dev_err(dev, "%s - unknown interrupt code, 0x%02X\n", __func__, data[1]);
                break;
        }
 
@@ -1175,19 +1175,19 @@ exit:
        retval = usb_submit_urb(urb, GFP_ATOMIC);
        if (retval)
                dev_err(dev, "%s - resubmit interrupt urb failed, %d\n",
-                       __FUNCTION__, retval);
+                       __func__, retval);
 }
 
 
 static void ti_bulk_in_callback(struct urb *urb)
 {
-       struct ti_port *tport = (struct ti_port *)urb->context;
+       struct ti_port *tport = urb->context;
        struct usb_serial_port *port = tport->tp_port;
        struct device *dev = &urb->dev->dev;
        int status = urb->status;
        int retval = 0;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        switch (status) {
        case 0:
@@ -1195,13 +1195,13 @@ static void ti_bulk_in_callback(struct urb *urb)
        case -ECONNRESET:
        case -ENOENT:
        case -ESHUTDOWN:
-               dbg("%s - urb shutting down, %d", __FUNCTION__, status);
+               dbg("%s - urb shutting down, %d", __func__, 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__, status );
+                       __func__, status );
                tport->tp_tdev->td_urb_error = 1;
                wake_up_interruptible(&tport->tp_write_wait);
        }
@@ -1210,16 +1210,16 @@ static void ti_bulk_in_callback(struct urb *urb)
                goto exit;
 
        if (status) {
-               dev_err(dev, "%s - stopping read!\n", __FUNCTION__);
+               dev_err(dev, "%s - stopping read!\n", __func__);
                return;
        }
 
        if (port->tty && urb->actual_length) {
-               usb_serial_debug_data(debug, dev, __FUNCTION__,
+               usb_serial_debug_data(debug, dev, __func__,
                        urb->actual_length, urb->transfer_buffer);
 
                if (!tport->tp_is_open)
-                       dbg("%s - port closed, dropping data", __FUNCTION__);
+                       dbg("%s - port closed, dropping data", __func__);
                else
                        ti_recv(&urb->dev->dev, port->tty, urb->transfer_buffer,
                                urb->actual_length);
@@ -1241,18 +1241,18 @@ exit:
        spin_unlock(&tport->tp_lock);
        if (retval)
                dev_err(dev, "%s - resubmit read urb failed, %d\n",
-                       __FUNCTION__, retval);
+                       __func__, retval);
 }
 
 
 static void ti_bulk_out_callback(struct urb *urb)
 {
-       struct ti_port *tport = (struct ti_port *)urb->context;
+       struct ti_port *tport = 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);
+       dbg("%s - port %d", __func__, port->number);
 
        tport->tp_write_urb_in_use = 0;
 
@@ -1262,13 +1262,13 @@ static void ti_bulk_out_callback(struct urb *urb)
        case -ECONNRESET:
        case -ENOENT:
        case -ESHUTDOWN:
-               dbg("%s - urb shutting down, %d", __FUNCTION__, status);
+               dbg("%s - urb shutting down, %d", __func__, 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__, status);
+                       __func__, status);
                tport->tp_tdev->td_urb_error = 1;
                wake_up_interruptible(&tport->tp_write_wait);
        }
@@ -1286,7 +1286,7 @@ static void ti_recv(struct device *dev, struct tty_struct *tty,
        do {
                cnt = tty_buffer_request_room(tty, length);
                if (cnt < length) {
-                       dev_err(dev, "%s - dropping data, %d bytes lost\n", __FUNCTION__, length - cnt);
+                       dev_err(dev, "%s - dropping data, %d bytes lost\n", __func__, length - cnt);
                        if(cnt == 0)
                                break;
                }
@@ -1307,7 +1307,7 @@ static void ti_send(struct ti_port *tport)
        unsigned long flags;
 
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&tport->tp_lock, flags);
 
@@ -1329,7 +1329,7 @@ static void ti_send(struct ti_port *tport)
 
        spin_unlock_irqrestore(&tport->tp_lock, flags);
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer);
+       usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer);
 
        usb_fill_bulk_urb(port->write_urb, port->serial->dev,
                           usb_sndbulkpipe(port->serial->dev,
@@ -1339,7 +1339,7 @@ static void ti_send(struct ti_port *tport)
 
        result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
        if (result) {
-               dev_err(&port->dev, "%s - submit write urb failed, %d\n", __FUNCTION__, result);
+               dev_err(&port->dev, "%s - submit write urb failed, %d\n", __func__, result);
                tport->tp_write_urb_in_use = 0; 
                /* TODO: reschedule ti_send */
        } else {
@@ -1357,14 +1357,17 @@ static void ti_send(struct ti_port *tport)
 
 static int ti_set_mcr(struct ti_port *tport, unsigned int mcr)
 {
+       unsigned long flags;
        int status;
 
        status = ti_write_byte(tport->tp_tdev,
                tport->tp_uart_base_addr + TI_UART_OFFSET_MCR,
                TI_MCR_RTS | TI_MCR_DTR | TI_MCR_LOOP, mcr);
 
+       spin_lock_irqsave(&tport->tp_lock, flags);
        if (!status)
                tport->tp_shadow_mcr = mcr;
+       spin_unlock_irqrestore(&tport->tp_lock, flags);
 
        return status;
 }
@@ -1378,23 +1381,23 @@ static int ti_get_lsr(struct ti_port *tport)
        int port_number = port->number - port->serial->minor;
        struct ti_port_status *data;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        size = sizeof(struct ti_port_status);
        data = kmalloc(size, GFP_KERNEL);
        if (!data) {
-               dev_err(&port->dev, "%s - out of memory\n", __FUNCTION__);
+               dev_err(&port->dev, "%s - out of memory\n", __func__);
                return -ENOMEM;
        }
 
        status = ti_command_in_sync(tdev, TI_GET_PORT_STATUS,
                (__u8)(TI_UART1_PORT+port_number), 0, (__u8 *)data, size);
        if (status) {
-               dev_err(&port->dev, "%s - get port status command failed, %d\n", __FUNCTION__, status);
+               dev_err(&port->dev, "%s - get port status command failed, %d\n", __func__, status);
                goto free_data;
        }
 
-       dbg("%s - lsr 0x%02X", __FUNCTION__, data->bLSR);
+       dbg("%s - lsr 0x%02X", __func__, data->bLSR);
 
        tport->tp_lsr = data->bLSR;
 
@@ -1455,7 +1458,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
        struct tty_struct *tty;
        unsigned long flags;
 
-       dbg("%s - msr 0x%02X", __FUNCTION__, msr);
+       dbg("%s - msr 0x%02X", __func__, msr);
 
        if (msr & TI_MSR_DELTA_MASK) {
                spin_lock_irqsave(&tport->tp_lock, flags);
@@ -1493,7 +1496,7 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush)
        struct usb_serial_port *port = tport->tp_port;
        wait_queue_t wait;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irq(&tport->tp_lock);
 
@@ -1625,12 +1628,12 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
        struct ti_write_data_bytes *data;
        struct device *dev = &tdev->td_serial->dev->dev;
 
-       dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X", __FUNCTION__, addr, mask, byte);
+       dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X", __func__, addr, mask, byte);
 
        size = sizeof(struct ti_write_data_bytes) + 2;
        data = kmalloc(size, GFP_KERNEL);
        if (!data) {
-               dev_err(dev, "%s - out of memory\n", __FUNCTION__);
+               dev_err(dev, "%s - out of memory\n", __func__);
                return -ENOMEM;
        }
 
@@ -1646,7 +1649,7 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
                (__u8 *)data, size);
 
        if (status < 0)
-               dev_err(dev, "%s - failed, %d\n", __FUNCTION__, status);
+               dev_err(dev, "%s - failed, %d\n", __func__, status);
 
        kfree(data);
 
@@ -1673,7 +1676,7 @@ static int ti_download_firmware(struct ti_device *tdev,
        buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header);
        buffer = kmalloc(buffer_size, GFP_KERNEL);
        if (!buffer) {
-               dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
+               dev_err(&dev->dev, "%s - out of memory\n", __func__);
                return -ENOMEM;
        }
 
@@ -1687,7 +1690,7 @@ static int ti_download_firmware(struct ti_device *tdev,
        header->wLength = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_firmware_header)));
        header->bCheckSum = cs;
 
-       dbg("%s - downloading firmware", __FUNCTION__);
+       dbg("%s - downloading firmware", __func__);
        for (pos = 0; pos < buffer_size; pos += done) {
                len = min(buffer_size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE);
                status = usb_bulk_msg(dev, pipe, buffer+pos, len, &done, 1000);
@@ -1698,11 +1701,11 @@ static int ti_download_firmware(struct ti_device *tdev,
        kfree(buffer);
 
        if (status) {
-               dev_err(&dev->dev, "%s - error downloading firmware, %d\n", __FUNCTION__, status);
+               dev_err(&dev->dev, "%s - error downloading firmware, %d\n", __func__, status);
                return status;
        }
 
-       dbg("%s - download successful", __FUNCTION__);
+       dbg("%s - download successful", __func__);
 
        return 0;
 }
index 2138ba8aeb697b2e35ee04d5e62e6f008bdb0c47..a9934a3f984591700cfa64e8dce7d31900035c64 100644 (file)
@@ -81,7 +81,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
        unsigned int i, j;
        int good_spot;
 
-       dbg("%s %d", __FUNCTION__, num_ports);
+       dbg("%s %d", __func__, num_ports);
 
        *minor = 0;
        mutex_lock(&table_lock);
@@ -101,7 +101,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
 
                *minor = i;
                j = 0;
-               dbg("%s - minor base = %d", __FUNCTION__, *minor);
+               dbg("%s - minor base = %d", __func__, *minor);
                for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
                        serial_table[i] = serial;
                        serial->port[j++]->number = i;
@@ -117,7 +117,7 @@ static void return_serial(struct usb_serial *serial)
 {
        int i;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        if (serial == NULL)
                return;
@@ -135,7 +135,7 @@ static void destroy_serial(struct kref *kref)
 
        serial = to_usb_serial(kref);
 
-       dbg("%s - %s", __FUNCTION__, serial->type->description);
+       dbg("%s - %s", __func__, serial->type->description);
 
        serial->type->shutdown(serial);
 
@@ -187,7 +187,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
        unsigned int portNumber;
        int retval;
        
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /* get the serial object associated with this tty pointer */
        serial = usb_serial_get_by_index(tty->index);
@@ -259,7 +259,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
        if (!port)
                return;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        mutex_lock(&port->mutex);
 
@@ -299,11 +299,11 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int
        if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
                goto exit;
 
-       dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
+       dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
 
        if (!port->open_count) {
                retval = -EINVAL;
-               dbg("%s - port not opened", __FUNCTION__);
+               dbg("%s - port not opened", __func__);
                goto exit;
        }
 
@@ -322,10 +322,10 @@ static int serial_write_room (struct tty_struct *tty)
        if (!port)
                goto exit;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (!port->open_count) {
-               dbg("%s - port not open", __FUNCTION__);
+               dbg("%s - port not open", __func__);
                goto exit;
        }
 
@@ -344,10 +344,10 @@ static int serial_chars_in_buffer (struct tty_struct *tty)
        if (!port)
                goto exit;
 
-       dbg("%s = port %d", __FUNCTION__, port->number);
+       dbg("%s = port %d", __func__, port->number);
 
        if (!port->open_count) {
-               dbg("%s - port not open", __FUNCTION__);
+               dbg("%s - port not open", __func__);
                goto exit;
        }
 
@@ -365,10 +365,10 @@ static void serial_throttle (struct tty_struct * tty)
        if (!port)
                return;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (!port->open_count) {
-               dbg ("%s - port not open", __FUNCTION__);
+               dbg ("%s - port not open", __func__);
                return;
        }
 
@@ -384,10 +384,10 @@ static void serial_unthrottle (struct tty_struct * tty)
        if (!port)
                return;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (!port->open_count) {
-               dbg("%s - port not open", __FUNCTION__);
+               dbg("%s - port not open", __func__);
                return;
        }
 
@@ -401,13 +401,15 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in
        struct usb_serial_port *port = tty->driver_data;
        int retval = -ENODEV;
 
+       lock_kernel();
        if (!port)
                goto exit;
 
-       dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
+       dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
 
+       /* Caution - port->open_count is BKL protected */
        if (!port->open_count) {
-               dbg ("%s - port not open", __FUNCTION__);
+               dbg ("%s - port not open", __func__);
                goto exit;
        }
 
@@ -416,8 +418,8 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in
                retval = port->serial->type->ioctl(port, file, cmd, arg);
        else
                retval = -ENOIOCTLCMD;
-
 exit:
+       unlock_kernel();
        return retval;
 }
 
@@ -428,10 +430,10 @@ static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
        if (!port)
                return;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (!port->open_count) {
-               dbg("%s - port not open", __FUNCTION__);
+               dbg("%s - port not open", __func__);
                return;
        }
 
@@ -446,19 +448,24 @@ static void serial_break (struct tty_struct *tty, int break_state)
 {
        struct usb_serial_port *port = tty->driver_data;
 
-       if (!port)
+       lock_kernel();
+       if (!port) {
+               unlock_kernel();
                return;
+       }
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (!port->open_count) {
-               dbg("%s - port not open", __FUNCTION__);
+               dbg("%s - port not open", __func__);
+               unlock_kernel();
                return;
        }
 
        /* pass on to the driver specific version of this function if it is available */
        if (port->serial->type->break_ctl)
                port->serial->type->break_ctl(port, break_state);
+       unlock_kernel();
 }
 
 static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
@@ -469,7 +476,7 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int
        off_t begin = 0;
        char tmp[40];
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
        length += sprintf (page, "usbserinfo:1.0 driver:2.0\n");
        for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
                serial = usb_serial_get_by_index(i);
@@ -515,10 +522,10 @@ static int serial_tiocmget (struct tty_struct *tty, struct file *file)
        if (!port)
                return -ENODEV;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (!port->open_count) {
-               dbg("%s - port not open", __FUNCTION__);
+               dbg("%s - port not open", __func__);
                return -ENODEV;
        }
 
@@ -536,10 +543,10 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file,
        if (!port)
                return -ENODEV;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (!port->open_count) {
-               dbg("%s - port not open", __FUNCTION__);
+               dbg("%s - port not open", __func__);
                return -ENODEV;
        }
 
@@ -565,7 +572,7 @@ static void usb_serial_port_work(struct work_struct *work)
                container_of(work, struct usb_serial_port, work);
        struct tty_struct *tty;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
        
        if (!port)
                return;
@@ -581,7 +588,7 @@ static void port_release(struct device *dev)
 {
        struct usb_serial_port *port = to_usb_serial_port(dev);
 
-       dbg ("%s - %s", __FUNCTION__, dev->bus_id);
+       dbg ("%s - %s", __func__, dev->bus_id);
        port_free(port);
 }
 
@@ -627,7 +634,7 @@ static struct usb_serial * create_serial (struct usb_device *dev,
 
        serial = kzalloc(sizeof(*serial), GFP_KERNEL);
        if (!serial) {
-               dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
+               dev_err(&dev->dev, "%s - out of memory\n", __func__);
                return NULL;
        }
        serial->dev = usb_get_dev(dev);
@@ -722,7 +729,7 @@ int usb_serial_probe(struct usb_interface *interface,
        serial = create_serial (dev, interface, type);
        if (!serial) {
                unlock_kernel();
-               dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__);
+               dev_err(&interface->dev, "%s - out of memory\n", __func__);
                return -ENOMEM;
        }
 
@@ -854,22 +861,6 @@ int usb_serial_probe(struct usb_interface *interface,
        serial->num_interrupt_in = num_interrupt_in;
        serial->num_interrupt_out = num_interrupt_out;
 
-#if 0
-       /* check that the device meets the driver's requirements */
-       if ((type->num_interrupt_in != NUM_DONT_CARE &&
-                               type->num_interrupt_in != num_interrupt_in)
-                       || (type->num_interrupt_out != NUM_DONT_CARE &&
-                               type->num_interrupt_out != num_interrupt_out)
-                       || (type->num_bulk_in != NUM_DONT_CARE &&
-                               type->num_bulk_in != num_bulk_in)
-                       || (type->num_bulk_out != NUM_DONT_CARE &&
-                               type->num_bulk_out != num_bulk_out)) {
-               dbg("wrong number of endpoints");
-               kfree(serial);
-               return -EIO;
-       }
-#endif
-
        /* found all that we need */
        dev_info(&interface->dev, "%s converter detected\n",
                        type->description);
@@ -883,7 +874,7 @@ int usb_serial_probe(struct usb_interface *interface,
        serial->num_port_pointers = max_endpoints;
        unlock_kernel();
 
-       dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints);
+       dbg("%s - setting up %d port structures for this device", __func__, max_endpoints);
        for (i = 0; i < max_endpoints; ++i) {
                port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
                if (!port)
@@ -1031,7 +1022,7 @@ int usb_serial_probe(struct usb_interface *interface,
                port->dev.release = &port_release;
 
                snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number);
-               dbg ("%s - registering %s", __FUNCTION__, port->dev.bus_id);
+               dbg ("%s - registering %s", __func__, port->dev.bus_id);
                retval = device_register(&port->dev);
                if (retval)
                        dev_err(&port->dev, "Error registering port device, "
@@ -1090,7 +1081,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
        struct usb_serial_port *port;
 
        usb_serial_console_disconnect(serial);
-       dbg ("%s", __FUNCTION__);
+       dbg ("%s", __func__);
 
        mutex_lock(&serial->disc_mutex);
        usb_set_intfdata (interface, NULL);
@@ -1174,7 +1165,7 @@ static int __init usb_serial_init(void)
 
        result = bus_register(&usb_serial_bus_type);
        if (result) {
-               err("%s - registering bus driver failed", __FUNCTION__);
+               err("%s - registering bus driver failed", __func__);
                goto exit_bus;
        }
 
@@ -1188,24 +1179,26 @@ static int __init usb_serial_init(void)
        usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
        usb_serial_tty_driver->init_termios = tty_std_termios;
        usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       usb_serial_tty_driver->init_termios.c_ispeed = 9600;
+       usb_serial_tty_driver->init_termios.c_ospeed = 9600;
        tty_set_operations(usb_serial_tty_driver, &serial_ops);
        result = tty_register_driver(usb_serial_tty_driver);
        if (result) {
-               err("%s - tty_register_driver failed", __FUNCTION__);
+               err("%s - tty_register_driver failed", __func__);
                goto exit_reg_driver;
        }
 
        /* register the USB driver */
        result = usb_register(&usb_serial_driver);
        if (result < 0) {
-               err("%s - usb_register failed", __FUNCTION__);
+               err("%s - usb_register failed", __func__);
                goto exit_tty;
        }
 
        /* register the generic driver, if we should */
        result = usb_serial_generic_register(debug);
        if (result < 0) {
-               err("%s - registering generic driver failed", __FUNCTION__);
+               err("%s - registering generic driver failed", __func__);
                goto exit_generic;
        }
 
@@ -1223,7 +1216,7 @@ exit_reg_driver:
        bus_unregister(&usb_serial_bus_type);
 
 exit_bus:
-       err ("%s - returning with error %d", __FUNCTION__, result);
+       err ("%s - returning with error %d", __func__, result);
        put_tty_driver(usb_serial_tty_driver);
        return result;
 }
index 257a5e4368731ef66f88144399f46c96d57e7365..f9fc926b56d87896577280da6c7d8b39d6b10cc6 100644 (file)
@@ -35,9 +35,6 @@ static struct usb_serial_driver debug_device = {
                .name =         "debug",
        },
        .id_table =             id_table,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          NUM_DONT_CARE,
-       .num_bulk_out =         NUM_DONT_CARE,
        .num_ports =            1,
 };
 
index c2b01f7c3197ad0f74ebac9f14b21d71c00d04f5..5fc20122145f3a31dbd4038377e27680fc0a2f93 100644 (file)
@@ -189,9 +189,6 @@ static struct usb_serial_driver handspring_device = {
        .description =          "Handspring Visor / Palm OS",
        .usb_driver =           &visor_driver,
        .id_table =             id_table,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          2,
-       .num_bulk_out =         NUM_DONT_CARE,
        .num_ports =            2,
        .open =                 visor_open,
        .close =                visor_close,
@@ -219,9 +216,6 @@ static struct usb_serial_driver clie_5_device = {
        .description =          "Sony Clie 5.0",
        .usb_driver =           &visor_driver,
        .id_table =             clie_id_5_table,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          2,
-       .num_bulk_out =         2,
        .num_ports =            2,
        .open =                 visor_open,
        .close =                visor_close,
@@ -249,9 +243,6 @@ static struct usb_serial_driver clie_3_5_device = {
        .description =          "Sony Clie 3.5",
        .usb_driver =           &visor_driver,
        .id_table =             clie_id_3_5_table,
-       .num_interrupt_in =     0,
-       .num_bulk_in =          1,
-       .num_bulk_out =         1,
        .num_ports =            1,
        .open =                 visor_open,
        .close =                visor_close,
@@ -290,7 +281,7 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
        unsigned long flags;
        int result = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (!port->read_urb) {
                /* this is needed for some brain dead Sony devices */
@@ -322,16 +313,16 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
        result = usb_submit_urb(port->read_urb, GFP_KERNEL);
        if (result) {
                dev_err(&port->dev, "%s - failed submitting read urb, error %d\n",
-                       __FUNCTION__, result);
+                       __func__, result);
                goto exit;
        }
        
        if (port->interrupt_in_urb) {
-               dbg("%s - adding interrupt input for treo", __FUNCTION__);
+               dbg("%s - adding interrupt input for treo", __func__);
                result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
                if (result)
                        dev_err(&port->dev, "%s - failed submitting interrupt urb, error %d\n",
-                               __FUNCTION__, result);
+                               __func__, result);
        }
 exit:  
        return result;
@@ -343,7 +334,7 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
        struct visor_private *priv = usb_get_serial_port_data(port);
        unsigned char *transfer_buffer;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
                         
        /* shutdown our urbs */
        usb_kill_urb(port->read_urb);
@@ -379,12 +370,12 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
        unsigned long flags;
        int status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
        if (priv->outstanding_urbs > URB_UPPER_LIMIT) {
                spin_unlock_irqrestore(&priv->lock, flags);
-               dbg("%s - write limit hit\n", __FUNCTION__);
+               dbg("%s - write limit hit\n", __func__);
                return 0;
        }
        priv->outstanding_urbs++;
@@ -406,7 +397,7 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
 
        memcpy (buffer, buf, count);
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
+       usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
 
        usb_fill_bulk_urb (urb, serial->dev,
                           usb_sndbulkpipe (serial->dev,
@@ -418,7 +409,7 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
        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);
+                       __func__, status);
                count = status;
                goto error;
        } else {
@@ -449,7 +440,7 @@ static int visor_write_room (struct usb_serial_port *port)
        struct visor_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /*
         * We really can take anything the user throws at us
@@ -460,7 +451,7 @@ static int visor_write_room (struct usb_serial_port *port)
        spin_lock_irqsave(&priv->lock, flags);
        if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) {
                spin_unlock_irqrestore(&priv->lock, flags);
-               dbg("%s - write limit hit\n", __FUNCTION__);
+               dbg("%s - write limit hit\n", __func__);
                return 0;
        }
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -471,13 +462,15 @@ static int visor_write_room (struct usb_serial_port *port)
 
 static int visor_chars_in_buffer (struct usb_serial_port *port)
 {
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /* 
         * We can't really account for how much data we
         * have sent out, but hasn't made it through to the
         * device, so just tell the tty layer that everything
         * is flushed.
+        *
+        * FIXME: Should walk outstanding_urbs
         */
        return 0;
 }
@@ -485,7 +478,7 @@ static int visor_chars_in_buffer (struct usb_serial_port *port)
 
 static void visor_write_bulk_callback (struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct visor_private *priv = usb_get_serial_port_data(port);
        int status = urb->status;
        unsigned long flags;
@@ -493,11 +486,11 @@ static void visor_write_bulk_callback (struct urb *urb)
        /* free up the transfer buffer, as usb_free_urb() does not do this */
        kfree (urb->transfer_buffer);
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (status)
                dbg("%s - nonzero write bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
 
        spin_lock_irqsave(&priv->lock, flags);
        --priv->outstanding_urbs;
@@ -509,7 +502,7 @@ static void visor_write_bulk_callback (struct urb *urb)
 
 static void visor_read_bulk_callback (struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        struct visor_private *priv = usb_get_serial_port_data(port);
        unsigned char *data = urb->transfer_buffer;
        int status = urb->status;
@@ -517,15 +510,15 @@ static void visor_read_bulk_callback (struct urb *urb)
        int result;
        int available_room;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (status) {
                dbg("%s - nonzero read bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+       usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
 
        tty = port->tty;
        if (tty && urb->actual_length) {
@@ -551,7 +544,7 @@ static void visor_read_bulk_callback (struct urb *urb)
                                   visor_read_bulk_callback, port);
                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);
+                       dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
        } else {
                priv->actually_throttled = 1;
        }
@@ -560,7 +553,7 @@ static void visor_read_bulk_callback (struct urb *urb)
 
 static void visor_read_int_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;
        int result;
 
@@ -573,11 +566,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__, status);
+                   __func__, status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                goto exit;
        }
 
@@ -588,14 +581,14 @@ static void visor_read_int_callback (struct urb *urb)
         * Rumor has it this endpoint is used to notify when data
         * is ready to be read from the bulk ones.
         */
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+       usb_serial_debug_data(debug, &port->dev, __func__,
                              urb->actual_length, urb->transfer_buffer);
 
 exit:
        result = usb_submit_urb (urb, GFP_ATOMIC);
        if (result)
                dev_err(&urb->dev->dev, "%s - Error %d submitting interrupt urb\n",
-                       __FUNCTION__, result);
+                       __func__, result);
 }
 
 static void visor_throttle (struct usb_serial_port *port)
@@ -603,7 +596,7 @@ static void visor_throttle (struct usb_serial_port *port)
        struct visor_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
        spin_lock_irqsave(&priv->lock, flags);
        priv->throttled = 1;
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -616,7 +609,7 @@ static void visor_unthrottle (struct usb_serial_port *port)
        unsigned long flags;
        int result;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
        spin_lock_irqsave(&priv->lock, flags);
        priv->throttled = 0;
        priv->actually_throttled = 0;
@@ -625,7 +618,7 @@ static void visor_unthrottle (struct usb_serial_port *port)
        port->read_urb->dev = port->serial->dev;
        result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
        if (result)
-               dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
+               dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
 }
 
 static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id)
@@ -638,11 +631,11 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
        int i;
        int num_ports = 0;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        transfer_buffer = kmalloc (sizeof (*connection_info), GFP_KERNEL);
        if (!transfer_buffer) {
-               dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __FUNCTION__,
+               dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
                        sizeof(*connection_info));
                return -ENOMEM;
        }
@@ -655,7 +648,7 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
                                  sizeof(*connection_info), 300);
        if (retval < 0) {
                dev_err(dev, "%s - error %d getting connection information\n",
-                       __FUNCTION__, retval);
+                       __func__, retval);
                goto exit;
        }
 
@@ -715,7 +708,7 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
                                  0x02, 300);
        if (retval < 0)
                dev_err(dev, "%s - error %d getting bytes available request\n",
-                       __FUNCTION__, retval);
+                       __func__, retval);
        retval = 0;
 
 exit:
@@ -731,11 +724,11 @@ static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_i
        unsigned char *transfer_buffer;
        int retval;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        transfer_buffer =  kmalloc (sizeof (*connection_info), GFP_KERNEL);
        if (!transfer_buffer) {
-               dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __FUNCTION__,
+               dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
                        sizeof(*connection_info));
                return -ENOMEM;
        }
@@ -747,9 +740,9 @@ static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_i
                                  sizeof (*connection_info), 300);
        if (retval < 0)
                dev_err(dev, "%s - error %d getting connection info\n",
-                       __FUNCTION__, retval);
+                       __func__, retval);
        else
-               usb_serial_debug_data(debug, &serial->dev->dev, __FUNCTION__,
+               usb_serial_debug_data(debug, &serial->dev->dev, __func__,
                                      retval, transfer_buffer);
 
        kfree (transfer_buffer);
@@ -762,7 +755,7 @@ static int visor_probe (struct usb_serial *serial, const struct usb_device_id *i
        int retval = 0;
        int (*startup) (struct usb_serial *serial, const struct usb_device_id *id);
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
                err("active config #%d != 1 ??",
@@ -816,7 +809,7 @@ static int clie_3_5_startup (struct usb_serial *serial)
        int result;
        u8 data;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /*
         * Note that PEG-300 series devices expect the following two calls.
@@ -827,11 +820,11 @@ static int clie_3_5_startup (struct usb_serial *serial)
                                  USB_REQ_GET_CONFIGURATION, USB_DIR_IN,
                                  0, 0, &data, 1, 3000);
        if (result < 0) {
-               dev_err(dev, "%s: get config number failed: %d\n", __FUNCTION__, result);
+               dev_err(dev, "%s: get config number failed: %d\n", __func__, result);
                return result;
        }
        if (result != 1) {
-               dev_err(dev, "%s: get config number bad return length: %d\n", __FUNCTION__, result);
+               dev_err(dev, "%s: get config number bad return length: %d\n", __func__, result);
                return -EIO;
        }
 
@@ -841,11 +834,11 @@ static int clie_3_5_startup (struct usb_serial *serial)
                                  USB_DIR_IN | USB_RECIP_INTERFACE,
                                  0, 0, &data, 1, 3000);
        if (result < 0) {
-               dev_err(dev, "%s: get interface number failed: %d\n", __FUNCTION__, result);
+               dev_err(dev, "%s: get interface number failed: %d\n", __func__, result);
                return result;
        }
        if (result != 1) {
-               dev_err(dev, "%s: get interface number bad return length: %d\n", __FUNCTION__, result);
+               dev_err(dev, "%s: get interface number bad return length: %d\n", __func__, result);
                return -EIO;
        }
 
@@ -863,7 +856,7 @@ static int treo_attach (struct usb_serial *serial)
            (serial->num_interrupt_in == 0))
                goto generic_startup;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /*
        * It appears that Treos and Kyoceras want to use the 
@@ -894,7 +887,7 @@ generic_startup:
 
 static int clie_5_attach (struct usb_serial *serial)
 {
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /* TH55 registers 2 ports. 
           Communication in from the UX50/TH55 uses bulk_in_endpointAddress from port 0 
@@ -918,7 +911,7 @@ static void visor_shutdown (struct usb_serial *serial)
        struct visor_private *priv;
        int i;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        for (i = 0; i < serial->num_ports; i++) {
                priv = usb_get_serial_port_data(serial->port[i]);
@@ -931,7 +924,7 @@ static void visor_shutdown (struct usb_serial *serial)
 
 static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
 {
-       dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
+       dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
 
        return -ENOIOCTLCMD;
 }
index 38726ef3132b70d83121d8bdaa894b47990f0843..e96bf8663ffcd0eef052e334a0ecca8b430f628a 100644 (file)
@@ -164,9 +164,6 @@ static struct usb_serial_driver whiteheat_fake_device = {
        .description =          "Connect Tech - WhiteHEAT - (prerenumeration)",
        .usb_driver =           &whiteheat_driver,
        .id_table =             id_table_prerenumeration,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          NUM_DONT_CARE,
-       .num_bulk_out =         NUM_DONT_CARE,
        .num_ports =            1,
        .probe =                whiteheat_firmware_download,
        .attach =               whiteheat_firmware_attach,
@@ -180,9 +177,6 @@ static struct usb_serial_driver whiteheat_device = {
        .description =          "Connect Tech - WhiteHEAT",
        .usb_driver =           &whiteheat_driver,
        .id_table =             id_table_std,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          NUM_DONT_CARE,
-       .num_bulk_out =         NUM_DONT_CARE,
        .num_ports =            4,
        .attach =               whiteheat_attach,
        .shutdown =             whiteheat_shutdown,
@@ -225,7 +219,7 @@ struct whiteheat_urb_wrap {
 struct whiteheat_private {
        spinlock_t              lock;
        __u8                    flags;
-       __u8                    mcr;
+       __u8                    mcr;            /* FIXME: no locking on mcr */
        struct list_head        rx_urbs_free;
        struct list_head        rx_urbs_submitted;
        struct list_head        rx_urb_q;
@@ -288,7 +282,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
        int response;
        const struct whiteheat_hex_record *record;
        
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
        
        response = ezusb_set_reset (serial, 1);
 
@@ -298,7 +292,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
                                (unsigned char *)record->data, record->data_size, 0xa0);
                if (response < 0) {
                        err("%s - ezusb_writememory failed for loader (%d %04X %p %d)",
-                               __FUNCTION__, response, record->address, record->data, record->data_size);
+                               __func__, response, record->address, record->data, record->data_size);
                        break;
                }
                ++record;
@@ -315,7 +309,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
                                (unsigned char *)record->data, record->data_size, 0xa3);
                if (response < 0) {
                        err("%s - ezusb_writememory failed for first firmware step (%d %04X %p %d)", 
-                               __FUNCTION__, response, record->address, record->data, record->data_size);
+                               __func__, response, record->address, record->data, record->data_size);
                        break;
                }
                ++record;
@@ -329,7 +323,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
                                (unsigned char *)record->data, record->data_size, 0xa0);
                if (response < 0) {
                        err("%s - ezusb_writememory failed for second firmware step (%d %04X %p %d)", 
-                               __FUNCTION__, response, record->address, record->data, record->data_size);
+                               __func__, response, record->address, record->data, record->data_size);
                        break;
                }
                ++record;
@@ -567,7 +561,7 @@ static void whiteheat_shutdown (struct usb_serial *serial)
        struct list_head *tmp2;
        int i;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /* free up our private data for our command port */
        command_port = serial->port[COMMAND_PORT];
@@ -604,7 +598,7 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
        int             retval = 0;
        struct ktermios old_term;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        retval = start_command_port(port->serial);
        if (retval)
@@ -637,14 +631,14 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
        /* Start reading from the device */
        retval = start_port_read(port);
        if (retval) {
-               err("%s - failed submitting read urb, error %d", __FUNCTION__, retval);
+               err("%s - failed submitting read urb, error %d", __func__, retval);
                firm_close(port);
                stop_command_port(port->serial);
                goto exit;
        }
 
 exit:
-       dbg("%s - exit, retval = %d", __FUNCTION__, retval);
+       dbg("%s - exit, retval = %d", __func__, retval);
        return retval;
 }
 
@@ -657,7 +651,7 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
        struct list_head *tmp;
        struct list_head *tmp2;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        mutex_lock(&port->serial->disc_mutex);
        /* filp is NULL when called from usb_serial_disconnect */
@@ -732,10 +726,10 @@ static int whiteheat_write(struct usb_serial_port *port, const unsigned char *bu
        unsigned long flags;
        struct list_head *tmp;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (count == 0) {
-               dbg("%s - write request of 0 bytes", __FUNCTION__);
+               dbg("%s - write request of 0 bytes", __func__);
                return (0);
        }
 
@@ -754,13 +748,13 @@ static int whiteheat_write(struct usb_serial_port *port, const unsigned char *bu
                bytes = (count > port->bulk_out_size) ? port->bulk_out_size : count;
                memcpy (urb->transfer_buffer, buf + sent, bytes);
 
-               usb_serial_debug_data(debug, &port->dev, __FUNCTION__, bytes, urb->transfer_buffer);
+               usb_serial_debug_data(debug, &port->dev, __func__, bytes, urb->transfer_buffer);
 
                urb->dev = serial->dev;
                urb->transfer_buffer_length = bytes;
                result = usb_submit_urb(urb, GFP_ATOMIC);
                if (result) {
-                       err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
+                       err("%s - failed submitting write urb, error %d", __func__, result);
                        sent = result;
                        spin_lock_irqsave(&info->lock, flags);
                        list_add(tmp, &info->tx_urbs_free);
@@ -786,7 +780,7 @@ static int whiteheat_write_room(struct usb_serial_port *port)
        int room = 0;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
        
        spin_lock_irqsave(&info->lock, flags);
        list_for_each(tmp, &info->tx_urbs_free)
@@ -794,7 +788,7 @@ static int whiteheat_write_room(struct usb_serial_port *port)
        spin_unlock_irqrestore(&info->lock, flags);
        room *= port->bulk_out_size;
 
-       dbg("%s - returns %d", __FUNCTION__, room);
+       dbg("%s - returns %d", __func__, room);
        return (room);
 }
 
@@ -804,7 +798,7 @@ static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file)
        struct whiteheat_private *info = usb_get_serial_port_data(port);
        unsigned int modem_signals = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        firm_get_dtr_rts(port);
        if (info->mcr & UART_MCR_DTR)
@@ -821,7 +815,7 @@ static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file,
 {
        struct whiteheat_private *info = usb_get_serial_port_data(port);
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (set & TIOCM_RTS)
                info->mcr |= UART_MCR_RTS;
@@ -844,7 +838,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
        struct serial_struct serstruct;
        void __user *user_arg = (void __user *)arg;
 
-       dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
+       dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
 
        switch (cmd) {
                case TIOCGSERIAL:
@@ -886,7 +880,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)
 {
-       dbg("%s -port %d", __FUNCTION__, port->number);
+       dbg("%s -port %d", __func__, port->number);
        firm_setup_port(port);
 }
 
@@ -904,7 +898,7 @@ static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
        int chars = 0;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&info->lock, flags);
        list_for_each(tmp, &info->tx_urbs_submitted) {
@@ -913,7 +907,7 @@ static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
        }
        spin_unlock_irqrestore(&info->lock, flags);
 
-       dbg ("%s - returns %d", __FUNCTION__, chars);
+       dbg ("%s - returns %d", __func__, chars);
        return chars;
 }
 
@@ -923,7 +917,7 @@ static void whiteheat_throttle (struct usb_serial_port *port)
        struct whiteheat_private *info = usb_get_serial_port_data(port);
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&info->lock, flags);
        info->flags |= THROTTLED;
@@ -939,7 +933,7 @@ static void whiteheat_unthrottle (struct usb_serial_port *port)
        int actually_throttled;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&info->lock, flags);
        actually_throttled = info->flags & ACTUALLY_THROTTLED;
@@ -960,7 +954,7 @@ static void command_port_write_callback(struct urb *urb)
 {
        int status = urb->status;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        if (status) {
                dbg("nonzero urb status: %d", status);
@@ -971,28 +965,28 @@ static void command_port_write_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 usb_serial_port *command_port = urb->context;
        struct whiteheat_command_private *command_info;
        int status = urb->status;
        unsigned char *data = urb->transfer_buffer;
        int result;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        command_info = usb_get_serial_port_data(command_port);
        if (!command_info) {
-               dbg ("%s - command_info is NULL, exiting.", __FUNCTION__);
+               dbg ("%s - command_info is NULL, exiting.", __func__);
                return;
        }
        if (status) {
-               dbg("%s - nonzero urb status: %d", __FUNCTION__, status);
+               dbg("%s - nonzero urb status: %d", __func__, 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);
+       usb_serial_debug_data(debug, &command_port->dev, __func__, urb->actual_length, data);
 
        if (data[0] == WHITEHEAT_CMD_COMPLETE) {
                command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
@@ -1002,38 +996,38 @@ static void command_port_read_callback(struct urb *urb)
                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__);
+               dbg("%s - event received", __func__);
        } 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(&command_info->wait_command);
        } else {
-               dbg("%s - bad reply from firmware", __FUNCTION__);
+               dbg("%s - bad reply from firmware", __func__);
        }
        
        /* Continue trying to always read */
        command_port->read_urb->dev = command_port->serial->dev;
        result = usb_submit_urb(command_port->read_urb, GFP_ATOMIC);
        if (result)
-               dbg("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+               dbg("%s - failed resubmitting read urb, error %d", __func__, result);
 }
 
 
 static void whiteheat_read_callback(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
        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);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock(&info->lock);
        wrap = urb_to_wrap(urb, &info->rx_urbs_submitted);
        if (!wrap) {
                spin_unlock(&info->lock);
-               err("%s - Not my urb!", __FUNCTION__);
+               err("%s - Not my urb!", __func__);
                return;
        }
        list_del(&wrap->list);
@@ -1041,14 +1035,14 @@ static void whiteheat_read_callback(struct urb *urb)
 
        if (status) {
                dbg("%s - nonzero read bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                spin_lock(&info->lock);
                list_add(&wrap->list, &info->rx_urbs_free);
                spin_unlock(&info->lock);
                return;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+       usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
 
        spin_lock(&info->lock);
        list_add_tail(&wrap->list, &info->rx_urb_q);
@@ -1065,18 +1059,18 @@ static void whiteheat_read_callback(struct urb *urb)
 
 static void whiteheat_write_callback(struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *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);
+       dbg("%s - port %d", __func__, port->number);
 
        spin_lock(&info->lock);
        wrap = urb_to_wrap(urb, &info->tx_urbs_submitted);
        if (!wrap) {
                spin_unlock(&info->lock);
-               err("%s - Not my urb!", __FUNCTION__);
+               err("%s - Not my urb!", __func__);
                return;
        }
        list_move(&wrap->list, &info->tx_urbs_free);
@@ -1084,7 +1078,7 @@ static void whiteheat_write_callback(struct urb *urb)
 
        if (status) {
                dbg("%s - nonzero write bulk status received: %d",
-                   __FUNCTION__, status);
+                   __func__, status);
                return;
        }
 
@@ -1104,7 +1098,7 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d
        int retval = 0;
        int t;
 
-       dbg("%s - command %d", __FUNCTION__, command);
+       dbg("%s - command %d", __func__, command);
 
        command_port = port->serial->port[COMMAND_PORT];
        command_info = usb_get_serial_port_data(command_port);
@@ -1118,7 +1112,7 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d
        command_port->write_urb->dev = port->serial->dev;
        retval = usb_submit_urb (command_port->write_urb, GFP_NOIO);
        if (retval) {
-               dbg("%s - submit urb failed", __FUNCTION__);
+               dbg("%s - submit urb failed", __func__);
                goto exit;
        }
 
@@ -1129,19 +1123,19 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d
                usb_kill_urb(command_port->write_urb);
 
        if (command_info->command_finished == false) {
-               dbg("%s - command timed out.", __FUNCTION__);
+               dbg("%s - command timed out.", __func__);
                retval = -ETIMEDOUT;
                goto exit;
        }
 
        if (command_info->command_finished == WHITEHEAT_CMD_FAILURE) {
-               dbg("%s - command failed.", __FUNCTION__);
+               dbg("%s - command failed.", __func__);
                retval = -EIO;
                goto exit;
        }
 
        if (command_info->command_finished == WHITEHEAT_CMD_COMPLETE) {
-               dbg("%s - command completed.", __FUNCTION__);
+               dbg("%s - command completed.", __func__);
                switch (command) {
                        case WHITEHEAT_GET_DTR_RTS:
                                info = usb_get_serial_port_data(port);
@@ -1186,7 +1180,7 @@ static int firm_setup_port(struct usb_serial_port *port) {
                default:
                case CS8:       port_settings.bits = 8;   break;
        }
-       dbg("%s - data bits = %d", __FUNCTION__, port_settings.bits);
+       dbg("%s - data bits = %d", __func__, port_settings.bits);
        
        /* determine the parity */
        if (cflag & PARENB)
@@ -1202,21 +1196,21 @@ static int firm_setup_port(struct usb_serial_port *port) {
                                port_settings.parity = WHITEHEAT_PAR_EVEN;
        else
                port_settings.parity = WHITEHEAT_PAR_NONE;
-       dbg("%s - parity = %c", __FUNCTION__, port_settings.parity);
+       dbg("%s - parity = %c", __func__, port_settings.parity);
 
        /* figure out the stop bits requested */
        if (cflag & CSTOPB)
                port_settings.stop = 2;
        else
                port_settings.stop = 1;
-       dbg("%s - stop bits = %d", __FUNCTION__, port_settings.stop);
+       dbg("%s - stop bits = %d", __func__, port_settings.stop);
 
        /* figure out the flow control settings */
        if (cflag & CRTSCTS)
                port_settings.hflow = (WHITEHEAT_HFLOW_CTS | WHITEHEAT_HFLOW_RTS);
        else
                port_settings.hflow = WHITEHEAT_HFLOW_NONE;
-       dbg("%s - hardware flow control = %s %s %s %s", __FUNCTION__,
+       dbg("%s - hardware flow control = %s %s %s %s", __func__,
            (port_settings.hflow & WHITEHEAT_HFLOW_CTS) ? "CTS" : "",
            (port_settings.hflow & WHITEHEAT_HFLOW_RTS) ? "RTS" : "",
            (port_settings.hflow & WHITEHEAT_HFLOW_DSR) ? "DSR" : "",
@@ -1227,15 +1221,15 @@ static int firm_setup_port(struct usb_serial_port *port) {
                port_settings.sflow = WHITEHEAT_SFLOW_RXTX;
        else
                port_settings.sflow = WHITEHEAT_SFLOW_NONE;
-       dbg("%s - software flow control = %c", __FUNCTION__, port_settings.sflow);
+       dbg("%s - software flow control = %c", __func__, port_settings.sflow);
        
        port_settings.xon = START_CHAR(port->tty);
        port_settings.xoff = STOP_CHAR(port->tty);
-       dbg("%s - XON = %2x, XOFF = %2x", __FUNCTION__, port_settings.xon, port_settings.xoff);
+       dbg("%s - XON = %2x, XOFF = %2x", __func__, port_settings.xon, port_settings.xoff);
 
        /* get the baud rate wanted */
        port_settings.baud = tty_get_baud_rate(port->tty);
-       dbg("%s - baud rate = %d", __FUNCTION__, port_settings.baud);
+       dbg("%s - baud rate = %d", __func__, port_settings.baud);
 
        /* fixme: should set validated settings */
        tty_encode_baud_rate(port->tty, port_settings.baud, port_settings.baud);
@@ -1318,7 +1312,7 @@ static int start_command_port(struct usb_serial *serial)
                command_port->read_urb->dev = serial->dev;
                retval = usb_submit_urb(command_port->read_urb, GFP_KERNEL);
                if (retval) {
-                       err("%s - failed submitting read urb, error %d", __FUNCTION__, retval);
+                       err("%s - failed submitting read urb, error %d", __func__, retval);
                        goto exit;
                }
        }
@@ -1454,7 +1448,7 @@ static void rx_data_softint(struct work_struct *work)
                urb->dev = port->serial->dev;
                result = usb_submit_urb(urb, GFP_ATOMIC);
                if (result) {
-                       err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+                       err("%s - failed resubmitting read urb, error %d", __func__, result);
                        spin_lock_irqsave(&info->lock, flags);
                        list_add(tmp, &info->rx_urbs_free);
                        continue;
index 7e53333be0136c4f392545225b55d0e59cf7bfac..0f6d234d699b1327b2691ebca03f2a2707fe43a1 100644 (file)
@@ -32,8 +32,8 @@ config USB_STORAGE_DEBUG
          verbose debugging messages.
 
 config USB_STORAGE_DATAFAB
-       bool "Datafab Compact Flash Reader support (EXPERIMENTAL)"
-       depends on USB_STORAGE && EXPERIMENTAL
+       bool "Datafab Compact Flash Reader support"
+       depends on USB_STORAGE
        help
          Support for certain Datafab CompactFlash readers.
          Datafab has a web page at <http://www.datafabusa.com/>.
@@ -69,8 +69,8 @@ config USB_STORAGE_DPCM
          There is a web page at <http://www.ziocorp.com/products/>.
 
 config USB_STORAGE_USBAT
-       bool "USBAT/USBAT02-based storage support (EXPERIMENTAL)"
-       depends on USB_STORAGE && EXPERIMENTAL
+       bool "USBAT/USBAT02-based storage support"
+       depends on USB_STORAGE
        help
          Say Y here to include additional code to support storage devices
          based on the SCM/Shuttle USBAT/USBAT02 processors.
@@ -90,30 +90,30 @@ config USB_STORAGE_USBAT
          - Sandisk ImageMate SDDR-05b
 
 config USB_STORAGE_SDDR09
-       bool "SanDisk SDDR-09 (and other SmartMedia) support (EXPERIMENTAL)"
-       depends on USB_STORAGE && EXPERIMENTAL
+       bool "SanDisk SDDR-09 (and other SmartMedia) support"
+       depends on USB_STORAGE
        help
          Say Y here to include additional code to support the Sandisk SDDR-09
          SmartMedia reader in the USB Mass Storage driver.
          Also works for the Microtech Zio! SmartMedia reader.
 
 config USB_STORAGE_SDDR55
-       bool "SanDisk SDDR-55 SmartMedia support (EXPERIMENTAL)"
-       depends on USB_STORAGE && EXPERIMENTAL
+       bool "SanDisk SDDR-55 SmartMedia support"
+       depends on USB_STORAGE
        help
          Say Y here to include additional code to support the Sandisk SDDR-55
          SmartMedia reader in the USB Mass Storage driver.
 
 config USB_STORAGE_JUMPSHOT
-       bool "Lexar Jumpshot Compact Flash Reader (EXPERIMENTAL)"
-       depends on USB_STORAGE && EXPERIMENTAL
+       bool "Lexar Jumpshot Compact Flash Reader"
+       depends on USB_STORAGE
        help
          Say Y here to include additional code to support the Lexar Jumpshot
          USB CompactFlash reader.
 
 config USB_STORAGE_ALAUDA
-       bool "Olympus MAUSB-10/Fuji DPC-R1 support (EXPERIMENTAL)"
-       depends on USB_STORAGE && EXPERIMENTAL
+       bool "Olympus MAUSB-10/Fuji DPC-R1 support"
+       depends on USB_STORAGE
        help
          Say Y here to include additional code to support the Olympus MAUSB-10
          and Fujifilm DPC-R1 USB Card reader/writer devices.
@@ -122,8 +122,8 @@ config USB_STORAGE_ALAUDA
          XD and SmartMedia cards.
 
 config USB_STORAGE_ONETOUCH
-       bool "Support OneTouch Button on Maxtor Hard Drives (EXPERIMENTAL)"
-       depends on USB_STORAGE && INPUT_EVDEV && EXPERIMENTAL && !PM
+       bool "Support OneTouch Button on Maxtor Hard Drives"
+       depends on USB_STORAGE && INPUT_EVDEV
        help
          Say Y here to include additional code to support the Maxtor OneTouch
          USB hard drive's onetouch button.
@@ -145,6 +145,17 @@ config USB_STORAGE_KARMA
          on the resulting scsi device node returns the Karma to normal
          operation.
 
+config USB_STORAGE_CYPRESS_ATACB
+       bool "SAT emulation on Cypress USB/ATA Bridge with ATACB"
+       depends on USB_STORAGE
+       ---help---
+         Say Y here if you want to use SAT (ata pass through) on devices based
+         on the Cypress USB/ATA bridge supporting ATACB. This will allow you
+         to use tools to tune and monitor your drive (like hdparm or smartctl).
+
+         If you say no here your device will still work with the standard usb
+         mass storage class.
+
 config USB_LIBUSUAL
        bool "The shared table of common (or usual) storage devices"
        depends on USB
index 023969b4385b689265b3836cb130a6dd8de64fad..4c596c766c53c61c2ee460d3a6e54a042e86e171 100644 (file)
@@ -21,6 +21,7 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT)        += jumpshot.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA)   += alauda.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA)    += karma.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += cypress_atacb.o
 
 usb-storage-objs :=    scsiglue.o protocol.o transport.o usb.o \
                        initializers.o $(usb-storage-obj-y)
diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c
new file mode 100644 (file)
index 0000000..d88824b
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Support for emulating SAT (ata pass through) on devices based
+ *       on the Cypress USB/ATA bridge supporting ATACB.
+ *
+ * Copyright (c) 2008 Matthieu Castet (castet.matthieu@free.fr)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_eh.h>
+#include <linux/ata.h>
+
+#include "usb.h"
+#include "protocol.h"
+#include "scsiglue.h"
+#include "debug.h"
+
+/*
+ * ATACB is a protocol used on cypress usb<->ata bridge to
+ * send raw ATA command over mass storage
+ * There is a ATACB2 protocol that support LBA48 on newer chip.
+ * More info that be found on cy7c68310_8.pdf and cy7c68300c_8.pdf
+ * datasheet from cypress.com.
+ */
+void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
+{
+       unsigned char save_cmnd[MAX_COMMAND_SIZE];
+
+       if (likely(srb->cmnd[0] != ATA_16 && srb->cmnd[0] != ATA_12)) {
+               usb_stor_transparent_scsi_command(srb, us);
+               return;
+       }
+
+       memcpy(save_cmnd, srb->cmnd, sizeof(save_cmnd));
+       memset(srb->cmnd, 0, sizeof(srb->cmnd));
+
+       /* check if we support the command */
+       if (save_cmnd[1] >> 5) /* MULTIPLE_COUNT */
+               goto invalid_fld;
+       /* check protocol */
+       switch((save_cmnd[1] >> 1) & 0xf) {
+               case 3: /*no DATA */
+               case 4: /* PIO in */
+               case 5: /* PIO out */
+                       break;
+               default:
+                       goto invalid_fld;
+       }
+
+       /* first build the ATACB command */
+       srb->cmd_len = 16;
+
+       srb->cmnd[0] = 0x24; /* bVSCBSignature : vendor-specific command
+                               this value can change, but most(all ?) manufacturers
+                                                       keep the cypress default : 0x24 */
+       srb->cmnd[1] = 0x24; /* bVSCBSubCommand : 0x24 for ATACB */
+
+       srb->cmnd[3] = 0xff - 1; /* features, sector count, lba low, lba med
+                                                               lba high, device, command are valid */
+       srb->cmnd[4] = 1; /* TransferBlockCount : 512 */
+
+       if (save_cmnd[0] == ATA_16) {
+               srb->cmnd[ 6] = save_cmnd[ 4]; /* features */
+               srb->cmnd[ 7] = save_cmnd[ 6]; /* sector count */
+               srb->cmnd[ 8] = save_cmnd[ 8]; /* lba low */
+               srb->cmnd[ 9] = save_cmnd[10]; /* lba med */
+               srb->cmnd[10] = save_cmnd[12]; /* lba high */
+               srb->cmnd[11] = save_cmnd[13]; /* device */
+               srb->cmnd[12] = save_cmnd[14]; /* command */
+
+               if (save_cmnd[1] & 0x01) {/* extended bit set for LBA48 */
+                       /* this could be supported by atacb2 */
+                       if (save_cmnd[3] || save_cmnd[5] || save_cmnd[7] || save_cmnd[9]
+                                       || save_cmnd[11])
+                               goto invalid_fld;
+               }
+       }
+       else { /* ATA12 */
+               srb->cmnd[ 6] = save_cmnd[3]; /* features */
+               srb->cmnd[ 7] = save_cmnd[4]; /* sector count */
+               srb->cmnd[ 8] = save_cmnd[5]; /* lba low */
+               srb->cmnd[ 9] = save_cmnd[6]; /* lba med */
+               srb->cmnd[10] = save_cmnd[7]; /* lba high */
+               srb->cmnd[11] = save_cmnd[8]; /* device */
+               srb->cmnd[12] = save_cmnd[9]; /* command */
+
+       }
+       /* Filter SET_FEATURES - XFER MODE command */
+       if ((srb->cmnd[12] == ATA_CMD_SET_FEATURES)
+                       && (srb->cmnd[6] == SETFEATURES_XFER))
+               goto invalid_fld;
+
+       if (srb->cmnd[12] == ATA_CMD_ID_ATA || srb->cmnd[12] == ATA_CMD_ID_ATAPI)
+               srb->cmnd[2] |= (1<<7); /* set  IdentifyPacketDevice for these cmds */
+
+
+       usb_stor_transparent_scsi_command(srb, us);
+
+       /* if the device doesn't support ATACB
+        */
+       if (srb->result == SAM_STAT_CHECK_CONDITION &&
+                       memcmp(srb->sense_buffer, usb_stor_sense_invalidCDB,
+                               sizeof(usb_stor_sense_invalidCDB)) == 0) {
+               US_DEBUGP("cypress atacb not supported ???\n");
+               goto end;
+       }
+
+       /* if ck_cond flags is set, and there wasn't critical error,
+        * build the special sense
+        */
+       if ((srb->result != (DID_ERROR << 16) &&
+                               srb->result != (DID_ABORT << 16)) &&
+                       save_cmnd[2] & 0x20) {
+               struct scsi_eh_save ses;
+               unsigned char regs[8];
+               unsigned char *sb = srb->sense_buffer;
+               unsigned char *desc = sb + 8;
+               int tmp_result;
+
+               /* build the command for
+                * reading the ATA registers */
+               scsi_eh_prep_cmnd(srb, &ses, NULL, 0, 0);
+               srb->sdb.length = sizeof(regs);
+               sg_init_one(&ses.sense_sgl, regs, srb->sdb.length);
+               srb->sdb.table.sgl = &ses.sense_sgl;
+               srb->sc_data_direction = DMA_FROM_DEVICE;
+               srb->sdb.table.nents = 1;
+               /* we use the same command as before, but we set
+                * the read taskfile bit, for not executing atacb command,
+                * but reading register selected in srb->cmnd[4]
+                */
+               srb->cmnd[2] = 1;
+
+               usb_stor_transparent_scsi_command(srb, us);
+               tmp_result = srb->result;
+               scsi_eh_restore_cmnd(srb, &ses);
+               /* we fail to get registers, report invalid command */
+               if (tmp_result != SAM_STAT_GOOD)
+                       goto invalid_fld;
+
+               /* build the sense */
+               memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
+
+               /* set sk, asc for a good command */
+               sb[1] = RECOVERED_ERROR;
+               sb[2] = 0; /* ATA PASS THROUGH INFORMATION AVAILABLE */
+               sb[3] = 0x1D;
+
+               /* XXX we should generate sk, asc, ascq from status and error
+                * regs
+                * (see 11.1 Error translation Â­ ATA device error to SCSI error map)
+                * and ata_to_sense_error from libata.
+                */
+
+               /* Sense data is current and format is descriptor. */
+               sb[0] = 0x72;
+               desc[0] = 0x09; /* ATA_RETURN_DESCRIPTOR */
+
+               /* set length of additional sense data */
+               sb[7] = 14;
+               desc[1] = 12;
+
+               /* Copy registers into sense buffer. */
+               desc[ 2] = 0x00;
+               desc[ 3] = regs[1];  /* features */
+               desc[ 5] = regs[2];  /* sector count */
+               desc[ 7] = regs[3];  /* lba low */
+               desc[ 9] = regs[4];  /* lba med */
+               desc[11] = regs[5];  /* lba high */
+               desc[12] = regs[6];  /* device */
+               desc[13] = regs[7];  /* command */
+
+               srb->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+       }
+       goto end;
+invalid_fld:
+       srb->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
+       memcpy(srb->sense_buffer,
+                       usb_stor_sense_invalidCDB,
+                       sizeof(usb_stor_sense_invalidCDB));
+end:
+       memcpy(srb->cmnd, save_cmnd, sizeof(save_cmnd));
+       if (srb->cmnd[0] == ATA_12)
+               srb->cmd_len = 12;
+}
diff --git a/drivers/usb/storage/cypress_atacb.h b/drivers/usb/storage/cypress_atacb.h
new file mode 100644 (file)
index 0000000..fbada89
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Support for emulating SAT (ata pass through) on devices based
+ *       on the Cypress USB/ATA bridge supporting ATACB.
+ *
+ * Copyright (c) 2008 Matthieu Castet (castet.matthieu@free.fr)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _CYPRESS_ATACB_H_
+#define _CYPRESS_ATACB_H_
+extern void cypress_atacb_passthrough(struct scsi_cmnd*, struct us_data*);
+#endif
index 55b952084f0c07d065546526ea870ca27d869f3e..a28d49122e7a046301799edfade54e95f50d1cdd 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/usb_usual.h>
 #include <linux/vmalloc.h>
 #include <linux/kthread.h>
+#include <linux/mutex.h>
 
 /*
  */
@@ -30,7 +31,7 @@ static atomic_t usu_bias = ATOMIC_INIT(USB_US_DEFAULT_BIAS);
 #define BIAS_NAME_SIZE  (sizeof("usb-storage"))
 static const char *bias_names[3] = { "none", "usb-storage", "ub" };
 
-static struct semaphore usu_init_notify;
+static DEFINE_MUTEX(usu_probe_mutex);
 static DECLARE_COMPLETION(usu_end_notify);
 static atomic_t total_threads = ATOMIC_INIT(0);
 
@@ -178,10 +179,7 @@ static int usu_probe_thread(void *arg)
        int rc;
        unsigned long flags;
 
-       /* A completion does not work here because it's counted. */
-       down(&usu_init_notify);
-       up(&usu_init_notify);
-
+       mutex_lock(&usu_probe_mutex);
        rc = request_module(bias_names[type]);
        spin_lock_irqsave(&usu_lock, flags);
        if (rc == 0 && (st->fls & USU_MOD_FL_PRESENT) == 0) {
@@ -194,6 +192,7 @@ static int usu_probe_thread(void *arg)
        }
        st->fls &= ~USU_MOD_FL_THREAD;
        spin_unlock_irqrestore(&usu_lock, flags);
+       mutex_unlock(&usu_probe_mutex);
 
        complete_and_exit(&usu_end_notify, 0);
 }
@@ -204,10 +203,9 @@ static int __init usb_usual_init(void)
 {
        int rc;
 
-       sema_init(&usu_init_notify, 0);
-
+       mutex_lock(&usu_probe_mutex);
        rc = usb_register(&usu_driver);
-       up(&usu_init_notify);
+       mutex_unlock(&usu_probe_mutex);
        return rc;
 }
 
index 8c1e2954f3b9e8556601b823bb0238a8ed41b0a6..3fcde9f0fa5fe64df4484fbcb068b5109b858650 100644 (file)
@@ -73,6 +73,7 @@ static const char* host_info(struct Scsi_Host *host)
 static int slave_alloc (struct scsi_device *sdev)
 {
        struct us_data *us = host_to_us(sdev->host);
+       struct usb_host_endpoint *bulk_in_ep;
 
        /*
         * Set the INQUIRY transfer length to 36.  We don't use any of
@@ -84,12 +85,13 @@ static int slave_alloc (struct scsi_device *sdev)
        /* Scatter-gather buffers (all but the last) must have a length
         * divisible by the bulk maxpacket size.  Otherwise a data packet
         * would end up being short, causing a premature end to the data
-        * transfer.  Since high-speed bulk pipes have a maxpacket size
-        * of 512, we'll use that as the scsi device queue's DMA alignment
-        * mask.  Guaranteeing proper alignment of the first buffer will
-        * have the desired effect because, except at the beginning and
-        * the end, scatter-gather buffers follow page boundaries. */
-       blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
+        * transfer.  We'll use the maxpacket value of the bulk-IN pipe
+        * to set the SCSI device queue's DMA alignment mask.
+        */
+       bulk_in_ep = us->pusb_dev->ep_in[usb_pipeendpoint(us->recv_bulk_pipe)];
+       blk_queue_update_dma_alignment(sdev->request_queue,
+                       le16_to_cpu(bulk_in_ep->desc.wMaxPacketSize) - 1);
+                       /* wMaxPacketSize must be a power of 2 */
 
        /*
         * The UFI spec treates the Peripheral Qualifier bits in an
@@ -132,7 +134,7 @@ static int slave_configure(struct scsi_device *sdev)
                /* Disk-type devices use MODE SENSE(6) if the protocol
                 * (SubClass) is Transparent SCSI, otherwise they use
                 * MODE SENSE(10). */
-               if (us->subclass != US_SC_SCSI)
+               if (us->subclass != US_SC_SCSI && us->subclass != US_SC_CYP_ATACB)
                        sdev->use_10_for_ms = 1;
 
                /* Many disks only accept MODE SENSE transfer lengths of
@@ -226,12 +228,12 @@ static int queuecommand(struct scsi_cmnd *srb,
 {
        struct us_data *us = host_to_us(srb->device->host);
 
-       US_DEBUGP("%s called\n", __FUNCTION__);
+       US_DEBUGP("%s called\n", __func__);
 
        /* check for state-transition errors */
        if (us->srb != NULL) {
                printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n",
-                       __FUNCTION__, us->srb);
+                       __func__, us->srb);
                return SCSI_MLQUEUE_HOST_BUSY;
        }
 
@@ -260,7 +262,7 @@ static int command_abort(struct scsi_cmnd *srb)
 {
        struct us_data *us = host_to_us(srb->device->host);
 
-       US_DEBUGP("%s called\n", __FUNCTION__);
+       US_DEBUGP("%s called\n", __func__);
 
        /* us->srb together with the TIMED_OUT, RESETTING, and ABORTING
         * bits are protected by the host lock. */
@@ -297,7 +299,7 @@ static int device_reset(struct scsi_cmnd *srb)
        struct us_data *us = host_to_us(srb->device->host);
        int result;
 
-       US_DEBUGP("%s called\n", __FUNCTION__);
+       US_DEBUGP("%s called\n", __func__);
 
        /* lock the device pointers and do the reset */
        mutex_lock(&(us->dev_mutex));
@@ -313,7 +315,7 @@ static int bus_reset(struct scsi_cmnd *srb)
        struct us_data *us = host_to_us(srb->device->host);
        int result;
 
-       US_DEBUGP("%s called\n", __FUNCTION__);
+       US_DEBUGP("%s called\n", __func__);
        result = usb_stor_port_reset(us);
        return result < 0 ? FAILED : SUCCESS;
 }
index bdd4334bed5a71c7615455cedbb755925cec1436..6610d2dd1e7f4f099261788321765b486300ca47 100644 (file)
  */
 static void usb_stor_blocking_completion(struct urb *urb)
 {
-       struct completion *urb_done_ptr = (struct completion *)urb->context;
+       struct completion *urb_done_ptr = urb->context;
 
        complete(urb_done_ptr);
 }
@@ -198,7 +198,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
        int status;
 
        US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
-                       __FUNCTION__, request, requesttype,
+                       __func__, request, requesttype,
                        value, index, size);
 
        /* fill in the devrequest structure */
@@ -250,7 +250,7 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
                usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe),
                                usb_pipeout(pipe), 0);
 
-       US_DEBUGP("%s: result = %d\n", __FUNCTION__, result);
+       US_DEBUGP("%s: result = %d\n", __func__, result);
        return result;
 }
 
@@ -332,7 +332,7 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
        int result;
 
        US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
-                       __FUNCTION__, request, requesttype,
+                       __func__, request, requesttype,
                        value, index, size);
 
        /* fill in the devrequest structure */
@@ -366,7 +366,7 @@ static int usb_stor_intr_transfer(struct us_data *us, void *buf,
        unsigned int pipe = us->recv_intr_pipe;
        unsigned int maxp;
 
-       US_DEBUGP("%s: xfer %u bytes\n", __FUNCTION__, length);
+       US_DEBUGP("%s: xfer %u bytes\n", __func__, length);
 
        /* calculate the max packet size */
        maxp = usb_maxpacket(us->pusb_dev, pipe, usb_pipeout(pipe));
@@ -393,7 +393,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
 {
        int result;
 
-       US_DEBUGP("%s: xfer %u bytes\n", __FUNCTION__, length);
+       US_DEBUGP("%s: xfer %u bytes\n", __func__, length);
 
        /* fill and submit the URB */
        usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, buf, length,
@@ -424,7 +424,7 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
                return USB_STOR_XFER_ERROR;
 
        /* initialize the scatter-gather request block */
-       US_DEBUGP("%s: xfer %u bytes, %d entries\n", __FUNCTION__,
+       US_DEBUGP("%s: xfer %u bytes, %d entries\n", __func__,
                        length, num_sg);
        result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0,
                        sg, num_sg, length, GFP_NOIO);
@@ -603,7 +603,8 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
                scsi_eh_prep_cmnd(srb, &ses, NULL, 0, US_SENSE_SIZE);
 
                /* FIXME: we must do the protocol translation here */
-               if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI)
+               if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI ||
+                               us->subclass == US_SC_CYP_ATACB)
                        srb->cmd_len = 6;
                else
                        srb->cmd_len = 12;
@@ -700,7 +701,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
 /* Stop the current URB transfer */
 void usb_stor_stop_transport(struct us_data *us)
 {
-       US_DEBUGP("%s called\n", __FUNCTION__);
+       US_DEBUGP("%s called\n", __func__);
 
        /* If the state machine is blocked waiting for an URB,
         * let's wake it up.  The test_and_clear_bit() call
@@ -1134,7 +1135,7 @@ static int usb_stor_reset_common(struct us_data *us,
 
 int usb_stor_CB_reset(struct us_data *us)
 {
-       US_DEBUGP("%s called\n", __FUNCTION__);
+       US_DEBUGP("%s called\n", __func__);
 
        memset(us->iobuf, 0xFF, CB_RESET_CMD_SIZE);
        us->iobuf[0] = SEND_DIAGNOSTIC;
@@ -1149,7 +1150,7 @@ int usb_stor_CB_reset(struct us_data *us)
  */
 int usb_stor_Bulk_reset(struct us_data *us)
 {
-       US_DEBUGP("%s called\n", __FUNCTION__);
+       US_DEBUGP("%s called\n", __func__);
 
        return usb_stor_reset_common(us, US_BULK_RESET_REQUEST, 
                                 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
index 91252075e6e195c9cde8c4444df899aed39665f3..732bf52a775e743d0039601b54dd20a127d00040 100644 (file)
@@ -1719,6 +1719,14 @@ UNUSUAL_DEV(  0xed06, 0x4500, 0x0001, 0x0001,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_CAPACITY_HEURISTICS),
 
+#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
+UNUSUAL_DEV(  0x04b4, 0x6830, 0x0000, 0x9999,
+               "Cypress",
+               "Cypress AT2LP",
+               US_SC_CYP_ATACB, US_PR_BULK, NULL,
+               0),
+#endif
+
 /* Control/Bulk transport for all SubClass values */
 USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
 USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR),
index ac6114eea0c3008f6f328ecd1bcf74368c837929..a856effad3bde74c9707bce6e9ff2dfe96681009 100644 (file)
 #ifdef CONFIG_USB_STORAGE_KARMA
 #include "karma.h"
 #endif
+#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
+#include "cypress_atacb.h"
+#endif
 
 /* Some informational data */
 MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
@@ -187,7 +190,7 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message)
        /* Wait until no command is running */
        mutex_lock(&us->dev_mutex);
 
-       US_DEBUGP("%s\n", __FUNCTION__);
+       US_DEBUGP("%s\n", __func__);
        if (us->suspend_resume_hook)
                (us->suspend_resume_hook)(us, US_SUSPEND);
 
@@ -204,7 +207,7 @@ static int storage_resume(struct usb_interface *iface)
 
        mutex_lock(&us->dev_mutex);
 
-       US_DEBUGP("%s\n", __FUNCTION__);
+       US_DEBUGP("%s\n", __func__);
        if (us->suspend_resume_hook)
                (us->suspend_resume_hook)(us, US_RESUME);
 
@@ -216,7 +219,7 @@ static int storage_reset_resume(struct usb_interface *iface)
 {
        struct us_data *us = usb_get_intfdata(iface);
 
-       US_DEBUGP("%s\n", __FUNCTION__);
+       US_DEBUGP("%s\n", __func__);
 
        /* Report the reset to the SCSI core */
        usb_stor_report_bus_reset(us);
@@ -237,7 +240,7 @@ static int storage_pre_reset(struct usb_interface *iface)
 {
        struct us_data *us = usb_get_intfdata(iface);
 
-       US_DEBUGP("%s\n", __FUNCTION__);
+       US_DEBUGP("%s\n", __func__);
 
        /* Make sure no command runs during the reset */
        mutex_lock(&us->dev_mutex);
@@ -248,7 +251,7 @@ static int storage_post_reset(struct usb_interface *iface)
 {
        struct us_data *us = usb_get_intfdata(iface);
 
-       US_DEBUGP("%s\n", __FUNCTION__);
+       US_DEBUGP("%s\n", __func__);
 
        /* Report the reset to the SCSI core */
        usb_stor_report_bus_reset(us);
@@ -434,7 +437,7 @@ SkipForAbort:
 /* Associate our private data with the USB device */
 static int associate_dev(struct us_data *us, struct usb_interface *intf)
 {
-       US_DEBUGP("-- %s\n", __FUNCTION__);
+       US_DEBUGP("-- %s\n", __func__);
 
        /* Fill in the device-related fields */
        us->pusb_dev = interface_to_usbdev(intf);
@@ -708,6 +711,13 @@ static int get_protocol(struct us_data *us)
                break;
 #endif
 
+#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
+       case US_SC_CYP_ATACB:
+               us->protocol_name = "Transparent SCSI with Cypress ATACB";
+               us->proto_handler = cypress_atacb_passthrough;
+               break;
+#endif
+
        default:
                return -EIO;
        }
@@ -806,7 +816,7 @@ static int usb_stor_acquire_resources(struct us_data *us)
 /* Release all our dynamic resources */
 static void usb_stor_release_resources(struct us_data *us)
 {
-       US_DEBUGP("-- %s\n", __FUNCTION__);
+       US_DEBUGP("-- %s\n", __func__);
 
        /* Tell the control thread to exit.  The SCSI host must
         * already have been removed so it won't try to queue
@@ -832,7 +842,7 @@ static void usb_stor_release_resources(struct us_data *us)
 /* Dissociate from the USB device */
 static void dissociate_dev(struct us_data *us)
 {
-       US_DEBUGP("-- %s\n", __FUNCTION__);
+       US_DEBUGP("-- %s\n", __func__);
 
        kfree(us->sensebuf);
 
index c815a40e167f33f7427f0c908514e0e93b685b7d..be76084c8d7e6a8f8429e389c9a5149e01d1db6d 100644 (file)
@@ -88,7 +88,7 @@ static int skel_open(struct inode *inode, struct file *file)
        interface = usb_find_interface(&skel_driver, subminor);
        if (!interface) {
                err ("%s - error, can't find device for minor %d",
-                    __FUNCTION__, subminor);
+                    __func__, subminor);
                retval = -ENODEV;
                goto exit;
        }
@@ -212,7 +212,7 @@ static void skel_write_bulk_callback(struct urb *urb)
 {
        struct usb_skel *dev;
 
-       dev = (struct usb_skel *)urb->context;
+       dev = urb->context;
 
        /* sync/async unlink faults aren't errors */
        if (urb->status) {
@@ -220,7 +220,7 @@ static void skel_write_bulk_callback(struct urb *urb)
                    urb->status == -ECONNRESET ||
                    urb->status == -ESHUTDOWN))
                        err("%s - nonzero write bulk status received: %d",
-                           __FUNCTION__, urb->status);
+                           __func__, urb->status);
 
                spin_lock(&dev->err_lock);
                dev->errors = urb->status;
@@ -301,7 +301,7 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
        retval = usb_submit_urb(urb, GFP_KERNEL);
        mutex_unlock(&dev->io_mutex);
        if (retval) {
-               err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);
+               err("%s - failed submitting write urb, error %d", __func__, retval);
                goto error_unanchor;
        }
 
index 1bd5fb30237d97a8037e5cc795ec41f1fef03a9d..e3dc8f8d0c3ec082530c846d99cce79d8a6f1892 100644 (file)
@@ -1930,6 +1930,20 @@ config FB_VIRTUAL
 
          If unsure, say N.
 
+config XEN_FBDEV_FRONTEND
+       tristate "Xen virtual frame buffer support"
+       depends on FB && XEN
+       select FB_SYS_FILLRECT
+       select FB_SYS_COPYAREA
+       select FB_SYS_IMAGEBLIT
+       select FB_SYS_FOPS
+       select FB_DEFERRED_IO
+       default y
+       help
+         This driver implements the front-end of the Xen virtual
+         frame buffer driver.  It communicates with a back-end
+         in another domain.
+
 source "drivers/video/omap/Kconfig"
 
 source "drivers/video/backlight/Kconfig"
index 11c0e5e05f219a36e5eda7ed3f0336d4ed54b32a..f172b9b73314ebc21845439919f6c18e63fd79cd 100644 (file)
@@ -114,6 +114,7 @@ obj-$(CONFIG_FB_PS3)                  += ps3fb.o
 obj-$(CONFIG_FB_SM501)            += sm501fb.o
 obj-$(CONFIG_FB_XILINX)           += xilinxfb.o
 obj-$(CONFIG_FB_OMAP)             += omap/
+obj-$(CONFIG_XEN_FBDEV_FRONTEND)  += xen-fbfront.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_UVESA)            += uvesafb.o
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
new file mode 100644 (file)
index 0000000..619a6f8
--- /dev/null
@@ -0,0 +1,550 @@
+/*
+ * Xen para-virtual frame buffer device
+ *
+ * Copyright (C) 2005-2006 Anthony Liguori <aliguori@us.ibm.com>
+ * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
+ *
+ *  Based on linux/drivers/video/q40fb.c
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+/*
+ * TODO:
+ *
+ * Switch to grant tables when they become capable of dealing with the
+ * frame buffer.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <asm/xen/hypervisor.h>
+#include <xen/events.h>
+#include <xen/page.h>
+#include <xen/interface/io/fbif.h>
+#include <xen/interface/io/protocols.h>
+#include <xen/xenbus.h>
+
+struct xenfb_info {
+       unsigned char           *fb;
+       struct fb_info          *fb_info;
+       int                     x1, y1, x2, y2; /* dirty rectangle,
+                                                  protected by dirty_lock */
+       spinlock_t              dirty_lock;
+       int                     nr_pages;
+       int                     irq;
+       struct xenfb_page       *page;
+       unsigned long           *mfns;
+       int                     update_wanted; /* XENFB_TYPE_UPDATE wanted */
+
+       struct xenbus_device    *xbdev;
+};
+
+static u32 xenfb_mem_len = XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8;
+
+static int xenfb_remove(struct xenbus_device *);
+static void xenfb_init_shared_page(struct xenfb_info *);
+static int xenfb_connect_backend(struct xenbus_device *, struct xenfb_info *);
+static void xenfb_disconnect_backend(struct xenfb_info *);
+
+static void xenfb_do_update(struct xenfb_info *info,
+                           int x, int y, int w, int h)
+{
+       union xenfb_out_event event;
+       u32 prod;
+
+       event.type = XENFB_TYPE_UPDATE;
+       event.update.x = x;
+       event.update.y = y;
+       event.update.width = w;
+       event.update.height = h;
+
+       prod = info->page->out_prod;
+       /* caller ensures !xenfb_queue_full() */
+       mb();                   /* ensure ring space available */
+       XENFB_OUT_RING_REF(info->page, prod) = event;
+       wmb();                  /* ensure ring contents visible */
+       info->page->out_prod = prod + 1;
+
+       notify_remote_via_irq(info->irq);
+}
+
+static int xenfb_queue_full(struct xenfb_info *info)
+{
+       u32 cons, prod;
+
+       prod = info->page->out_prod;
+       cons = info->page->out_cons;
+       return prod - cons == XENFB_OUT_RING_LEN;
+}
+
+static void xenfb_refresh(struct xenfb_info *info,
+                         int x1, int y1, int w, int h)
+{
+       unsigned long flags;
+       int y2 = y1 + h - 1;
+       int x2 = x1 + w - 1;
+
+       if (!info->update_wanted)
+               return;
+
+       spin_lock_irqsave(&info->dirty_lock, flags);
+
+       /* Combine with dirty rectangle: */
+       if (info->y1 < y1)
+               y1 = info->y1;
+       if (info->y2 > y2)
+               y2 = info->y2;
+       if (info->x1 < x1)
+               x1 = info->x1;
+       if (info->x2 > x2)
+               x2 = info->x2;
+
+       if (xenfb_queue_full(info)) {
+               /* Can't send right now, stash it in the dirty rectangle */
+               info->x1 = x1;
+               info->x2 = x2;
+               info->y1 = y1;
+               info->y2 = y2;
+               spin_unlock_irqrestore(&info->dirty_lock, flags);
+               return;
+       }
+
+       /* Clear dirty rectangle: */
+       info->x1 = info->y1 = INT_MAX;
+       info->x2 = info->y2 = 0;
+
+       spin_unlock_irqrestore(&info->dirty_lock, flags);
+
+       if (x1 <= x2 && y1 <= y2)
+               xenfb_do_update(info, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
+}
+
+static void xenfb_deferred_io(struct fb_info *fb_info,
+                             struct list_head *pagelist)
+{
+       struct xenfb_info *info = fb_info->par;
+       struct page *page;
+       unsigned long beg, end;
+       int y1, y2, miny, maxy;
+
+       miny = INT_MAX;
+       maxy = 0;
+       list_for_each_entry(page, pagelist, lru) {
+               beg = page->index << PAGE_SHIFT;
+               end = beg + PAGE_SIZE - 1;
+               y1 = beg / fb_info->fix.line_length;
+               y2 = end / fb_info->fix.line_length;
+               if (y2 >= fb_info->var.yres)
+                       y2 = fb_info->var.yres - 1;
+               if (miny > y1)
+                       miny = y1;
+               if (maxy < y2)
+                       maxy = y2;
+       }
+       xenfb_refresh(info, 0, miny, fb_info->var.xres, maxy - miny + 1);
+}
+
+static struct fb_deferred_io xenfb_defio = {
+       .delay          = HZ / 20,
+       .deferred_io    = xenfb_deferred_io,
+};
+
+static int xenfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+                          unsigned blue, unsigned transp,
+                          struct fb_info *info)
+{
+       u32 v;
+
+       if (regno > info->cmap.len)
+               return 1;
+
+#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
+       red = CNVT_TOHW(red, info->var.red.length);
+       green = CNVT_TOHW(green, info->var.green.length);
+       blue = CNVT_TOHW(blue, info->var.blue.length);
+       transp = CNVT_TOHW(transp, info->var.transp.length);
+#undef CNVT_TOHW
+
+       v = (red << info->var.red.offset) |
+           (green << info->var.green.offset) |
+           (blue << info->var.blue.offset);
+
+       switch (info->var.bits_per_pixel) {
+       case 16:
+       case 24:
+       case 32:
+               ((u32 *)info->pseudo_palette)[regno] = v;
+               break;
+       }
+
+       return 0;
+}
+
+static void xenfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+{
+       struct xenfb_info *info = p->par;
+
+       sys_fillrect(p, rect);
+       xenfb_refresh(info, rect->dx, rect->dy, rect->width, rect->height);
+}
+
+static void xenfb_imageblit(struct fb_info *p, const struct fb_image *image)
+{
+       struct xenfb_info *info = p->par;
+
+       sys_imageblit(p, image);
+       xenfb_refresh(info, image->dx, image->dy, image->width, image->height);
+}
+
+static void xenfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+{
+       struct xenfb_info *info = p->par;
+
+       sys_copyarea(p, area);
+       xenfb_refresh(info, area->dx, area->dy, area->width, area->height);
+}
+
+static ssize_t xenfb_write(struct fb_info *p, const char __user *buf,
+                       size_t count, loff_t *ppos)
+{
+       struct xenfb_info *info = p->par;
+       ssize_t res;
+
+       res = fb_sys_write(p, buf, count, ppos);
+       xenfb_refresh(info, 0, 0, info->page->width, info->page->height);
+       return res;
+}
+
+static struct fb_ops xenfb_fb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_read        = fb_sys_read,
+       .fb_write       = xenfb_write,
+       .fb_setcolreg   = xenfb_setcolreg,
+       .fb_fillrect    = xenfb_fillrect,
+       .fb_copyarea    = xenfb_copyarea,
+       .fb_imageblit   = xenfb_imageblit,
+};
+
+static irqreturn_t xenfb_event_handler(int rq, void *dev_id)
+{
+       /*
+        * No in events recognized, simply ignore them all.
+        * If you need to recognize some, see xen-kbdfront's
+        * input_handler() for how to do that.
+        */
+       struct xenfb_info *info = dev_id;
+       struct xenfb_page *page = info->page;
+
+       if (page->in_cons != page->in_prod) {
+               info->page->in_cons = info->page->in_prod;
+               notify_remote_via_irq(info->irq);
+       }
+
+       /* Flush dirty rectangle: */
+       xenfb_refresh(info, INT_MAX, INT_MAX, -INT_MAX, -INT_MAX);
+
+       return IRQ_HANDLED;
+}
+
+static int __devinit xenfb_probe(struct xenbus_device *dev,
+                                const struct xenbus_device_id *id)
+{
+       struct xenfb_info *info;
+       struct fb_info *fb_info;
+       int ret;
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (info == NULL) {
+               xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
+               return -ENOMEM;
+       }
+       dev->dev.driver_data = info;
+       info->xbdev = dev;
+       info->irq = -1;
+       info->x1 = info->y1 = INT_MAX;
+       spin_lock_init(&info->dirty_lock);
+
+       info->fb = vmalloc(xenfb_mem_len);
+       if (info->fb == NULL)
+               goto error_nomem;
+       memset(info->fb, 0, xenfb_mem_len);
+
+       info->nr_pages = (xenfb_mem_len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+       info->mfns = vmalloc(sizeof(unsigned long) * info->nr_pages);
+       if (!info->mfns)
+               goto error_nomem;
+
+       /* set up shared page */
+       info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+       if (!info->page)
+               goto error_nomem;
+
+       xenfb_init_shared_page(info);
+
+       /* abusing framebuffer_alloc() to allocate pseudo_palette */
+       fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL);
+       if (fb_info == NULL)
+               goto error_nomem;
+
+       /* complete the abuse: */
+       fb_info->pseudo_palette = fb_info->par;
+       fb_info->par = info;
+
+       fb_info->screen_base = info->fb;
+
+       fb_info->fbops = &xenfb_fb_ops;
+       fb_info->var.xres_virtual = fb_info->var.xres = info->page->width;
+       fb_info->var.yres_virtual = fb_info->var.yres = info->page->height;
+       fb_info->var.bits_per_pixel = info->page->depth;
+
+       fb_info->var.red = (struct fb_bitfield){16, 8, 0};
+       fb_info->var.green = (struct fb_bitfield){8, 8, 0};
+       fb_info->var.blue = (struct fb_bitfield){0, 8, 0};
+
+       fb_info->var.activate = FB_ACTIVATE_NOW;
+       fb_info->var.height = -1;
+       fb_info->var.width = -1;
+       fb_info->var.vmode = FB_VMODE_NONINTERLACED;
+
+       fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
+       fb_info->fix.line_length = info->page->line_length;
+       fb_info->fix.smem_start = 0;
+       fb_info->fix.smem_len = xenfb_mem_len;
+       strcpy(fb_info->fix.id, "xen");
+       fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
+       fb_info->fix.accel = FB_ACCEL_NONE;
+
+       fb_info->flags = FBINFO_FLAG_DEFAULT;
+
+       ret = fb_alloc_cmap(&fb_info->cmap, 256, 0);
+       if (ret < 0) {
+               framebuffer_release(fb_info);
+               xenbus_dev_fatal(dev, ret, "fb_alloc_cmap");
+               goto error;
+       }
+
+       fb_info->fbdefio = &xenfb_defio;
+       fb_deferred_io_init(fb_info);
+
+       ret = register_framebuffer(fb_info);
+       if (ret) {
+               fb_deferred_io_cleanup(fb_info);
+               fb_dealloc_cmap(&fb_info->cmap);
+               framebuffer_release(fb_info);
+               xenbus_dev_fatal(dev, ret, "register_framebuffer");
+               goto error;
+       }
+       info->fb_info = fb_info;
+
+       ret = xenfb_connect_backend(dev, info);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+
+ error_nomem:
+       ret = -ENOMEM;
+       xenbus_dev_fatal(dev, ret, "allocating device memory");
+ error:
+       xenfb_remove(dev);
+       return ret;
+}
+
+static int xenfb_resume(struct xenbus_device *dev)
+{
+       struct xenfb_info *info = dev->dev.driver_data;
+
+       xenfb_disconnect_backend(info);
+       xenfb_init_shared_page(info);
+       return xenfb_connect_backend(dev, info);
+}
+
+static int xenfb_remove(struct xenbus_device *dev)
+{
+       struct xenfb_info *info = dev->dev.driver_data;
+
+       xenfb_disconnect_backend(info);
+       if (info->fb_info) {
+               fb_deferred_io_cleanup(info->fb_info);
+               unregister_framebuffer(info->fb_info);
+               fb_dealloc_cmap(&info->fb_info->cmap);
+               framebuffer_release(info->fb_info);
+       }
+       free_page((unsigned long)info->page);
+       vfree(info->mfns);
+       vfree(info->fb);
+       kfree(info);
+
+       return 0;
+}
+
+static unsigned long vmalloc_to_mfn(void *address)
+{
+       return pfn_to_mfn(vmalloc_to_pfn(address));
+}
+
+static void xenfb_init_shared_page(struct xenfb_info *info)
+{
+       int i;
+
+       for (i = 0; i < info->nr_pages; i++)
+               info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE);
+
+       info->page->pd[0] = vmalloc_to_mfn(info->mfns);
+       info->page->pd[1] = 0;
+       info->page->width = XENFB_WIDTH;
+       info->page->height = XENFB_HEIGHT;
+       info->page->depth = XENFB_DEPTH;
+       info->page->line_length = (info->page->depth / 8) * info->page->width;
+       info->page->mem_length = xenfb_mem_len;
+       info->page->in_cons = info->page->in_prod = 0;
+       info->page->out_cons = info->page->out_prod = 0;
+}
+
+static int xenfb_connect_backend(struct xenbus_device *dev,
+                                struct xenfb_info *info)
+{
+       int ret, evtchn;
+       struct xenbus_transaction xbt;
+
+       ret = xenbus_alloc_evtchn(dev, &evtchn);
+       if (ret)
+               return ret;
+       ret = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler,
+                                       0, dev->devicetype, info);
+       if (ret < 0) {
+               xenbus_free_evtchn(dev, evtchn);
+               xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
+               return ret;
+       }
+       info->irq = ret;
+
+ again:
+       ret = xenbus_transaction_start(&xbt);
+       if (ret) {
+               xenbus_dev_fatal(dev, ret, "starting transaction");
+               return ret;
+       }
+       ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
+                           virt_to_mfn(info->page));
+       if (ret)
+               goto error_xenbus;
+       ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
+                           evtchn);
+       if (ret)
+               goto error_xenbus;
+       ret = xenbus_printf(xbt, dev->nodename, "protocol", "%s",
+                           XEN_IO_PROTO_ABI_NATIVE);
+       if (ret)
+               goto error_xenbus;
+       ret = xenbus_printf(xbt, dev->nodename, "feature-update", "1");
+       if (ret)
+               goto error_xenbus;
+       ret = xenbus_transaction_end(xbt, 0);
+       if (ret) {
+               if (ret == -EAGAIN)
+                       goto again;
+               xenbus_dev_fatal(dev, ret, "completing transaction");
+               return ret;
+       }
+
+       xenbus_switch_state(dev, XenbusStateInitialised);
+       return 0;
+
+ error_xenbus:
+       xenbus_transaction_end(xbt, 1);
+       xenbus_dev_fatal(dev, ret, "writing xenstore");
+       return ret;
+}
+
+static void xenfb_disconnect_backend(struct xenfb_info *info)
+{
+       if (info->irq >= 0)
+               unbind_from_irqhandler(info->irq, info);
+       info->irq = -1;
+}
+
+static void xenfb_backend_changed(struct xenbus_device *dev,
+                                 enum xenbus_state backend_state)
+{
+       struct xenfb_info *info = dev->dev.driver_data;
+       int val;
+
+       switch (backend_state) {
+       case XenbusStateInitialising:
+       case XenbusStateInitialised:
+       case XenbusStateUnknown:
+       case XenbusStateClosed:
+               break;
+
+       case XenbusStateInitWait:
+InitWait:
+               xenbus_switch_state(dev, XenbusStateConnected);
+               break;
+
+       case XenbusStateConnected:
+               /*
+                * Work around xenbus race condition: If backend goes
+                * through InitWait to Connected fast enough, we can
+                * get Connected twice here.
+                */
+               if (dev->state != XenbusStateConnected)
+                       goto InitWait; /* no InitWait seen yet, fudge it */
+
+               if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+                                "request-update", "%d", &val) < 0)
+                       val = 0;
+               if (val)
+                       info->update_wanted = 1;
+               break;
+
+       case XenbusStateClosing:
+               xenbus_frontend_closed(dev);
+               break;
+       }
+}
+
+static struct xenbus_device_id xenfb_ids[] = {
+       { "vfb" },
+       { "" }
+};
+
+static struct xenbus_driver xenfb = {
+       .name = "vfb",
+       .owner = THIS_MODULE,
+       .ids = xenfb_ids,
+       .probe = xenfb_probe,
+       .remove = xenfb_remove,
+       .resume = xenfb_resume,
+       .otherend_changed = xenfb_backend_changed,
+};
+
+static int __init xenfb_init(void)
+{
+       if (!is_running_on_xen())
+               return -ENODEV;
+
+       /* Nothing to do if running in dom0. */
+       if (is_initial_xendomain())
+               return -ENODEV;
+
+       return xenbus_register_frontend(&xenfb);
+}
+
+static void __exit xenfb_cleanup(void)
+{
+       xenbus_unregister_driver(&xenfb);
+}
+
+module_init(xenfb_init);
+module_exit(xenfb_cleanup);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
new file mode 100644 (file)
index 0000000..4b75a16
--- /dev/null
@@ -0,0 +1,19 @@
+config XEN_BALLOON
+       bool "Xen memory balloon driver"
+       depends on XEN
+       default y
+       help
+         The balloon driver allows the Xen domain to request more memory from
+         the system to expand the domain's memory allocation, or alternatively
+         return unneeded memory to the system.
+
+config XEN_SCRUB_PAGES
+       bool "Scrub pages before returning them to system"
+       depends on XEN_BALLOON
+       default y
+       help
+         Scrub pages before returning them to the system for reuse by
+         other domains.  This makes sure that any confidential data
+         is not accidentally visible to other domains.  Is it more
+         secure, but slightly less efficient.
+         If in doubt, say yes.
index 56592f0d6cefff998f305bcb4a0125f9bed28e0b..37af04f1ffd90d98a6ed33d5f29166d9d3747487 100644 (file)
@@ -1,2 +1,4 @@
-obj-y  += grant-table.o
+obj-y  += grant-table.o features.o events.o
 obj-y  += xenbus/
+obj-$(CONFIG_XEN_XENCOMM)      += xencomm.o
+obj-$(CONFIG_XEN_BALLOON)      += balloon.o
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
new file mode 100644 (file)
index 0000000..ab25ba6
--- /dev/null
@@ -0,0 +1,712 @@
+/******************************************************************************
+ * balloon.c
+ *
+ * Xen balloon driver - enables returning/claiming memory to/from Xen.
+ *
+ * Copyright (c) 2003, B Dragovic
+ * Copyright (c) 2003-2004, M Williamson, K Fraser
+ * Copyright (c) 2005 Dan M. Smith, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <linux/mutex.h>
+#include <linux/highmem.h>
+#include <linux/list.h>
+#include <linux/sysdev.h>
+
+#include <asm/xen/hypervisor.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/tlb.h>
+
+#include <xen/interface/memory.h>
+#include <xen/balloon.h>
+#include <xen/xenbus.h>
+#include <xen/features.h>
+#include <xen/page.h>
+
+#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
+
+#define BALLOON_CLASS_NAME "memory"
+
+struct balloon_stats {
+       /* We aim for 'current allocation' == 'target allocation'. */
+       unsigned long current_pages;
+       unsigned long target_pages;
+       /* We may hit the hard limit in Xen. If we do then we remember it. */
+       unsigned long hard_limit;
+       /*
+        * Drivers may alter the memory reservation independently, but they
+        * must inform the balloon driver so we avoid hitting the hard limit.
+        */
+       unsigned long driver_pages;
+       /* Number of pages in high- and low-memory balloons. */
+       unsigned long balloon_low;
+       unsigned long balloon_high;
+};
+
+static DEFINE_MUTEX(balloon_mutex);
+
+static struct sys_device balloon_sysdev;
+
+static int register_balloon(struct sys_device *sysdev);
+
+/*
+ * Protects atomic reservation decrease/increase against concurrent increases.
+ * Also protects non-atomic updates of current_pages and driver_pages, and
+ * balloon lists.
+ */
+static DEFINE_SPINLOCK(balloon_lock);
+
+static struct balloon_stats balloon_stats;
+
+/* We increase/decrease in batches which fit in a page */
+static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
+
+/* VM /proc information for memory */
+extern unsigned long totalram_pages;
+
+#ifdef CONFIG_HIGHMEM
+extern unsigned long totalhigh_pages;
+#define inc_totalhigh_pages() (totalhigh_pages++)
+#define dec_totalhigh_pages() (totalhigh_pages--)
+#else
+#define inc_totalhigh_pages() do {} while(0)
+#define dec_totalhigh_pages() do {} while(0)
+#endif
+
+/* List of ballooned pages, threaded through the mem_map array. */
+static LIST_HEAD(ballooned_pages);
+
+/* Main work function, always executed in process context. */
+static void balloon_process(struct work_struct *work);
+static DECLARE_WORK(balloon_worker, balloon_process);
+static struct timer_list balloon_timer;
+
+/* When ballooning out (allocating memory to return to Xen) we don't really
+   want the kernel to try too hard since that can trigger the oom killer. */
+#define GFP_BALLOON \
+       (GFP_HIGHUSER | __GFP_NOWARN | __GFP_NORETRY | __GFP_NOMEMALLOC)
+
+static void scrub_page(struct page *page)
+{
+#ifdef CONFIG_XEN_SCRUB_PAGES
+       if (PageHighMem(page)) {
+               void *v = kmap(page);
+               clear_page(v);
+               kunmap(v);
+       } else {
+               void *v = page_address(page);
+               clear_page(v);
+       }
+#endif
+}
+
+/* balloon_append: add the given page to the balloon. */
+static void balloon_append(struct page *page)
+{
+       /* Lowmem is re-populated first, so highmem pages go at list tail. */
+       if (PageHighMem(page)) {
+               list_add_tail(&page->lru, &ballooned_pages);
+               balloon_stats.balloon_high++;
+               dec_totalhigh_pages();
+       } else {
+               list_add(&page->lru, &ballooned_pages);
+               balloon_stats.balloon_low++;
+       }
+}
+
+/* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
+static struct page *balloon_retrieve(void)
+{
+       struct page *page;
+
+       if (list_empty(&ballooned_pages))
+               return NULL;
+
+       page = list_entry(ballooned_pages.next, struct page, lru);
+       list_del(&page->lru);
+
+       if (PageHighMem(page)) {
+               balloon_stats.balloon_high--;
+               inc_totalhigh_pages();
+       }
+       else
+               balloon_stats.balloon_low--;
+
+       return page;
+}
+
+static struct page *balloon_first_page(void)
+{
+       if (list_empty(&ballooned_pages))
+               return NULL;
+       return list_entry(ballooned_pages.next, struct page, lru);
+}
+
+static struct page *balloon_next_page(struct page *page)
+{
+       struct list_head *next = page->lru.next;
+       if (next == &ballooned_pages)
+               return NULL;
+       return list_entry(next, struct page, lru);
+}
+
+static void balloon_alarm(unsigned long unused)
+{
+       schedule_work(&balloon_worker);
+}
+
+static unsigned long current_target(void)
+{
+       unsigned long target = min(balloon_stats.target_pages, balloon_stats.hard_limit);
+
+       target = min(target,
+                    balloon_stats.current_pages +
+                    balloon_stats.balloon_low +
+                    balloon_stats.balloon_high);
+
+       return target;
+}
+
+static int increase_reservation(unsigned long nr_pages)
+{
+       unsigned long  pfn, i, flags;
+       struct page   *page;
+       long           rc;
+       struct xen_memory_reservation reservation = {
+               .address_bits = 0,
+               .extent_order = 0,
+               .domid        = DOMID_SELF
+       };
+
+       if (nr_pages > ARRAY_SIZE(frame_list))
+               nr_pages = ARRAY_SIZE(frame_list);
+
+       spin_lock_irqsave(&balloon_lock, flags);
+
+       page = balloon_first_page();
+       for (i = 0; i < nr_pages; i++) {
+               BUG_ON(page == NULL);
+               frame_list[i] = page_to_pfn(page);;
+               page = balloon_next_page(page);
+       }
+
+       reservation.extent_start = (unsigned long)frame_list;
+       reservation.nr_extents   = nr_pages;
+       rc = HYPERVISOR_memory_op(
+               XENMEM_populate_physmap, &reservation);
+       if (rc < nr_pages) {
+               if (rc > 0) {
+                       int ret;
+
+                       /* We hit the Xen hard limit: reprobe. */
+                       reservation.nr_extents = rc;
+                       ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+                                       &reservation);
+                       BUG_ON(ret != rc);
+               }
+               if (rc >= 0)
+                       balloon_stats.hard_limit = (balloon_stats.current_pages + rc -
+                                                   balloon_stats.driver_pages);
+               goto out;
+       }
+
+       for (i = 0; i < nr_pages; i++) {
+               page = balloon_retrieve();
+               BUG_ON(page == NULL);
+
+               pfn = page_to_pfn(page);
+               BUG_ON(!xen_feature(XENFEAT_auto_translated_physmap) &&
+                      phys_to_machine_mapping_valid(pfn));
+
+               set_phys_to_machine(pfn, frame_list[i]);
+
+               /* Link back into the page tables if not highmem. */
+               if (pfn < max_low_pfn) {
+                       int ret;
+                       ret = HYPERVISOR_update_va_mapping(
+                               (unsigned long)__va(pfn << PAGE_SHIFT),
+                               mfn_pte(frame_list[i], PAGE_KERNEL),
+                               0);
+                       BUG_ON(ret);
+               }
+
+               /* Relinquish the page back to the allocator. */
+               ClearPageReserved(page);
+               init_page_count(page);
+               __free_page(page);
+       }
+
+       balloon_stats.current_pages += nr_pages;
+       totalram_pages = balloon_stats.current_pages;
+
+ out:
+       spin_unlock_irqrestore(&balloon_lock, flags);
+
+       return 0;
+}
+
+static int decrease_reservation(unsigned long nr_pages)
+{
+       unsigned long  pfn, i, flags;
+       struct page   *page;
+       int            need_sleep = 0;
+       int ret;
+       struct xen_memory_reservation reservation = {
+               .address_bits = 0,
+               .extent_order = 0,
+               .domid        = DOMID_SELF
+       };
+
+       if (nr_pages > ARRAY_SIZE(frame_list))
+               nr_pages = ARRAY_SIZE(frame_list);
+
+       for (i = 0; i < nr_pages; i++) {
+               if ((page = alloc_page(GFP_BALLOON)) == NULL) {
+                       nr_pages = i;
+                       need_sleep = 1;
+                       break;
+               }
+
+               pfn = page_to_pfn(page);
+               frame_list[i] = pfn_to_mfn(pfn);
+
+               scrub_page(page);
+       }
+
+       /* Ensure that ballooned highmem pages don't have kmaps. */
+       kmap_flush_unused();
+       flush_tlb_all();
+
+       spin_lock_irqsave(&balloon_lock, flags);
+
+       /* No more mappings: invalidate P2M and add to balloon. */
+       for (i = 0; i < nr_pages; i++) {
+               pfn = mfn_to_pfn(frame_list[i]);
+               set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+               balloon_append(pfn_to_page(pfn));
+       }
+
+       reservation.extent_start = (unsigned long)frame_list;
+       reservation.nr_extents   = nr_pages;
+       ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
+       BUG_ON(ret != nr_pages);
+
+       balloon_stats.current_pages -= nr_pages;
+       totalram_pages = balloon_stats.current_pages;
+
+       spin_unlock_irqrestore(&balloon_lock, flags);
+
+       return need_sleep;
+}
+
+/*
+ * We avoid multiple worker processes conflicting via the balloon mutex.
+ * We may of course race updates of the target counts (which are protected
+ * by the balloon lock), or with changes to the Xen hard limit, but we will
+ * recover from these in time.
+ */
+static void balloon_process(struct work_struct *work)
+{
+       int need_sleep = 0;
+       long credit;
+
+       mutex_lock(&balloon_mutex);
+
+       do {
+               credit = current_target() - balloon_stats.current_pages;
+               if (credit > 0)
+                       need_sleep = (increase_reservation(credit) != 0);
+               if (credit < 0)
+                       need_sleep = (decrease_reservation(-credit) != 0);
+
+#ifndef CONFIG_PREEMPT
+               if (need_resched())
+                       schedule();
+#endif
+       } while ((credit != 0) && !need_sleep);
+
+       /* Schedule more work if there is some still to be done. */
+       if (current_target() != balloon_stats.current_pages)
+               mod_timer(&balloon_timer, jiffies + HZ);
+
+       mutex_unlock(&balloon_mutex);
+}
+
+/* Resets the Xen limit, sets new target, and kicks off processing. */
+void balloon_set_new_target(unsigned long target)
+{
+       /* No need for lock. Not read-modify-write updates. */
+       balloon_stats.hard_limit   = ~0UL;
+       balloon_stats.target_pages = target;
+       schedule_work(&balloon_worker);
+}
+
+static struct xenbus_watch target_watch =
+{
+       .node = "memory/target"
+};
+
+/* React to a change in the target key */
+static void watch_target(struct xenbus_watch *watch,
+                        const char **vec, unsigned int len)
+{
+       unsigned long long new_target;
+       int err;
+
+       err = xenbus_scanf(XBT_NIL, "memory", "target", "%llu", &new_target);
+       if (err != 1) {
+               /* This is ok (for domain0 at least) - so just return */
+               return;
+       }
+
+       /* The given memory/target value is in KiB, so it needs converting to
+        * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10.
+        */
+       balloon_set_new_target(new_target >> (PAGE_SHIFT - 10));
+}
+
+static int balloon_init_watcher(struct notifier_block *notifier,
+                               unsigned long event,
+                               void *data)
+{
+       int err;
+
+       err = register_xenbus_watch(&target_watch);
+       if (err)
+               printk(KERN_ERR "Failed to set balloon watcher\n");
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block xenstore_notifier;
+
+static int __init balloon_init(void)
+{
+       unsigned long pfn;
+       struct page *page;
+
+       if (!is_running_on_xen())
+               return -ENODEV;
+
+       pr_info("xen_balloon: Initialising balloon driver.\n");
+
+       balloon_stats.current_pages = min(xen_start_info->nr_pages, max_pfn);
+       totalram_pages   = balloon_stats.current_pages;
+       balloon_stats.target_pages  = balloon_stats.current_pages;
+       balloon_stats.balloon_low   = 0;
+       balloon_stats.balloon_high  = 0;
+       balloon_stats.driver_pages  = 0UL;
+       balloon_stats.hard_limit    = ~0UL;
+
+       init_timer(&balloon_timer);
+       balloon_timer.data = 0;
+       balloon_timer.function = balloon_alarm;
+
+       register_balloon(&balloon_sysdev);
+
+       /* Initialise the balloon with excess memory space. */
+       for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
+               page = pfn_to_page(pfn);
+               if (!PageReserved(page))
+                       balloon_append(page);
+       }
+
+       target_watch.callback = watch_target;
+       xenstore_notifier.notifier_call = balloon_init_watcher;
+
+       register_xenstore_notifier(&xenstore_notifier);
+
+       return 0;
+}
+
+subsys_initcall(balloon_init);
+
+static void balloon_exit(void)
+{
+    /* XXX - release balloon here */
+    return;
+}
+
+module_exit(balloon_exit);
+
+static void balloon_update_driver_allowance(long delta)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&balloon_lock, flags);
+       balloon_stats.driver_pages += delta;
+       spin_unlock_irqrestore(&balloon_lock, flags);
+}
+
+static int dealloc_pte_fn(
+       pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
+{
+       unsigned long mfn = pte_mfn(*pte);
+       int ret;
+       struct xen_memory_reservation reservation = {
+               .nr_extents   = 1,
+               .extent_order = 0,
+               .domid        = DOMID_SELF
+       };
+       reservation.extent_start = (unsigned long)&mfn;
+       set_pte_at(&init_mm, addr, pte, __pte_ma(0ull));
+       set_phys_to_machine(__pa(addr) >> PAGE_SHIFT, INVALID_P2M_ENTRY);
+       ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
+       BUG_ON(ret != 1);
+       return 0;
+}
+
+static struct page **alloc_empty_pages_and_pagevec(int nr_pages)
+{
+       unsigned long vaddr, flags;
+       struct page *page, **pagevec;
+       int i, ret;
+
+       pagevec = kmalloc(sizeof(page) * nr_pages, GFP_KERNEL);
+       if (pagevec == NULL)
+               return NULL;
+
+       for (i = 0; i < nr_pages; i++) {
+               page = pagevec[i] = alloc_page(GFP_KERNEL);
+               if (page == NULL)
+                       goto err;
+
+               vaddr = (unsigned long)page_address(page);
+
+               scrub_page(page);
+
+               spin_lock_irqsave(&balloon_lock, flags);
+
+               if (xen_feature(XENFEAT_auto_translated_physmap)) {
+                       unsigned long gmfn = page_to_pfn(page);
+                       struct xen_memory_reservation reservation = {
+                               .nr_extents   = 1,
+                               .extent_order = 0,
+                               .domid        = DOMID_SELF
+                       };
+                       reservation.extent_start = (unsigned long)&gmfn;
+                       ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+                                                  &reservation);
+                       if (ret == 1)
+                               ret = 0; /* success */
+               } else {
+                       ret = apply_to_page_range(&init_mm, vaddr, PAGE_SIZE,
+                                                 dealloc_pte_fn, NULL);
+               }
+
+               if (ret != 0) {
+                       spin_unlock_irqrestore(&balloon_lock, flags);
+                       __free_page(page);
+                       goto err;
+               }
+
+               totalram_pages = --balloon_stats.current_pages;
+
+               spin_unlock_irqrestore(&balloon_lock, flags);
+       }
+
+ out:
+       schedule_work(&balloon_worker);
+       flush_tlb_all();
+       return pagevec;
+
+ err:
+       spin_lock_irqsave(&balloon_lock, flags);
+       while (--i >= 0)
+               balloon_append(pagevec[i]);
+       spin_unlock_irqrestore(&balloon_lock, flags);
+       kfree(pagevec);
+       pagevec = NULL;
+       goto out;
+}
+
+static void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages)
+{
+       unsigned long flags;
+       int i;
+
+       if (pagevec == NULL)
+               return;
+
+       spin_lock_irqsave(&balloon_lock, flags);
+       for (i = 0; i < nr_pages; i++) {
+               BUG_ON(page_count(pagevec[i]) != 1);
+               balloon_append(pagevec[i]);
+       }
+       spin_unlock_irqrestore(&balloon_lock, flags);
+
+       kfree(pagevec);
+
+       schedule_work(&balloon_worker);
+}
+
+static void balloon_release_driver_page(struct page *page)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&balloon_lock, flags);
+       balloon_append(page);
+       balloon_stats.driver_pages--;
+       spin_unlock_irqrestore(&balloon_lock, flags);
+
+       schedule_work(&balloon_worker);
+}
+
+
+#define BALLOON_SHOW(name, format, args...)                    \
+       static ssize_t show_##name(struct sys_device *dev,      \
+                                  char *buf)                   \
+       {                                                       \
+               return sprintf(buf, format, ##args);            \
+       }                                                       \
+       static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL)
+
+BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages));
+BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low));
+BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high));
+BALLOON_SHOW(hard_limit_kb,
+            (balloon_stats.hard_limit!=~0UL) ? "%lu\n" : "???\n",
+            (balloon_stats.hard_limit!=~0UL) ? PAGES2KB(balloon_stats.hard_limit) : 0);
+BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages));
+
+static ssize_t show_target_kb(struct sys_device *dev, char *buf)
+{
+       return sprintf(buf, "%lu\n", PAGES2KB(balloon_stats.target_pages));
+}
+
+static ssize_t store_target_kb(struct sys_device *dev,
+                              const char *buf,
+                              size_t count)
+{
+       char memstring[64], *endchar;
+       unsigned long long target_bytes;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       if (count <= 1)
+               return -EBADMSG; /* runt */
+       if (count > sizeof(memstring))
+               return -EFBIG;   /* too long */
+       strcpy(memstring, buf);
+
+       target_bytes = memparse(memstring, &endchar);
+       balloon_set_new_target(target_bytes >> PAGE_SHIFT);
+
+       return count;
+}
+
+static SYSDEV_ATTR(target_kb, S_IRUGO | S_IWUSR,
+                  show_target_kb, store_target_kb);
+
+static struct sysdev_attribute *balloon_attrs[] = {
+       &attr_target_kb,
+};
+
+static struct attribute *balloon_info_attrs[] = {
+       &attr_current_kb.attr,
+       &attr_low_kb.attr,
+       &attr_high_kb.attr,
+       &attr_hard_limit_kb.attr,
+       &attr_driver_kb.attr,
+       NULL
+};
+
+static struct attribute_group balloon_info_group = {
+       .name = "info",
+       .attrs = balloon_info_attrs,
+};
+
+static struct sysdev_class balloon_sysdev_class = {
+       .name = BALLOON_CLASS_NAME,
+};
+
+static int register_balloon(struct sys_device *sysdev)
+{
+       int i, error;
+
+       error = sysdev_class_register(&balloon_sysdev_class);
+       if (error)
+               return error;
+
+       sysdev->id = 0;
+       sysdev->cls = &balloon_sysdev_class;
+
+       error = sysdev_register(sysdev);
+       if (error) {
+               sysdev_class_unregister(&balloon_sysdev_class);
+               return error;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++) {
+               error = sysdev_create_file(sysdev, balloon_attrs[i]);
+               if (error)
+                       goto fail;
+       }
+
+       error = sysfs_create_group(&sysdev->kobj, &balloon_info_group);
+       if (error)
+               goto fail;
+
+       return 0;
+
+ fail:
+       while (--i >= 0)
+               sysdev_remove_file(sysdev, balloon_attrs[i]);
+       sysdev_unregister(sysdev);
+       sysdev_class_unregister(&balloon_sysdev_class);
+       return error;
+}
+
+static void unregister_balloon(struct sys_device *sysdev)
+{
+       int i;
+
+       sysfs_remove_group(&sysdev->kobj, &balloon_info_group);
+       for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++)
+               sysdev_remove_file(sysdev, balloon_attrs[i]);
+       sysdev_unregister(sysdev);
+       sysdev_class_unregister(&balloon_sysdev_class);
+}
+
+static void balloon_sysfs_exit(void)
+{
+       unregister_balloon(&balloon_sysdev);
+}
+
+MODULE_LICENSE("GPL");
similarity index 82%
rename from arch/x86/xen/events.c
rename to drivers/xen/events.c
index dcf613e17581448926794286ac9c1fad05011857..4f0f22b020ea4aa192dbab56cba76edd6076a837 100644 (file)
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
 
+#include <xen/xen-ops.h>
 #include <xen/events.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/event_channel.h>
 
-#include "xen-ops.h"
-
 /*
  * This lock protects updates to the following mapping and reference-count
  * arrays. The lock does not need to be acquired to read the mapping tables.
@@ -455,6 +454,53 @@ void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector)
        notify_remote_via_irq(irq);
 }
 
+irqreturn_t xen_debug_interrupt(int irq, void *dev_id)
+{
+       struct shared_info *sh = HYPERVISOR_shared_info;
+       int cpu = smp_processor_id();
+       int i;
+       unsigned long flags;
+       static DEFINE_SPINLOCK(debug_lock);
+
+       spin_lock_irqsave(&debug_lock, flags);
+
+       printk("vcpu %d\n  ", cpu);
+
+       for_each_online_cpu(i) {
+               struct vcpu_info *v = per_cpu(xen_vcpu, i);
+               printk("%d: masked=%d pending=%d event_sel %08lx\n  ", i,
+                       (get_irq_regs() && i == cpu) ? xen_irqs_disabled(get_irq_regs()) : v->evtchn_upcall_mask,
+                       v->evtchn_upcall_pending,
+                       v->evtchn_pending_sel);
+       }
+       printk("pending:\n   ");
+       for(i = ARRAY_SIZE(sh->evtchn_pending)-1; i >= 0; i--)
+               printk("%08lx%s", sh->evtchn_pending[i],
+                       i % 8 == 0 ? "\n   " : " ");
+       printk("\nmasks:\n   ");
+       for(i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--)
+               printk("%08lx%s", sh->evtchn_mask[i],
+                       i % 8 == 0 ? "\n   " : " ");
+
+       printk("\nunmasked:\n   ");
+       for(i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--)
+               printk("%08lx%s", sh->evtchn_pending[i] & ~sh->evtchn_mask[i],
+                       i % 8 == 0 ? "\n   " : " ");
+
+       printk("\npending list:\n");
+       for(i = 0; i < NR_EVENT_CHANNELS; i++) {
+               if (sync_test_bit(i, sh->evtchn_pending)) {
+                       printk("  %d: event %d -> irq %d\n",
+                               cpu_evtchn[i], i,
+                               evtchn_to_irq[i]);
+               }
+       }
+
+       spin_unlock_irqrestore(&debug_lock, flags);
+
+       return IRQ_HANDLED;
+}
+
 
 /*
  * Search the CPUs pending events bitmasks.  For each one found, map
@@ -470,29 +516,44 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
        int cpu = get_cpu();
        struct shared_info *s = HYPERVISOR_shared_info;
        struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
-       unsigned long pending_words;
+       static DEFINE_PER_CPU(unsigned, nesting_count);
+       unsigned count;
 
-       vcpu_info->evtchn_upcall_pending = 0;
+       do {
+               unsigned long pending_words;
 
-       /* NB. No need for a barrier here -- XCHG is a barrier on x86. */
-       pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0);
-       while (pending_words != 0) {
-               unsigned long pending_bits;
-               int word_idx = __ffs(pending_words);
-               pending_words &= ~(1UL << word_idx);
+               vcpu_info->evtchn_upcall_pending = 0;
 
-               while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) {
-                       int bit_idx = __ffs(pending_bits);
-                       int port = (word_idx * BITS_PER_LONG) + bit_idx;
-                       int irq = evtchn_to_irq[port];
+               if (__get_cpu_var(nesting_count)++)
+                       goto out;
 
-                       if (irq != -1) {
-                               regs->orig_ax = ~irq;
-                               do_IRQ(regs);
+#ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
+               /* Clear master flag /before/ clearing selector flag. */
+               rmb();
+#endif
+               pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0);
+               while (pending_words != 0) {
+                       unsigned long pending_bits;
+                       int word_idx = __ffs(pending_words);
+                       pending_words &= ~(1UL << word_idx);
+
+                       while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) {
+                               int bit_idx = __ffs(pending_bits);
+                               int port = (word_idx * BITS_PER_LONG) + bit_idx;
+                               int irq = evtchn_to_irq[port];
+
+                               if (irq != -1)
+                                       xen_do_IRQ(irq, regs);
                        }
                }
-       }
 
+               BUG_ON(!irqs_disabled());
+
+               count = __get_cpu_var(nesting_count);
+               __get_cpu_var(nesting_count) = 0;
+       } while(count != 1);
+
+out:
        put_cpu();
 }
 
@@ -525,6 +586,22 @@ static void set_affinity_irq(unsigned irq, cpumask_t dest)
        rebind_irq_to_cpu(irq, tcpu);
 }
 
+int resend_irq_on_evtchn(unsigned int irq)
+{
+       int masked, evtchn = evtchn_from_irq(irq);
+       struct shared_info *s = HYPERVISOR_shared_info;
+
+       if (!VALID_EVTCHN(evtchn))
+               return 1;
+
+       masked = sync_test_and_set_bit(evtchn, s->evtchn_mask);
+       sync_set_bit(evtchn, s->evtchn_pending);
+       if (!masked)
+               unmask_evtchn(evtchn);
+
+       return 1;
+}
+
 static void enable_dynirq(unsigned int irq)
 {
        int evtchn = evtchn_from_irq(irq);
@@ -554,10 +631,16 @@ static void ack_dynirq(unsigned int irq)
 static int retrigger_dynirq(unsigned int irq)
 {
        int evtchn = evtchn_from_irq(irq);
+       struct shared_info *sh = HYPERVISOR_shared_info;
        int ret = 0;
 
        if (VALID_EVTCHN(evtchn)) {
-               set_evtchn(evtchn);
+               int masked;
+
+               masked = sync_test_and_set_bit(evtchn, sh->evtchn_mask);
+               sync_set_bit(evtchn, sh->evtchn_pending);
+               if (!masked)
+                       unmask_evtchn(evtchn);
                ret = 1;
        }
 
index d85dc6d41c2aee930f79f08cb31ebecb406e948c..52b6b41b909de5a142fc5eee2c96255e900c6039 100644 (file)
@@ -439,24 +439,6 @@ static inline unsigned int max_nr_grant_frames(void)
        return xen_max;
 }
 
-static int map_pte_fn(pte_t *pte, struct page *pmd_page,
-                     unsigned long addr, void *data)
-{
-       unsigned long **frames = (unsigned long **)data;
-
-       set_pte_at(&init_mm, addr, pte, mfn_pte((*frames)[0], PAGE_KERNEL));
-       (*frames)++;
-       return 0;
-}
-
-static int unmap_pte_fn(pte_t *pte, struct page *pmd_page,
-                       unsigned long addr, void *data)
-{
-
-       set_pte_at(&init_mm, addr, pte, __pte(0));
-       return 0;
-}
-
 static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
 {
        struct gnttab_setup_table setup;
@@ -470,7 +452,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
 
        setup.dom        = DOMID_SELF;
        setup.nr_frames  = nr_gframes;
-       setup.frame_list = frames;
+       set_xen_guest_handle(setup.frame_list, frames);
 
        rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
        if (rc == -ENOSYS) {
@@ -480,17 +462,9 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
 
        BUG_ON(rc || setup.status);
 
-       if (shared == NULL) {
-               struct vm_struct *area;
-               area = alloc_vm_area(PAGE_SIZE * max_nr_grant_frames());
-               BUG_ON(area == NULL);
-               shared = area->addr;
-       }
-       rc = apply_to_page_range(&init_mm, (unsigned long)shared,
-                                PAGE_SIZE * nr_gframes,
-                                map_pte_fn, &frames);
+       rc = arch_gnttab_map_shared(frames, nr_gframes, max_nr_grant_frames(),
+                                   &shared);
        BUG_ON(rc);
-       frames -= nr_gframes; /* adjust after map_pte_fn() */
 
        kfree(frames);
 
@@ -506,10 +480,7 @@ static int gnttab_resume(void)
 
 static int gnttab_suspend(void)
 {
-       apply_to_page_range(&init_mm, (unsigned long)shared,
-                           PAGE_SIZE * nr_grant_frames,
-                           unmap_pte_fn, NULL);
-
+       arch_gnttab_unmap_shared(shared, nr_grant_frames);
        return 0;
 }
 
index 9fd2f70ab46d873af33fdc1e6f14f0e9f2fd9826..0f86b0ff78796517838399d956e90577924f56e5 100644 (file)
@@ -399,7 +399,7 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
 
        *vaddr = NULL;
 
-       area = alloc_vm_area(PAGE_SIZE);
+       area = xen_alloc_vm_area(PAGE_SIZE);
        if (!area)
                return -ENOMEM;
 
@@ -409,7 +409,7 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
                BUG();
 
        if (op.status != GNTST_okay) {
-               free_vm_area(area);
+               xen_free_vm_area(area);
                xenbus_dev_fatal(dev, op.status,
                                 "mapping in shared page %d from domain %d",
                                 gnt_ref, dev->otherend_id);
@@ -508,7 +508,7 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
                BUG();
 
        if (op.status == GNTST_okay)
-               free_vm_area(area);
+               xen_free_vm_area(area);
        else
                xenbus_dev_error(dev, op.status,
                                 "unmapping page at handle %d error %d",
index 4750de316ad36fbde50524d81beac8f10cfd424f..57ceb5346b749338e153ccdbeaf4bf5ceb09c19f 100644 (file)
@@ -88,6 +88,16 @@ int xenbus_match(struct device *_dev, struct device_driver *_drv)
        return match_device(drv->ids, to_xenbus_device(_dev)) != NULL;
 }
 
+static int xenbus_uevent(struct device *_dev, struct kobj_uevent_env *env)
+{
+       struct xenbus_device *dev = to_xenbus_device(_dev);
+
+       if (add_uevent_var(env, "MODALIAS=xen:%s", dev->devicetype))
+               return -ENOMEM;
+
+       return 0;
+}
+
 /* device/<type>/<id> => <type>-<id> */
 static int frontend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
 {
@@ -166,6 +176,7 @@ static struct xen_bus_type xenbus_frontend = {
        .bus = {
                .name     = "xen",
                .match    = xenbus_match,
+               .uevent   = xenbus_uevent,
                .probe    = xenbus_dev_probe,
                .remove   = xenbus_dev_remove,
                .shutdown = xenbus_dev_shutdown,
@@ -438,6 +449,12 @@ static ssize_t xendev_show_devtype(struct device *dev,
 }
 DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL);
 
+static ssize_t xendev_show_modalias(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "xen:%s\n", to_xenbus_device(dev)->devicetype);
+}
+DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL);
 
 int xenbus_probe_node(struct xen_bus_type *bus,
                      const char *type,
@@ -492,10 +509,16 @@ int xenbus_probe_node(struct xen_bus_type *bus,
 
        err = device_create_file(&xendev->dev, &dev_attr_devtype);
        if (err)
-               goto fail_remove_file;
+               goto fail_remove_nodename;
+
+       err = device_create_file(&xendev->dev, &dev_attr_modalias);
+       if (err)
+               goto fail_remove_devtype;
 
        return 0;
-fail_remove_file:
+fail_remove_devtype:
+       device_remove_file(&xendev->dev, &dev_attr_devtype);
+fail_remove_nodename:
        device_remove_file(&xendev->dev, &dev_attr_nodename);
 fail_unregister:
        device_unregister(&xendev->dev);
@@ -846,6 +869,7 @@ static int is_disconnected_device(struct device *dev, void *data)
 {
        struct xenbus_device *xendev = to_xenbus_device(dev);
        struct device_driver *drv = data;
+       struct xenbus_driver *xendrv;
 
        /*
         * A device with no driver will never connect. We care only about
@@ -858,7 +882,9 @@ static int is_disconnected_device(struct device *dev, void *data)
        if (drv && (dev->driver != drv))
                return 0;
 
-       return (xendev->state != XenbusStateConnected);
+       xendrv = to_xenbus_driver(dev->driver);
+       return (xendev->state != XenbusStateConnected ||
+               (xendrv->is_ready && !xendrv->is_ready(xendev)));
 }
 
 static int exists_disconnected_device(struct device_driver *drv)
diff --git a/drivers/xen/xencomm.c b/drivers/xen/xencomm.c
new file mode 100644 (file)
index 0000000..797cb4e
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <xen/xencomm.h>
+#include <xen/interface/xen.h>
+#ifdef __ia64__
+#include <asm/xen/xencomm.h>   /* for is_kern_addr() */
+#endif
+
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
+
+static int xencomm_init(struct xencomm_desc *desc,
+                       void *buffer, unsigned long bytes)
+{
+       unsigned long recorded = 0;
+       int i = 0;
+
+       while ((recorded < bytes) && (i < desc->nr_addrs)) {
+               unsigned long vaddr = (unsigned long)buffer + recorded;
+               unsigned long paddr;
+               int offset;
+               int chunksz;
+
+               offset = vaddr % PAGE_SIZE; /* handle partial pages */
+               chunksz = min(PAGE_SIZE - offset, bytes - recorded);
+
+               paddr = xencomm_vtop(vaddr);
+               if (paddr == ~0UL) {
+                       printk(KERN_DEBUG "%s: couldn't translate vaddr %lx\n",
+                              __func__, vaddr);
+                       return -EINVAL;
+               }
+
+               desc->address[i++] = paddr;
+               recorded += chunksz;
+       }
+
+       if (recorded < bytes) {
+               printk(KERN_DEBUG
+                      "%s: could only translate %ld of %ld bytes\n",
+                      __func__, recorded, bytes);
+               return -ENOSPC;
+       }
+
+       /* mark remaining addresses invalid (just for safety) */
+       while (i < desc->nr_addrs)
+               desc->address[i++] = XENCOMM_INVALID;
+
+       desc->magic = XENCOMM_MAGIC;
+
+       return 0;
+}
+
+static struct xencomm_desc *xencomm_alloc(gfp_t gfp_mask,
+                                         void *buffer, unsigned long bytes)
+{
+       struct xencomm_desc *desc;
+       unsigned long buffer_ulong = (unsigned long)buffer;
+       unsigned long start = buffer_ulong & PAGE_MASK;
+       unsigned long end = (buffer_ulong + bytes) | ~PAGE_MASK;
+       unsigned long nr_addrs = (end - start + 1) >> PAGE_SHIFT;
+       unsigned long size = sizeof(*desc) +
+               sizeof(desc->address[0]) * nr_addrs;
+
+       /*
+        * slab allocator returns at least sizeof(void*) aligned pointer.
+        * When sizeof(*desc) > sizeof(void*), struct xencomm_desc might
+        * cross page boundary.
+        */
+       if (sizeof(*desc) > sizeof(void *)) {
+               unsigned long order = get_order(size);
+               desc = (struct xencomm_desc *)__get_free_pages(gfp_mask,
+                                                              order);
+               if (desc == NULL)
+                       return NULL;
+
+               desc->nr_addrs =
+                       ((PAGE_SIZE << order) - sizeof(struct xencomm_desc)) /
+                       sizeof(*desc->address);
+       } else {
+               desc = kmalloc(size, gfp_mask);
+               if (desc == NULL)
+                       return NULL;
+
+               desc->nr_addrs = nr_addrs;
+       }
+       return desc;
+}
+
+void xencomm_free(struct xencomm_handle *desc)
+{
+       if (desc && !((ulong)desc & XENCOMM_INLINE_FLAG)) {
+               struct xencomm_desc *desc__ = (struct xencomm_desc *)desc;
+               if (sizeof(*desc__) > sizeof(void *)) {
+                       unsigned long size = sizeof(*desc__) +
+                               sizeof(desc__->address[0]) * desc__->nr_addrs;
+                       unsigned long order = get_order(size);
+                       free_pages((unsigned long)__va(desc), order);
+               } else
+                       kfree(__va(desc));
+       }
+}
+
+static int xencomm_create(void *buffer, unsigned long bytes,
+                         struct xencomm_desc **ret, gfp_t gfp_mask)
+{
+       struct xencomm_desc *desc;
+       int rc;
+
+       pr_debug("%s: %p[%ld]\n", __func__, buffer, bytes);
+
+       if (bytes == 0) {
+               /* don't create a descriptor; Xen recognizes NULL. */
+               BUG_ON(buffer != NULL);
+               *ret = NULL;
+               return 0;
+       }
+
+       BUG_ON(buffer == NULL); /* 'bytes' is non-zero */
+
+       desc = xencomm_alloc(gfp_mask, buffer, bytes);
+       if (!desc) {
+               printk(KERN_DEBUG "%s failure\n", "xencomm_alloc");
+               return -ENOMEM;
+       }
+
+       rc = xencomm_init(desc, buffer, bytes);
+       if (rc) {
+               printk(KERN_DEBUG "%s failure: %d\n", "xencomm_init", rc);
+               xencomm_free((struct xencomm_handle *)__pa(desc));
+               return rc;
+       }
+
+       *ret = desc;
+       return 0;
+}
+
+/* check if memory address is within VMALLOC region  */
+static int is_phys_contiguous(unsigned long addr)
+{
+       if (!is_kernel_addr(addr))
+               return 0;
+
+       return (addr < VMALLOC_START) || (addr >= VMALLOC_END);
+}
+
+static struct xencomm_handle *xencomm_create_inline(void *ptr)
+{
+       unsigned long paddr;
+
+       BUG_ON(!is_phys_contiguous((unsigned long)ptr));
+
+       paddr = (unsigned long)xencomm_pa(ptr);
+       BUG_ON(paddr & XENCOMM_INLINE_FLAG);
+       return (struct xencomm_handle *)(paddr | XENCOMM_INLINE_FLAG);
+}
+
+/* "mini" routine, for stack-based communications: */
+static int xencomm_create_mini(void *buffer,
+       unsigned long bytes, struct xencomm_mini *xc_desc,
+       struct xencomm_desc **ret)
+{
+       int rc = 0;
+       struct xencomm_desc *desc;
+       BUG_ON(((unsigned long)xc_desc) % sizeof(*xc_desc) != 0);
+
+       desc = (void *)xc_desc;
+
+       desc->nr_addrs = XENCOMM_MINI_ADDRS;
+
+       rc = xencomm_init(desc, buffer, bytes);
+       if (!rc)
+               *ret = desc;
+
+       return rc;
+}
+
+struct xencomm_handle *xencomm_map(void *ptr, unsigned long bytes)
+{
+       int rc;
+       struct xencomm_desc *desc;
+
+       if (is_phys_contiguous((unsigned long)ptr))
+               return xencomm_create_inline(ptr);
+
+       rc = xencomm_create(ptr, bytes, &desc, GFP_KERNEL);
+
+       if (rc || desc == NULL)
+               return NULL;
+
+       return xencomm_pa(desc);
+}
+
+struct xencomm_handle *__xencomm_map_no_alloc(void *ptr, unsigned long bytes,
+                       struct xencomm_mini *xc_desc)
+{
+       int rc;
+       struct xencomm_desc *desc = NULL;
+
+       if (is_phys_contiguous((unsigned long)ptr))
+               return xencomm_create_inline(ptr);
+
+       rc = xencomm_create_mini(ptr, bytes, xc_desc,
+                               &desc);
+
+       if (rc)
+               return NULL;
+
+       return xencomm_pa(desc);
+}
index 678c02f1ae231306b8f2062ef6925bb69a4a6b71..a452ac67fc947cc4268f17dfb77605688e1ba188 100644 (file)
@@ -224,12 +224,11 @@ static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt)
 }
 
 static void
-v9fs_umount_begin(struct vfsmount *vfsmnt, int flags)
+v9fs_umount_begin(struct super_block *sb)
 {
-       struct v9fs_session_info *v9ses = vfsmnt->mnt_sb->s_fs_info;
+       struct v9fs_session_info *v9ses = sb->s_fs_info;
 
-       if (flags & MNT_FORCE)
-               v9fs_session_cancel(v9ses);
+       v9fs_session_cancel(v9ses);
 }
 
 static const struct super_operations v9fs_super_ops = {
index 5e1a4fb5cacb2a3715ad3552bd8e412fdae9b00c..9924581df6f6ccbc35520237cbdf8c9c079559f8 100644 (file)
@@ -543,7 +543,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
        unsigned long interp_load_addr = 0;
        unsigned long start_code, end_code, start_data, end_data;
        unsigned long reloc_func_desc = 0;
-       struct files_struct *files;
        int executable_stack = EXSTACK_DEFAULT;
        unsigned long def_flags = 0;
        struct {
@@ -593,20 +592,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                goto out_free_ph;
        }
 
-       files = current->files; /* Refcounted so ok */
-       retval = unshare_files();
-       if (retval < 0)
-               goto out_free_ph;
-       if (files == current->files) {
-               put_files_struct(files);
-               files = NULL;
-       }
-
-       /* exec will make our files private anyway, but for the a.out
-          loader stuff we need to do it earlier */
        retval = get_unused_fd();
        if (retval < 0)
-               goto out_free_fh;
+               goto out_free_ph;
        get_file(bprm->file);
        fd_install(elf_exec_fileno = retval, bprm->file);
 
@@ -728,12 +716,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
        if (retval)
                goto out_free_dentry;
 
-       /* Discard our unneeded old files struct */
-       if (files) {
-               put_files_struct(files);
-               files = NULL;
-       }
-
        /* OK, This is the point of no return */
        current->flags &= ~PF_FORKNOEXEC;
        current->mm->def_flags = def_flags;
@@ -1016,9 +998,6 @@ out_free_interp:
        kfree(elf_interpreter);
 out_free_file:
        sys_close(elf_exec_fileno);
-out_free_fh:
-       if (files)
-               reset_files_struct(current, files);
 out_free_ph:
        kfree(elf_phdata);
        goto out;
index b53c7e5f41bbcffd8f936642117ecfce5f258a21..dbf0ac0523de14d49edcc58b43ab7c62a407e406 100644 (file)
@@ -110,7 +110,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
        char *iname_addr = iname;
        int retval;
        int fd_binary = -1;
-       struct files_struct *files = NULL;
 
        retval = -ENOEXEC;
        if (!enabled)
@@ -133,21 +132,13 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 
        if (fmt->flags & MISC_FMT_OPEN_BINARY) {
 
-               files = current->files;
-               retval = unshare_files();
-               if (retval < 0)
-                       goto _ret;
-               if (files == current->files) {
-                       put_files_struct(files);
-                       files = NULL;
-               }
                /* if the binary should be opened on behalf of the
                 * interpreter than keep it open and assign descriptor
                 * to it */
                fd_binary = get_unused_fd();
                if (fd_binary < 0) {
                        retval = fd_binary;
-                       goto _unshare;
+                       goto _ret;
                }
                fd_install(fd_binary, bprm->file);
 
@@ -205,10 +196,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
        if (retval < 0)
                goto _error;
 
-       if (files) {
-               put_files_struct(files);
-               files = NULL;
-       }
 _ret:
        return retval;
 _error:
@@ -216,9 +203,6 @@ _error:
                sys_close(fd_binary);
        bprm->interp_flags = 0;
        bprm->interp_data = 0;
-_unshare:
-       if (files)
-               reset_files_struct(current, files);
        goto _ret;
 }
 
index 14c63527c762d8cdc8fc443dec512bd4f34e194f..fdc36bfd6a7beb8d1b63b91520ece0a7d2a347b7 100644 (file)
@@ -194,7 +194,6 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        unsigned long som_entry;
        struct som_hdr *som_ex;
        struct som_exec_auxhdr *hpuxhdr;
-       struct files_struct *files;
 
        /* Get the exec-header */
        som_ex = (struct som_hdr *) bprm->buf;
@@ -221,15 +220,6 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                goto out_free;
        }
 
-       files = current->files; /* Refcounted so ok */
-       retval = unshare_files();
-       if (retval < 0)
-               goto out_free;
-       if (files == current->files) {
-               put_files_struct(files);
-               files = NULL;
-       }
-
        retval = get_unused_fd();
        if (retval < 0)
                goto out_free;
index dbd91461853c97fc1c5c4538c53c6514570f85d4..05c9da6181c3793cd540c803053fc2bd21e08bbc 100644 (file)
@@ -8,7 +8,8 @@ of second share to disconnected server session (autoreconnect on this).
 Add ability to modify cifs acls for handling chmod (when mounted with
 cifsacl flag). Fix prefixpath path separator so we can handle mounts
 with prefixpaths longer than one directory (one path component) when
-mounted to Windows servers.
+mounted to Windows servers.  Fix slow file open when cifsacl
+enabled.
 
 Version 1.51
 ------------
index 50306229b0f9f822b4f4e6d53cca9b9a5986ec07..621aa1a85971394d37424e2a50c9cf71c9aa2146 100644 (file)
@@ -3,7 +3,14 @@ features such as hierarchical dfs like namespace, hardlinks, locking and more.
 It was designed to comply with the SNIA CIFS Technical Reference (which 
 supersedes the 1992 X/Open SMB Standard) as well as to perform best practice 
 practical interoperability with Windows 2000, Windows XP, Samba and equivalent 
-servers.  
+servers.  This code was developed in participation with the Protocol Freedom
+Information Foundation.
+
+Please see
+  http://protocolfreedom.org/ and
+  http://samba.org/samba/PFIF/
+for more details.
+
 
 For questions or bug reports please contact:
     sfrench@samba.org (sfrench@us.ibm.com) 
index 56c924033b78d73d382f1a391e00c4710bf3f01a..95024c066d89d6422e7a1adb233a7fb38e76473a 100644 (file)
 #include "dns_resolve.h"
 #include "cifs_debug.h"
 
-LIST_HEAD(cifs_dfs_automount_list);
+static LIST_HEAD(cifs_dfs_automount_list);
 
-/*
- * DFS functions
-*/
+static void cifs_dfs_expire_automounts(struct work_struct *work);
+static DECLARE_DELAYED_WORK(cifs_dfs_automount_task,
+                           cifs_dfs_expire_automounts);
+static int cifs_dfs_mountpoint_expiry_timeout = 500 * HZ;
+
+static void cifs_dfs_expire_automounts(struct work_struct *work)
+{
+       struct list_head *list = &cifs_dfs_automount_list;
+
+       mark_mounts_for_expiry(list);
+       if (!list_empty(list))
+               schedule_delayed_work(&cifs_dfs_automount_task,
+                                     cifs_dfs_mountpoint_expiry_timeout);
+}
 
-void dfs_shrink_umount_helper(struct vfsmount *vfsmnt)
+void cifs_dfs_release_automount_timer(void)
 {
-       mark_mounts_for_expiry(&cifs_dfs_automount_list);
-       mark_mounts_for_expiry(&cifs_dfs_automount_list);
+       BUG_ON(!list_empty(&cifs_dfs_automount_list));
+       cancel_delayed_work(&cifs_dfs_automount_task);
+       flush_scheduled_work();
 }
 
 /**
@@ -261,10 +273,11 @@ static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd,
        err = do_add_mount(newmnt, nd, nd->path.mnt->mnt_flags, mntlist);
        switch (err) {
        case 0:
-               dput(nd->path.dentry);
-               mntput(nd->path.mnt);
+               path_put(&nd->path);
                nd->path.mnt = newmnt;
                nd->path.dentry = dget(newmnt->mnt_root);
+               schedule_delayed_work(&cifs_dfs_automount_task,
+                                     cifs_dfs_mountpoint_expiry_timeout);
                break;
        case -EBUSY:
                /* someone else made a mount here whilst we were busy */
index 1cb5b0a9f2aca95b8790a8b6be3fae90157f9e68..e99d4faf5f022e5c3315dbd38b63e12e85ccf0e7 100644 (file)
@@ -516,7 +516,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
 
 /* Convert permission bits from mode to equivalent CIFS ACL */
 static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
-                               int acl_len, struct inode *inode, __u64 nmode)
+                               struct inode *inode, __u64 nmode)
 {
        int rc = 0;
        __u32 dacloffset;
@@ -692,14 +692,14 @@ void acl_to_uid_mode(struct inode *inode, const char *path, const __u16 *pfid)
 int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
 {
        int rc = 0;
-       __u32 acllen = 0;
+       __u32 secdesclen = 0;
        struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
        struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
 
        cFYI(DBG2, ("set ACL from mode for %s", path));
 
        /* Get the security descriptor */
-       pntsd = get_cifs_acl(&acllen, inode, path, NULL);
+       pntsd = get_cifs_acl(&secdesclen, inode, path, NULL);
 
        /* Add three ACEs for owner, group, everyone getting rid of
           other ACEs as chmod disables ACEs and set the security descriptor */
@@ -709,20 +709,22 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
                   set security descriptor request security descriptor
                   parameters, and secuirty descriptor itself */
 
-               pnntsd = kmalloc(acllen, GFP_KERNEL);
+               secdesclen = secdesclen < DEFSECDESCLEN ?
+                                       DEFSECDESCLEN : secdesclen;
+               pnntsd = kmalloc(secdesclen, GFP_KERNEL);
                if (!pnntsd) {
                        cERROR(1, ("Unable to allocate security descriptor"));
                        kfree(pntsd);
                        return (-ENOMEM);
                }
 
-               rc = build_sec_desc(pntsd, pnntsd, acllen, inode, nmode);
+               rc = build_sec_desc(pntsd, pnntsd, inode, nmode);
 
                cFYI(DBG2, ("build_sec_desc rc: %d", rc));
 
                if (!rc) {
                        /* Set the security descriptor */
-                       rc = set_cifs_acl(pnntsd, acllen, inode, path);
+                       rc = set_cifs_acl(pnntsd, secdesclen, inode, path);
                        cFYI(DBG2, ("set_cifs_acl rc: %d", rc));
                }
 
index 93a7c3462ea27c7c3080bbc963f545ba51fe1286..6c8096cf51557764aa10af6c28d108d3e93ce6e7 100644 (file)
@@ -27,6 +27,7 @@
 #define NUM_SUBAUTHS 5 /* number of sub authority fields */
 #define NUM_WK_SIDS 7 /* number of well known sids */
 #define SIDNAMELENGTH 20 /* long enough for the ones we care about */
+#define DEFSECDESCLEN 192 /* sec desc len contaiting a dacl with three aces */
 
 #define READ_BIT        0x4
 #define WRITE_BIT       0x2
index a04b17e5a9d01dbf5b8af64323b38b9ec45b20e8..39c2cbdface7b52e27ef8f79820caa6e1d350eff 100644 (file)
@@ -466,16 +466,11 @@ static struct quotactl_ops cifs_quotactl_ops = {
 };
 #endif
 
-static void cifs_umount_begin(struct vfsmount *vfsmnt, int flags)
+static void cifs_umount_begin(struct super_block *sb)
 {
-       struct cifs_sb_info *cifs_sb;
+       struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
        struct cifsTconInfo *tcon;
 
-       dfs_shrink_umount_helper(vfsmnt);
-
-       if (!(flags & MNT_FORCE))
-               return;
-       cifs_sb = CIFS_SB(vfsmnt->mnt_sb);
        if (cifs_sb == NULL)
                return;
 
@@ -1100,6 +1095,7 @@ exit_cifs(void)
        cFYI(DBG2, ("exit_cifs"));
        cifs_proc_clean();
 #ifdef CONFIG_CIFS_DFS_UPCALL
+       cifs_dfs_release_automount_timer();
        unregister_key_type(&key_type_dns_resolver);
 #endif
 #ifdef CONFIG_CIFS_UPCALL
index 68978306c3cad4333e7db69aa19e5eb7d1e89dfe..e1dd9f32e1d7600610ed084fa44548f7d153acb5 100644 (file)
@@ -62,11 +62,9 @@ extern int cifs_setattr(struct dentry *, struct iattr *);
 
 extern const struct inode_operations cifs_file_inode_ops;
 extern const struct inode_operations cifs_symlink_inode_ops;
-extern struct list_head cifs_dfs_automount_list;
 extern struct inode_operations cifs_dfs_referral_inode_operations;
 
 
-
 /* Functions related to files and directories */
 extern const struct file_operations cifs_file_ops;
 extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */
index 47f79504f57b35524b5e9a6629e75264a2047184..9f49c2f3582c03bfa6f217776548605370cd00a4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifspdu.h
  *
- *   Copyright (c) International Business Machines  Corp., 2002,2007
+ *   Copyright (c) International Business Machines  Corp., 2002,2008
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
                                                   path names in response */
 #define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
 #define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
+#define SMBFLG2_COMPRESSED (8)
+#define SMBFLG2_SECURITY_SIGNATURE_REQUIRED (0x10)
 #define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
+#define SMBFLG2_REPARSE_PATH (0x400)
 #define SMBFLG2_EXT_SEC cpu_to_le16(0x800)
 #define SMBFLG2_DFS cpu_to_le16(0x1000)
 #define SMBFLG2_PAGING_IO cpu_to_le16(0x2000)
 #define FILE_SHARE_DELETE 0x00000004
 #define FILE_SHARE_ALL    0x00000007
 
-/* CreateDisposition flags */
+/* CreateDisposition flags, similar to CreateAction as well */
 #define FILE_SUPERSEDE    0x00000000
 #define FILE_OPEN         0x00000001
 #define FILE_CREATE       0x00000002
 #define CREATE_NOT_FILE                0x00000001      /* if set must not be file */
 #define CREATE_WRITE_THROUGH   0x00000002
 #define CREATE_SEQUENTIAL       0x00000004
-#define CREATE_SYNC_ALERT       0x00000010
-#define CREATE_ASYNC_ALERT      0x00000020
+#define CREATE_NO_BUFFER        0x00000008      /* should not buffer on srv */
+#define CREATE_SYNC_ALERT       0x00000010     /* MBZ */
+#define CREATE_ASYNC_ALERT      0x00000020     /* MBZ */
 #define CREATE_NOT_DIR         0x00000040    /* if set must not be directory */
+#define CREATE_TREE_CONNECTION  0x00000080     /* should be zero */
+#define CREATE_COMPLETE_IF_OPLK 0x00000100     /* should be zero */
 #define CREATE_NO_EA_KNOWLEDGE  0x00000200
-#define CREATE_EIGHT_DOT_THREE  0x00000400
+#define CREATE_EIGHT_DOT_THREE  0x00000400     /* doc says this is obsolete
+                                                open for recovery flag - should
+                                                be zero */
 #define CREATE_RANDOM_ACCESS   0x00000800
 #define CREATE_DELETE_ON_CLOSE 0x00001000
 #define CREATE_OPEN_BY_ID       0x00002000
+#define CREATE_OPEN_BACKUP_INTN 0x00004000
+#define CREATE_NO_COMPRESSION   0x00008000
+#define CREATE_RESERVE_OPFILTER 0x00100000     /* should be zero */
 #define OPEN_REPARSE_POINT     0x00200000
+#define OPEN_NO_RECALL          0x00400000
+#define OPEN_FREE_SPACE_QUERY   0x00800000     /* should be zero */
 #define CREATE_OPTIONS_MASK     0x007FFFFF
 #define CREATE_OPTION_SPECIAL   0x20000000   /* system. NB not sent over wire */
 
@@ -470,7 +483,7 @@ typedef struct lanman_neg_rsp {
 
 typedef struct negotiate_rsp {
        struct smb_hdr hdr;     /* wct = 17 */
-       __le16 DialectIndex;
+       __le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
        __u8 SecurityMode;
        __le16 MaxMpxCount;
        __le16 MaxNumberVcs;
@@ -516,10 +529,11 @@ typedef struct negotiate_rsp {
 #define CAP_INFOLEVEL_PASSTHRU 0x00002000
 #define CAP_LARGE_READ_X       0x00004000
 #define CAP_LARGE_WRITE_X      0x00008000
+#define CAP_LWIO               0x00010000 /* support fctl_srv_req_resume_key */
 #define CAP_UNIX               0x00800000
-#define CAP_RESERVED           0x02000000
-#define CAP_BULK_TRANSFER      0x20000000
-#define CAP_COMPRESSED_DATA    0x40000000
+#define CAP_COMPRESSED_DATA    0x02000000
+#define CAP_DYNAMIC_REAUTH     0x20000000
+#define CAP_PERSISTENT_HANDLES 0x40000000
 #define CAP_EXTENDED_SECURITY  0x80000000
 
 typedef union smb_com_session_setup_andx {
@@ -668,9 +682,7 @@ typedef struct smb_com_tconx_req {
 } __attribute__((packed)) TCONX_REQ;
 
 typedef struct smb_com_tconx_rsp {
-       struct smb_hdr hdr;     /* wct = 3 note that Win2000 has sent wct = 7
-                                in some cases on responses. Four unspecified
-                                words followed OptionalSupport */
+       struct smb_hdr hdr;     /* wct = 3 , not extended response */
        __u8 AndXCommand;
        __u8 AndXReserved;
        __le16 AndXOffset;
@@ -680,13 +692,48 @@ typedef struct smb_com_tconx_rsp {
        /* STRING NativeFileSystem */
 } __attribute__((packed)) TCONX_RSP;
 
+typedef struct smb_com_tconx_rsp_ext {
+       struct smb_hdr hdr;     /* wct = 7, extended response */
+       __u8 AndXCommand;
+       __u8 AndXReserved;
+       __le16 AndXOffset;
+       __le16 OptionalSupport; /* see below */
+       __le32 MaximalShareAccessRights;
+       __le32 GuestMaximalShareAccessRights;
+       __u16 ByteCount;
+       unsigned char Service[1];       /* always ASCII, not Unicode */
+       /* STRING NativeFileSystem */
+} __attribute__((packed)) TCONX_RSP_EXT;
+
+
 /* tree connect Flags */
 #define DISCONNECT_TID          0x0001
+#define TCON_EXTENDED_SIGNATURES 0x0004
 #define TCON_EXTENDED_SECINFO   0x0008
+
 /* OptionalSupport bits */
 #define SMB_SUPPORT_SEARCH_BITS 0x0001 /* "must have" directory search bits
                                         (exclusive searches supported) */
 #define SMB_SHARE_IS_IN_DFS     0x0002
+#define SMB_CSC_MASK               0x000C
+/* CSC flags defined as follows */
+#define SMB_CSC_CACHE_MANUAL_REINT 0x0000
+#define SMB_CSC_CACHE_AUTO_REINT   0x0004
+#define SMB_CSC_CACHE_VDO          0x0008
+#define SMB_CSC_NO_CACHING         0x000C
+
+#define SMB_UNIQUE_FILE_NAME    0x0010
+#define SMB_EXTENDED_SIGNATURES 0x0020
+
+/* services
+ *
+ * A:       ie disk
+ * LPT1:    ie printer
+ * IPC      ie named pipe
+ * COMM
+ * ?????    ie any type
+ *
+ */
 
 typedef struct smb_com_logoff_andx_req {
        struct smb_hdr hdr;     /* wct = 2 */
@@ -750,6 +797,17 @@ typedef struct smb_com_findclose_req {
 #define COMM_DEV_TYPE          0x0004
 #define UNKNOWN_TYPE           0xFFFF
 
+/* Device Type or File Status Flags */
+#define NO_EAS                 0x0001
+#define NO_SUBSTREAMS          0x0002
+#define NO_REPARSETAG          0x0004
+/* following flags can apply if pipe */
+#define ICOUNT_MASK            0x00FF
+#define PIPE_READ_MODE         0x0100
+#define NAMED_PIPE_TYPE                0x0400
+#define PIPE_END_POINT         0x0800
+#define BLOCKING_NAMED_PIPE    0x8000
+
 typedef struct smb_com_open_req {      /* also handles create */
        struct smb_hdr hdr;     /* wct = 24 */
        __u8 AndXCommand;
@@ -758,7 +816,7 @@ typedef struct smb_com_open_req {   /* also handles create */
        __u8 Reserved;          /* Must Be Zero */
        __le16 NameLength;
        __le32 OpenFlags;
-       __le32 RootDirectoryFid;
+       __u32  RootDirectoryFid;
        __le32 DesiredAccess;
        __le64 AllocationSize;
        __le32 FileAttributes;
@@ -801,6 +859,32 @@ typedef struct smb_com_open_rsp {
        __u16 ByteCount;        /* bct = 0 */
 } __attribute__((packed)) OPEN_RSP;
 
+typedef struct smb_com_open_rsp_ext {
+       struct smb_hdr hdr;     /* wct = 42 but meaningless due to MS bug? */
+       __u8 AndXCommand;
+       __u8 AndXReserved;
+       __le16 AndXOffset;
+       __u8 OplockLevel;
+       __u16 Fid;
+       __le32 CreateAction;
+       __le64 CreationTime;
+       __le64 LastAccessTime;
+       __le64 LastWriteTime;
+       __le64 ChangeTime;
+       __le32 FileAttributes;
+       __le64 AllocationSize;
+       __le64 EndOfFile;
+       __le16 FileType;
+       __le16 DeviceState;
+       __u8 DirectoryFlag;
+       __u8 VolumeGUID[16];
+       __u64 FileId; /* note no endian conversion - is opaque UniqueID */
+       __le32 MaximalAccessRights;
+       __le32 GuestMaximalAccessRights;
+       __u16 ByteCount;        /* bct = 0 */
+} __attribute__((packed)) OPEN_RSP_EXT;
+
+
 /* format of legacy open request */
 typedef struct smb_com_openx_req {
        struct smb_hdr  hdr;    /* wct = 15 */
@@ -1703,6 +1787,12 @@ typedef struct smb_com_transaction2_fnext_rsp_parms {
 #define SMB_QUERY_CIFS_UNIX_INFO    0x200
 #define SMB_QUERY_POSIX_FS_INFO     0x201
 #define SMB_QUERY_POSIX_WHO_AM_I    0x202
+#define SMB_REQUEST_TRANSPORT_ENCRYPTION 0x203
+#define SMB_QUERY_FS_PROXY          0x204 /* WAFS enabled. Returns structure
+                                           FILE_SYSTEM__UNIX_INFO to tell
+                                           whether new NTIOCTL available
+                                           (0xACE) for WAN friendly SMB
+                                           operations to be carried */
 #define SMB_QUERY_LABEL_INFO        0x3ea
 #define SMB_QUERY_FS_QUOTA_INFO     0x3ee
 #define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef
@@ -1959,7 +2049,10 @@ typedef struct {
 #define CIFS_UNIX_LARGE_READ_CAP        0x00000040 /* support reads >128K (up
                                                      to 0xFFFF00 */
 #define CIFS_UNIX_LARGE_WRITE_CAP       0x00000080
-
+#define CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP 0x00000100 /* can do SPNEGO crypt */
+#define CIFS_UNIX_TRANPSORT_ENCRYPTION_MANDATORY_CAP  0x00000200 /* must do  */
+#define CIFS_UNIX_PROXY_CAP             0x00000400 /* Proxy cap: 0xACE ioctl and
+                                                     QFS PROXY call */
 #ifdef CONFIG_CIFS_POSIX
 /* Can not set pathnames cap yet until we send new posix create SMB since
    otherwise server can treat such handles opened with older ntcreatex
index 7e5e0e78cd72c1c051ef5e23957de768687a664d..50f9fdae19b3d7c97a5638120b56201af3630312 100644 (file)
@@ -84,6 +84,7 @@ extern __u16 GetNextMid(struct TCP_Server_Info *server);
 extern struct oplock_q_entry *AllocOplockQEntry(struct inode *, u16,
                                                 struct cifsTconInfo *);
 extern void DeleteOplockQEntry(struct oplock_q_entry *);
+extern void DeleteTconOplockQEntries(struct cifsTconInfo *);
 extern struct timespec cifs_NTtimeToUnix(u64 utc_nanoseconds_since_1601);
 extern u64 cifs_UnixTimeToNT(struct timespec);
 extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
@@ -103,13 +104,7 @@ extern int mode_to_acl(struct inode *inode, const char *path, __u64);
 extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
                        const char *);
 extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
-#ifdef CONFIG_CIFS_DFS_UPCALL
-extern void dfs_shrink_umount_helper(struct vfsmount *vfsmnt);
-#else
-static inline void dfs_shrink_umount_helper(struct vfsmount *vfsmnt)
-{
-}
-#endif /* DFS_UPCALL */
+extern void cifs_dfs_release_automount_timer(void);
 void cifs_proc_init(void);
 void cifs_proc_clean(void);
 
index 30bbe448e260fa931a2a36098057bfdd8364fad3..4728fa982a4ed965237427b7386b838266ec497b 100644 (file)
@@ -165,17 +165,19 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
                                rc = CIFSTCon(0, tcon->ses, tcon->treeName,
                                              tcon, nls_codepage);
                                up(&tcon->ses->sesSem);
-                               /* tell server which Unix caps we support */
-                               if (tcon->ses->capabilities & CAP_UNIX)
-                                       reset_cifs_unix_caps(0 /* no xid */,
-                                               tcon,
-                                               NULL /* we do not know sb */,
-                                               NULL /* no vol info */);
                                /* BB FIXME add code to check if wsize needs
                                   update due to negotiated smb buffer size
                                   shrinking */
-                               if (rc == 0)
+                               if (rc == 0) {
                                        atomic_inc(&tconInfoReconnectCount);
+                                       /* tell server Unix caps we support */
+                                       if (tcon->ses->capabilities & CAP_UNIX)
+                                               reset_cifs_unix_caps(
+                                               0 /* no xid */,
+                                               tcon,
+                                               NULL /* we do not know sb */,
+                                               NULL /* no vol info */);
+                               }
 
                                cFYI(1, ("reconnect tcon rc = %d", rc));
                                /* Removed call to reopen open files here.
@@ -310,17 +312,19 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
                                rc = CIFSTCon(0, tcon->ses, tcon->treeName,
                                              tcon, nls_codepage);
                                up(&tcon->ses->sesSem);
-                               /* tell server which Unix caps we support */
-                               if (tcon->ses->capabilities & CAP_UNIX)
-                                       reset_cifs_unix_caps(0 /* no xid */,
-                                               tcon,
-                                               NULL /* do not know sb */,
-                                               NULL /* no vol info */);
                                /* BB FIXME add code to check if wsize needs
                                update due to negotiated smb buffer size
                                shrinking */
-                               if (rc == 0)
+                               if (rc == 0) {
                                        atomic_inc(&tconInfoReconnectCount);
+                                       /* tell server Unix caps we support */
+                                       if (tcon->ses->capabilities & CAP_UNIX)
+                                               reset_cifs_unix_caps(
+                                               0 /* no xid */,
+                                               tcon,
+                                               NULL /* do not know sb */,
+                                               NULL /* no vol info */);
+                               }
 
                                cFYI(1, ("reconnect tcon rc = %d", rc));
                                /* Removed call to reopen open files here.
index 8dbfa97cd18ca6ae60ba6621e8e9214cb7a1641d..e171067301689dee90ed97de96fc2fcb7eb3f518 100644 (file)
@@ -3527,6 +3527,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
                        FreeXid(xid);
                        return 0;
                }
+               DeleteTconOplockQEntries(cifs_sb->tcon);
                tconInfoFree(cifs_sb->tcon);
                if ((ses) && (ses->server)) {
                        /* save off task so we do not refer to ses later */
index bc673c8c1e6b59eb7fc48464965db0e3e7835365..e1031b9e2c55ccfb13182e89c899ba6e49c89f7d 100644 (file)
@@ -161,12 +161,14 @@ static void cifs_unix_info_to_inode(struct inode *inode,
        spin_unlock(&inode->i_lock);
 }
 
-static const unsigned char *cifs_get_search_path(struct cifsTconInfo *pTcon,
-                                       const char *search_path)
+static const unsigned char *cifs_get_search_path(struct cifs_sb_info *cifs_sb,
+                                               const char *search_path)
 {
        int tree_len;
        int path_len;
+       int i;
        char *tmp_path;
+       struct cifsTconInfo *pTcon = cifs_sb->tcon;
 
        if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS))
                return search_path;
@@ -180,6 +182,11 @@ static const unsigned char *cifs_get_search_path(struct cifsTconInfo *pTcon,
                return search_path;
 
        strncpy(tmp_path, pTcon->treeName, tree_len);
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
+               for (i = 0; i < tree_len; i++) {
+                       if (tmp_path[i] == '\\')
+                               tmp_path[i] = '/';
+               }
        strncpy(tmp_path+tree_len, search_path, path_len);
        tmp_path[tree_len+path_len] = 0;
        return tmp_path;
@@ -199,7 +206,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
        pTcon = cifs_sb->tcon;
        cFYI(1, ("Getting info on %s", search_path));
 
-       full_path = cifs_get_search_path(pTcon, search_path);
+       full_path = cifs_get_search_path(cifs_sb, search_path);
 
 try_again_CIFSSMBUnixQPathInfo:
        /* could have done a find first instead but this returns more info */
@@ -402,7 +409,7 @@ int cifs_get_inode_info(struct inode **pinode,
                        return -ENOMEM;
                pfindData = (FILE_ALL_INFO *)buf;
 
-               full_path = cifs_get_search_path(pTcon, search_path);
+               full_path = cifs_get_search_path(cifs_sb, search_path);
 
 try_again_CIFSSMBQPathInfo:
                /* could do find first instead but this returns more info */
index 3612d6c0a0bbc1a4c9f64c2ce0f674517ce86d72..000ac509c98a32e884322149e88b53e4bdb2a4c1 100644 (file)
@@ -142,6 +142,24 @@ void DeleteOplockQEntry(struct oplock_q_entry *oplockEntry)
        kmem_cache_free(cifs_oplock_cachep, oplockEntry);
 }
 
+
+void DeleteTconOplockQEntries(struct cifsTconInfo *tcon)
+{
+       struct oplock_q_entry *temp;
+
+       if (tcon == NULL)
+               return;
+
+       spin_lock(&GlobalMid_Lock);
+       list_for_each_entry(temp, &GlobalOplock_Q, qhead) {
+               if ((temp->tcon) && (temp->tcon == tcon)) {
+                       list_del(&temp->qhead);
+                       kmem_cache_free(cifs_oplock_cachep, temp);
+               }
+       }
+       spin_unlock(&GlobalMid_Lock);
+}
+
 int
 smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
         unsigned int smb_buf_length, struct sockaddr *sin)
index 54a0a557b6781ecf379015bbd60dc6f3fd37c176..b152029f18f61e68e260d63bab4a9720f2e31ab6 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -953,7 +953,6 @@ int flush_old_exec(struct linux_binprm * bprm)
 {
        char * name;
        int i, ch, retval;
-       struct files_struct *files;
        char tcomm[sizeof(current->comm)];
 
        /*
@@ -964,27 +963,16 @@ int flush_old_exec(struct linux_binprm * bprm)
        if (retval)
                goto out;
 
-       /*
-        * Make sure we have private file handles. Ask the
-        * fork helper to do the work for us and the exit
-        * helper to do the cleanup of the old one.
-        */
-       files = current->files;         /* refcounted so safe to hold */
-       retval = unshare_files();
-       if (retval)
-               goto out;
        /*
         * Release all of the old mmap stuff
         */
        retval = exec_mmap(bprm->mm);
        if (retval)
-               goto mmap_failed;
+               goto out;
 
        bprm->mm = NULL;                /* We're using it now */
 
        /* This is the point of no return */
-       put_files_struct(files);
-
        current->sas_ss_sp = current->sas_ss_size = 0;
 
        if (current->euid == current->uid && current->egid == current->gid)
@@ -1034,8 +1022,6 @@ int flush_old_exec(struct linux_binprm * bprm)
 
        return 0;
 
-mmap_failed:
-       reset_files_struct(current, files);
 out:
        return retval;
 }
@@ -1283,12 +1269,17 @@ int do_execve(char * filename,
        struct linux_binprm *bprm;
        struct file *file;
        unsigned long env_p;
+       struct files_struct *displaced;
        int retval;
 
+       retval = unshare_files(&displaced);
+       if (retval)
+               goto out_ret;
+
        retval = -ENOMEM;
        bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
        if (!bprm)
-               goto out_ret;
+               goto out_files;
 
        file = open_exec(filename);
        retval = PTR_ERR(file);
@@ -1343,6 +1334,8 @@ int do_execve(char * filename,
                security_bprm_free(bprm);
                acct_update_integrals(current);
                kfree(bprm);
+               if (displaced)
+                       put_files_struct(displaced);
                return retval;
        }
 
@@ -1363,6 +1356,9 @@ out_file:
 out_kfree:
        kfree(bprm);
 
+out_files:
+       if (displaced)
+               reset_files_struct(displaced);
 out_ret:
        return retval;
 }
index e632da761fc11cd19b8637bcad23b1f5562d7382..3f3ac630ccde701992caf5edf69a5f717c424f0c 100644 (file)
@@ -55,14 +55,16 @@ static int get_close_on_exec(unsigned int fd)
  * file_lock held for write.
  */
 
-static int locate_fd(struct files_struct *files, 
-                           struct file *file, unsigned int orig_start)
+static int locate_fd(unsigned int orig_start, int cloexec)
 {
+       struct files_struct *files = current->files;
        unsigned int newfd;
        unsigned int start;
        int error;
        struct fdtable *fdt;
 
+       spin_lock(&files->file_lock);
+
        error = -EINVAL;
        if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
                goto out;
@@ -97,42 +99,28 @@ repeat:
        if (error)
                goto repeat;
 
-       /*
-        * We reacquired files_lock, so we are safe as long as
-        * we reacquire the fdtable pointer and use it while holding
-        * the lock, no one can free it during that time.
-        */
        if (start <= files->next_fd)
                files->next_fd = newfd + 1;
 
+       FD_SET(newfd, fdt->open_fds);
+       if (cloexec)
+               FD_SET(newfd, fdt->close_on_exec);
+       else
+               FD_CLR(newfd, fdt->close_on_exec);
        error = newfd;
-       
+
 out:
+       spin_unlock(&files->file_lock);
        return error;
 }
 
 static int dupfd(struct file *file, unsigned int start, int cloexec)
 {
-       struct files_struct * files = current->files;
-       struct fdtable *fdt;
-       int fd;
-
-       spin_lock(&files->file_lock);
-       fd = locate_fd(files, file, start);
-       if (fd >= 0) {
-               /* locate_fd() may have expanded fdtable, load the ptr */
-               fdt = files_fdtable(files);
-               FD_SET(fd, fdt->open_fds);
-               if (cloexec)
-                       FD_SET(fd, fdt->close_on_exec);
-               else
-                       FD_CLR(fd, fdt->close_on_exec);
-               spin_unlock(&files->file_lock);
+       int fd = locate_fd(start, cloexec);
+       if (fd >= 0)
                fd_install(fd, file);
-       } else {
-               spin_unlock(&files->file_lock);
+       else
                fput(file);
-       }
 
        return fd;
 }
index 033f7bdd47e80e2f659be152bd51e0441e607c3d..4df34da2284aaf1cf9b96ee995afb03fd408209a 100644 (file)
@@ -242,10 +242,9 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
        return inode;
 }
 
-static void fuse_umount_begin(struct vfsmount *vfsmnt, int flags)
+static void fuse_umount_begin(struct super_block *sb)
 {
-       if (flags & MNT_FORCE)
-               fuse_abort_conn(get_fuse_conn_super(vfsmnt->mnt_sb));
+       fuse_abort_conn(get_fuse_conn_super(sb));
 }
 
 static void fuse_send_destroy(struct fuse_conn *fc)
index d14d5a4dc5ac6f9a956fc1653e04de94079470e7..3ea36554107fc7740558ac81daa0328c308b2903 100644 (file)
@@ -14,7 +14,7 @@ be fairly close.
        alloc_sem
        ---------
 
-The alloc_sem is a per-filesystem semaphore, used primarily to ensure
+The alloc_sem is a per-filesystem mutex, used primarily to ensure
 contiguous allocation of space on the medium. It is automatically
 obtained during space allocations (jffs2_reserve_space()) and freed
 upon write completion (jffs2_complete_reservation()). Note that
@@ -41,10 +41,10 @@ if the wbuf is currently holding any data is permitted, though.
 Ordering constraints: See f->sem.
 
 
-       File Semaphore f->sem
+       File Mutex f->sem
        ---------------------
 
-This is the JFFS2-internal equivalent of the inode semaphore i->i_sem.
+This is the JFFS2-internal equivalent of the inode mutex i->i_sem.
 It protects the contents of the jffs2_inode_info private inode data,
 including the linked list of node fragments (but see the notes below on
 erase_completion_lock), etc.
@@ -60,14 +60,14 @@ lead to deadlock, unless we played games with unlocking the i_sem
 before calling the space allocation functions.
 
 Instead of playing such games, we just have an extra internal
-semaphore, which is obtained by the garbage collection code and also
+mutex, which is obtained by the garbage collection code and also
 by the normal file system code _after_ allocation of space.
 
 Ordering constraints: 
 
        1. Never attempt to allocate space or lock alloc_sem with 
           any f->sem held.
-       2. Never attempt to lock two file semaphores in one thread.
+       2. Never attempt to lock two file mutexes in one thread.
           No ordering rules have been made for doing so.
 
 
@@ -86,8 +86,8 @@ a simple spin_lock() rather than spin_lock_bh().
 
 Note that the per-inode list of physical nodes (f->nodes) is a special
 case. Any changes to _valid_ nodes (i.e. ->flash_offset & 1 == 0) in
-the list are protected by the file semaphore f->sem. But the erase
-code may remove _obsolete_ nodes from the list while holding only the
+the list are protected by the file mutex f->sem. But the erase code
+may remove _obsolete_ nodes from the list while holding only the
 erase_completion_lock. So you can walk the list only while holding the
 erase_completion_lock, and can drop the lock temporarily mid-walk as
 long as the pointer you're holding is to a _valid_ node, not an
@@ -124,10 +124,10 @@ Ordering constraints:
        erase_free_sem
        --------------
 
-This semaphore is only used by the erase code which frees obsolete
-node references and the jffs2_garbage_collect_deletion_dirent()
-function. The latter function on NAND flash must read _obsolete_ nodes
-to determine whether the 'deletion dirent' under consideration can be
+This mutex is only used by the erase code which frees obsolete node
+references and the jffs2_garbage_collect_deletion_dirent() function.
+The latter function on NAND flash must read _obsolete_ nodes to
+determine whether the 'deletion dirent' under consideration can be
 discarded or whether it is still required to show that an inode has
 been unlinked. Because reading from the flash may sleep, the
 erase_completion_lock cannot be held, so an alternative, more
index 722a6b682951b8bcdecac8107171c2d06f5d60be..d58f845ccb85984666d2e6ef0d1d6d9339c10d67 100644 (file)
@@ -345,6 +345,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c)
        INIT_LIST_HEAD(&c->dirty_list);
        INIT_LIST_HEAD(&c->erasable_list);
        INIT_LIST_HEAD(&c->erasing_list);
+       INIT_LIST_HEAD(&c->erase_checking_list);
        INIT_LIST_HEAD(&c->erase_pending_list);
        INIT_LIST_HEAD(&c->erasable_pending_wbuf_list);
        INIT_LIST_HEAD(&c->erase_complete_list);
index 3a32c64ed4975260079e7b9f3c435eecef18b534..5544d31c066be22fb25cc857df3691de8e420ea6 100644 (file)
@@ -62,9 +62,9 @@ __jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c,
 void
 __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
 {
-       down(&f->sem);
+       mutex_lock(&f->sem);
        __jffs2_dbg_fragtree_paranoia_check_nolock(f);
-       up(&f->sem);
+       mutex_unlock(&f->sem);
 }
 
 void
@@ -153,6 +153,139 @@ __jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c,
        kfree(buf);
 }
 
+void __jffs2_dbg_superblock_counts(struct jffs2_sb_info *c)
+{
+       struct jffs2_eraseblock *jeb;
+       uint32_t free = 0, dirty = 0, used = 0, wasted = 0,
+               erasing = 0, bad = 0, unchecked = 0;
+       int nr_counted = 0;
+       int dump = 0;
+
+       if (c->gcblock) {
+               nr_counted++;
+               free += c->gcblock->free_size;
+               dirty += c->gcblock->dirty_size;
+               used += c->gcblock->used_size;
+               wasted += c->gcblock->wasted_size;
+               unchecked += c->gcblock->unchecked_size;
+       }
+       if (c->nextblock) {
+               nr_counted++;
+               free += c->nextblock->free_size;
+               dirty += c->nextblock->dirty_size;
+               used += c->nextblock->used_size;
+               wasted += c->nextblock->wasted_size;
+               unchecked += c->nextblock->unchecked_size;
+       }
+       list_for_each_entry(jeb, &c->clean_list, list) {
+               nr_counted++;
+               free += jeb->free_size;
+               dirty += jeb->dirty_size;
+               used += jeb->used_size;
+               wasted += jeb->wasted_size;
+               unchecked += jeb->unchecked_size;
+       }
+       list_for_each_entry(jeb, &c->very_dirty_list, list) {
+               nr_counted++;
+               free += jeb->free_size;
+               dirty += jeb->dirty_size;
+               used += jeb->used_size;
+               wasted += jeb->wasted_size;
+               unchecked += jeb->unchecked_size;
+       }
+       list_for_each_entry(jeb, &c->dirty_list, list) {
+               nr_counted++;
+               free += jeb->free_size;
+               dirty += jeb->dirty_size;
+               used += jeb->used_size;
+               wasted += jeb->wasted_size;
+               unchecked += jeb->unchecked_size;
+       }
+       list_for_each_entry(jeb, &c->erasable_list, list) {
+               nr_counted++;
+               free += jeb->free_size;
+               dirty += jeb->dirty_size;
+               used += jeb->used_size;
+               wasted += jeb->wasted_size;
+               unchecked += jeb->unchecked_size;
+       }
+       list_for_each_entry(jeb, &c->erasable_pending_wbuf_list, list) {
+               nr_counted++;
+               free += jeb->free_size;
+               dirty += jeb->dirty_size;
+               used += jeb->used_size;
+               wasted += jeb->wasted_size;
+               unchecked += jeb->unchecked_size;
+       }
+       list_for_each_entry(jeb, &c->erase_pending_list, list) {
+               nr_counted++;
+               free += jeb->free_size;
+               dirty += jeb->dirty_size;
+               used += jeb->used_size;
+               wasted += jeb->wasted_size;
+               unchecked += jeb->unchecked_size;
+       }
+       list_for_each_entry(jeb, &c->free_list, list) {
+               nr_counted++;
+               free += jeb->free_size;
+               dirty += jeb->dirty_size;
+               used += jeb->used_size;
+               wasted += jeb->wasted_size;
+               unchecked += jeb->unchecked_size;
+       }
+       list_for_each_entry(jeb, &c->bad_used_list, list) {
+               nr_counted++;
+               free += jeb->free_size;
+               dirty += jeb->dirty_size;
+               used += jeb->used_size;
+               wasted += jeb->wasted_size;
+               unchecked += jeb->unchecked_size;
+       }
+
+       list_for_each_entry(jeb, &c->erasing_list, list) {
+               nr_counted++;
+               erasing += c->sector_size;
+       }
+       list_for_each_entry(jeb, &c->erase_checking_list, list) {
+               nr_counted++;
+               erasing += c->sector_size;
+       }
+       list_for_each_entry(jeb, &c->erase_complete_list, list) {
+               nr_counted++;
+               erasing += c->sector_size;
+       }
+       list_for_each_entry(jeb, &c->bad_list, list) {
+               nr_counted++;
+               bad += c->sector_size;
+       }
+
+#define check(sz) \
+       if (sz != c->sz##_size) {                       \
+               printk(KERN_WARNING #sz "_size mismatch counted 0x%x, c->" #sz "_size 0x%x\n", \
+                      sz, c->sz##_size);               \
+               dump = 1;                               \
+       }
+       check(free);
+       check(dirty);
+       check(used);
+       check(wasted);
+       check(unchecked);
+       check(bad);
+       check(erasing);
+#undef check
+
+       if (nr_counted != c->nr_blocks) {
+               printk(KERN_WARNING "%s counted only 0x%x blocks of 0x%x. Where are the others?\n",
+                      __func__, nr_counted, c->nr_blocks);
+               dump = 1;
+       }
+
+       if (dump) {
+               __jffs2_dbg_dump_block_lists_nolock(c);
+               BUG();
+       }
+}
+
 /*
  * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
  */
@@ -229,6 +362,9 @@ __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
        }
 #endif
 
+       if (!(c->flags & (JFFS2_SB_FLAG_BUILDING|JFFS2_SB_FLAG_SCANNING)))
+               __jffs2_dbg_superblock_counts(c);
+
        return;
 
 error:
@@ -268,7 +404,10 @@ __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
 
        printk(JFFS2_DBG);
        for (ref = jeb->first_node; ; ref = ref_next(ref)) {
-               printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
+               printk("%#08x", ref_offset(ref));
+#ifdef TEST_TOTLEN
+               printk("(%x)", ref->__totlen);
+#endif
                if (ref_next(ref))
                        printk("->");
                else
@@ -447,6 +586,21 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
                        }
                }
        }
+       if (list_empty(&c->erase_checking_list)) {
+               printk(JFFS2_DBG "erase_checking_list: empty\n");
+       } else {
+               struct list_head *this;
+
+               list_for_each(this, &c->erase_checking_list) {
+                       struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
+
+                       if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
+                               printk(JFFS2_DBG "erase_checking_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
+                                       jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
+                                       jeb->unchecked_size, jeb->free_size);
+                       }
+               }
+       }
 
        if (list_empty(&c->erase_pending_list)) {
                printk(JFFS2_DBG "erase_pending_list: empty\n");
@@ -532,9 +686,9 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
 void
 __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
 {
-       down(&f->sem);
+       mutex_lock(&f->sem);
        jffs2_dbg_dump_fragtree_nolock(f);
-       up(&f->sem);
+       mutex_unlock(&f->sem);
 }
 
 void
index 4130adabd76e6d9a9d496d1e6d176a43cb905783..9645275023e68c5b93f582a10d31d541a4a79884 100644 (file)
@@ -38,6 +38,7 @@
 
 #if CONFIG_JFFS2_FS_DEBUG > 1
 #define JFFS2_DBG_FRAGTREE2_MESSAGES
+#define JFFS2_DBG_READINODE2_MESSAGES
 #define JFFS2_DBG_MEMALLOC_MESSAGES
 #endif
 
 #else
 #define dbg_readinode(fmt, ...)
 #endif
+#ifdef JFFS2_DBG_READINODE2_MESSAGES
+#define dbg_readinode2(fmt, ...)       JFFS2_DEBUG(fmt, ##__VA_ARGS__)
+#else
+#define dbg_readinode2(fmt, ...)
+#endif
 
 /* Fragtree build debugging messages */
 #ifdef JFFS2_DBG_FRAGTREE_MESSAGES
index f948f7e6ec8202ab901d83b7fd5c62fd6ec41b27..c63e7a96af0dd025996c80b707b710213d7bdb1d 100644 (file)
@@ -86,7 +86,7 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
        dir_f = JFFS2_INODE_INFO(dir_i);
        c = JFFS2_SB_INFO(dir_i->i_sb);
 
-       down(&dir_f->sem);
+       mutex_lock(&dir_f->sem);
 
        /* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */
        for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= target->d_name.hash; fd_list = fd_list->next) {
@@ -99,7 +99,7 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
        }
        if (fd)
                ino = fd->ino;
-       up(&dir_f->sem);
+       mutex_unlock(&dir_f->sem);
        if (ino) {
                inode = jffs2_iget(dir_i->i_sb, ino);
                if (IS_ERR(inode)) {
@@ -146,7 +146,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
        }
 
        curofs=1;
-       down(&f->sem);
+       mutex_lock(&f->sem);
        for (fd = f->dents; fd; fd = fd->next) {
 
                curofs++;
@@ -166,7 +166,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
                        break;
                offset++;
        }
-       up(&f->sem);
+       mutex_unlock(&f->sem);
  out:
        filp->f_pos = offset;
        return 0;
@@ -275,9 +275,9 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
        ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len, now);
 
        if (!ret) {
-               down(&f->sem);
+               mutex_lock(&f->sem);
                old_dentry->d_inode->i_nlink = ++f->inocache->nlink;
-               up(&f->sem);
+               mutex_unlock(&f->sem);
                d_instantiate(dentry, old_dentry->d_inode);
                dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
                atomic_inc(&old_dentry->d_inode->i_count);
@@ -351,7 +351,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
 
        if (IS_ERR(fn)) {
                /* Eeek. Wave bye bye */
-               up(&f->sem);
+               mutex_unlock(&f->sem);
                jffs2_complete_reservation(c);
                jffs2_clear_inode(inode);
                return PTR_ERR(fn);
@@ -361,7 +361,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
        f->target = kmalloc(targetlen + 1, GFP_KERNEL);
        if (!f->target) {
                printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1);
-               up(&f->sem);
+               mutex_unlock(&f->sem);
                jffs2_complete_reservation(c);
                jffs2_clear_inode(inode);
                return -ENOMEM;
@@ -374,7 +374,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
           obsoleted by the first data write
        */
        f->metadata = fn;
-       up(&f->sem);
+       mutex_unlock(&f->sem);
 
        jffs2_complete_reservation(c);
 
@@ -406,7 +406,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
        }
 
        dir_f = JFFS2_INODE_INFO(dir_i);
-       down(&dir_f->sem);
+       mutex_lock(&dir_f->sem);
 
        rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
        rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
@@ -429,7 +429,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
                   as if it were the final unlink() */
                jffs2_complete_reservation(c);
                jffs2_free_raw_dirent(rd);
-               up(&dir_f->sem);
+               mutex_unlock(&dir_f->sem);
                jffs2_clear_inode(inode);
                return PTR_ERR(fd);
        }
@@ -442,7 +442,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
           one if necessary. */
        jffs2_add_fd_to_list(c, fd, &dir_f->dents);
 
-       up(&dir_f->sem);
+       mutex_unlock(&dir_f->sem);
        jffs2_complete_reservation(c);
 
        d_instantiate(dentry, inode);
@@ -507,7 +507,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
 
        if (IS_ERR(fn)) {
                /* Eeek. Wave bye bye */
-               up(&f->sem);
+               mutex_unlock(&f->sem);
                jffs2_complete_reservation(c);
                jffs2_clear_inode(inode);
                return PTR_ERR(fn);
@@ -516,7 +516,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
           obsoleted by the first data write
        */
        f->metadata = fn;
-       up(&f->sem);
+       mutex_unlock(&f->sem);
 
        jffs2_complete_reservation(c);
 
@@ -548,7 +548,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
        }
 
        dir_f = JFFS2_INODE_INFO(dir_i);
-       down(&dir_f->sem);
+       mutex_lock(&dir_f->sem);
 
        rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
        rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
@@ -571,7 +571,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
                   as if it were the final unlink() */
                jffs2_complete_reservation(c);
                jffs2_free_raw_dirent(rd);
-               up(&dir_f->sem);
+               mutex_unlock(&dir_f->sem);
                jffs2_clear_inode(inode);
                return PTR_ERR(fd);
        }
@@ -585,7 +585,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
           one if necessary. */
        jffs2_add_fd_to_list(c, fd, &dir_f->dents);
 
-       up(&dir_f->sem);
+       mutex_unlock(&dir_f->sem);
        jffs2_complete_reservation(c);
 
        d_instantiate(dentry, inode);
@@ -673,7 +673,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
 
        if (IS_ERR(fn)) {
                /* Eeek. Wave bye bye */
-               up(&f->sem);
+               mutex_unlock(&f->sem);
                jffs2_complete_reservation(c);
                jffs2_clear_inode(inode);
                return PTR_ERR(fn);
@@ -682,7 +682,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
           obsoleted by the first data write
        */
        f->metadata = fn;
-       up(&f->sem);
+       mutex_unlock(&f->sem);
 
        jffs2_complete_reservation(c);
 
@@ -714,7 +714,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
        }
 
        dir_f = JFFS2_INODE_INFO(dir_i);
-       down(&dir_f->sem);
+       mutex_lock(&dir_f->sem);
 
        rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
        rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
@@ -740,7 +740,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
                   as if it were the final unlink() */
                jffs2_complete_reservation(c);
                jffs2_free_raw_dirent(rd);
-               up(&dir_f->sem);
+               mutex_unlock(&dir_f->sem);
                jffs2_clear_inode(inode);
                return PTR_ERR(fd);
        }
@@ -753,7 +753,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
           one if necessary. */
        jffs2_add_fd_to_list(c, fd, &dir_f->dents);
 
-       up(&dir_f->sem);
+       mutex_unlock(&dir_f->sem);
        jffs2_complete_reservation(c);
 
        d_instantiate(dentry, inode);
@@ -780,14 +780,14 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
                if (S_ISDIR(new_dentry->d_inode->i_mode)) {
                        struct jffs2_full_dirent *fd;
 
-                       down(&victim_f->sem);
+                       mutex_lock(&victim_f->sem);
                        for (fd = victim_f->dents; fd; fd = fd->next) {
                                if (fd->ino) {
-                                       up(&victim_f->sem);
+                                       mutex_unlock(&victim_f->sem);
                                        return -ENOTEMPTY;
                                }
                        }
-                       up(&victim_f->sem);
+                       mutex_unlock(&victim_f->sem);
                }
        }
 
@@ -816,9 +816,9 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
                /* Don't oops if the victim was a dirent pointing to an
                   inode which didn't exist. */
                if (victim_f->inocache) {
-                       down(&victim_f->sem);
+                       mutex_lock(&victim_f->sem);
                        victim_f->inocache->nlink--;
-                       up(&victim_f->sem);
+                       mutex_unlock(&victim_f->sem);
                }
        }
 
@@ -836,11 +836,11 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
        if (ret) {
                /* Oh shit. We really ought to make a single node which can do both atomically */
                struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
-               down(&f->sem);
+               mutex_lock(&f->sem);
                inc_nlink(old_dentry->d_inode);
                if (f->inocache)
                        f->inocache->nlink++;
-               up(&f->sem);
+               mutex_unlock(&f->sem);
 
                printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
                /* Might as well let the VFS know */
index a1db9180633fcb3476757af80f22b3e6621f06d2..25a640e566d3d6d47ae9310b12b3e222f7bbed52 100644 (file)
@@ -50,14 +50,14 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
        instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL);
        if (!instr) {
                printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n");
-               down(&c->erase_free_sem);
+               mutex_lock(&c->erase_free_sem);
                spin_lock(&c->erase_completion_lock);
                list_move(&jeb->list, &c->erase_pending_list);
                c->erasing_size -= c->sector_size;
                c->dirty_size += c->sector_size;
                jeb->dirty_size = c->sector_size;
                spin_unlock(&c->erase_completion_lock);
-               up(&c->erase_free_sem);
+               mutex_unlock(&c->erase_free_sem);
                return;
        }
 
@@ -84,14 +84,14 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
        if (ret == -ENOMEM || ret == -EAGAIN) {
                /* Erase failed immediately. Refile it on the list */
                D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret));
-               down(&c->erase_free_sem);
+               mutex_lock(&c->erase_free_sem);
                spin_lock(&c->erase_completion_lock);
                list_move(&jeb->list, &c->erase_pending_list);
                c->erasing_size -= c->sector_size;
                c->dirty_size += c->sector_size;
                jeb->dirty_size = c->sector_size;
                spin_unlock(&c->erase_completion_lock);
-               up(&c->erase_free_sem);
+               mutex_unlock(&c->erase_free_sem);
                return;
        }
 
@@ -107,7 +107,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
 {
        struct jffs2_eraseblock *jeb;
 
-       down(&c->erase_free_sem);
+       mutex_lock(&c->erase_free_sem);
 
        spin_lock(&c->erase_completion_lock);
 
@@ -116,9 +116,9 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
 
                if (!list_empty(&c->erase_complete_list)) {
                        jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list);
-                       list_del(&jeb->list);
+                       list_move(&jeb->list, &c->erase_checking_list);
                        spin_unlock(&c->erase_completion_lock);
-                       up(&c->erase_free_sem);
+                       mutex_unlock(&c->erase_free_sem);
                        jffs2_mark_erased_block(c, jeb);
 
                        if (!--count) {
@@ -139,7 +139,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
                        jffs2_free_jeb_node_refs(c, jeb);
                        list_add(&jeb->list, &c->erasing_list);
                        spin_unlock(&c->erase_completion_lock);
-                       up(&c->erase_free_sem);
+                       mutex_unlock(&c->erase_free_sem);
 
                        jffs2_erase_block(c, jeb);
 
@@ -149,12 +149,12 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
 
                /* Be nice */
                yield();
-               down(&c->erase_free_sem);
+               mutex_lock(&c->erase_free_sem);
                spin_lock(&c->erase_completion_lock);
        }
 
        spin_unlock(&c->erase_completion_lock);
-       up(&c->erase_free_sem);
+       mutex_unlock(&c->erase_free_sem);
  done:
        D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n"));
 }
@@ -162,11 +162,11 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
 static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
 {
        D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset));
-       down(&c->erase_free_sem);
+       mutex_lock(&c->erase_free_sem);
        spin_lock(&c->erase_completion_lock);
        list_move_tail(&jeb->list, &c->erase_complete_list);
        spin_unlock(&c->erase_completion_lock);
-       up(&c->erase_free_sem);
+       mutex_unlock(&c->erase_free_sem);
        /* Ensure that kupdated calls us again to mark them clean */
        jffs2_erase_pending_trigger(c);
 }
@@ -180,26 +180,26 @@ static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock
                   failed too many times. */
                if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) {
                        /* We'd like to give this block another try. */
-                       down(&c->erase_free_sem);
+                       mutex_lock(&c->erase_free_sem);
                        spin_lock(&c->erase_completion_lock);
                        list_move(&jeb->list, &c->erase_pending_list);
                        c->erasing_size -= c->sector_size;
                        c->dirty_size += c->sector_size;
                        jeb->dirty_size = c->sector_size;
                        spin_unlock(&c->erase_completion_lock);
-                       up(&c->erase_free_sem);
+                       mutex_unlock(&c->erase_free_sem);
                        return;
                }
        }
 
-       down(&c->erase_free_sem);
+       mutex_lock(&c->erase_free_sem);
        spin_lock(&c->erase_completion_lock);
        c->erasing_size -= c->sector_size;
        c->bad_size += c->sector_size;
        list_move(&jeb->list, &c->bad_list);
        c->nr_erasing_blocks--;
        spin_unlock(&c->erase_completion_lock);
-       up(&c->erase_free_sem);
+       mutex_unlock(&c->erase_free_sem);
        wake_up(&c->erase_wait);
 }
 
@@ -350,9 +350,11 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
                           break;
                } while(--retlen);
                c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size);
-               if (retlen)
+               if (retlen) {
                        printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08tx\n",
                               *wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf));
+                       return -EIO;
+               }
                return 0;
        }
  do_flash_read:
@@ -373,10 +375,12 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
                ret = c->mtd->read(c->mtd, ofs, readlen, &retlen, ebuf);
                if (ret) {
                        printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret);
+                       ret = -EIO;
                        goto fail;
                }
                if (retlen != readlen) {
                        printk(KERN_WARNING "Short read from newly-erased block at 0x%08x. Wanted %d, got %zd\n", ofs, readlen, retlen);
+                       ret = -EIO;
                        goto fail;
                }
                for (i=0; i<readlen; i += sizeof(unsigned long)) {
@@ -385,6 +389,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
                        if (*datum + 1) {
                                *bad_offset += i;
                                printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08x\n", *datum, *bad_offset);
+                               ret = -EIO;
                                goto fail;
                        }
                }
@@ -419,9 +424,6 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
                        if (jffs2_write_nand_cleanmarker(c, jeb))
                                goto filebad;
                }
-
-               /* Everything else got zeroed before the erase */
-               jeb->free_size = c->sector_size;
        } else {
 
                struct kvec vecs[1];
@@ -449,48 +451,50 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
 
                        goto filebad;
                }
-
-               /* Everything else got zeroed before the erase */
-               jeb->free_size = c->sector_size;
-               /* FIXME Special case for cleanmarker in empty block */
-               jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
        }
+       /* Everything else got zeroed before the erase */
+       jeb->free_size = c->sector_size;
 
-       down(&c->erase_free_sem);
+       mutex_lock(&c->erase_free_sem);
        spin_lock(&c->erase_completion_lock);
+
        c->erasing_size -= c->sector_size;
-       c->free_size += jeb->free_size;
-       c->used_size += jeb->used_size;
+       c->free_size += c->sector_size;
 
-       jffs2_dbg_acct_sanity_check_nolock(c,jeb);
-       jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
+       /* Account for cleanmarker now, if it's in-band */
+       if (c->cleanmarker_size && !jffs2_cleanmarker_oob(c))
+               jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
 
-       list_add_tail(&jeb->list, &c->free_list);
+       list_move_tail(&jeb->list, &c->free_list);
        c->nr_erasing_blocks--;
        c->nr_free_blocks++;
+
+       jffs2_dbg_acct_sanity_check_nolock(c, jeb);
+       jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
+
        spin_unlock(&c->erase_completion_lock);
-       up(&c->erase_free_sem);
+       mutex_unlock(&c->erase_free_sem);
        wake_up(&c->erase_wait);
        return;
 
 filebad:
-       down(&c->erase_free_sem);
+       mutex_lock(&c->erase_free_sem);
        spin_lock(&c->erase_completion_lock);
        /* Stick it on a list (any list) so erase_failed can take it
           right off again.  Silly, but shouldn't happen often. */
-       list_add(&jeb->list, &c->erasing_list);
+       list_move(&jeb->list, &c->erasing_list);
        spin_unlock(&c->erase_completion_lock);
-       up(&c->erase_free_sem);
+       mutex_unlock(&c->erase_free_sem);
        jffs2_erase_failed(c, jeb, bad_offset);
        return;
 
 refile:
        /* Stick it back on the list from whence it came and come back later */
        jffs2_erase_pending_trigger(c);
-       down(&c->erase_free_sem);
+       mutex_lock(&c->erase_free_sem);
        spin_lock(&c->erase_completion_lock);
-       list_add(&jeb->list, &c->erase_complete_list);
+       list_move(&jeb->list, &c->erase_complete_list);
        spin_unlock(&c->erase_completion_lock);
-       up(&c->erase_free_sem);
+       mutex_unlock(&c->erase_free_sem);
        return;
 }
index dcc2734e0b5d65479a34ba53a9bf7ea2f08ecbbf..5e920343b2c598595f2c068455e17d7d360c5a4f 100644 (file)
@@ -115,9 +115,9 @@ static int jffs2_readpage (struct file *filp, struct page *pg)
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(pg->mapping->host);
        int ret;
 
-       down(&f->sem);
+       mutex_lock(&f->sem);
        ret = jffs2_do_readpage_unlock(pg->mapping->host, pg);
-       up(&f->sem);
+       mutex_unlock(&f->sem);
        return ret;
 }
 
@@ -154,7 +154,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
                if (ret)
                        goto out_page;
 
-               down(&f->sem);
+               mutex_lock(&f->sem);
                memset(&ri, 0, sizeof(ri));
 
                ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -181,7 +181,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
                if (IS_ERR(fn)) {
                        ret = PTR_ERR(fn);
                        jffs2_complete_reservation(c);
-                       up(&f->sem);
+                       mutex_unlock(&f->sem);
                        goto out_page;
                }
                ret = jffs2_add_full_dnode_to_inode(c, f, fn);
@@ -195,12 +195,12 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
                        jffs2_mark_node_obsolete(c, fn->raw);
                        jffs2_free_full_dnode(fn);
                        jffs2_complete_reservation(c);
-                       up(&f->sem);
+                       mutex_unlock(&f->sem);
                        goto out_page;
                }
                jffs2_complete_reservation(c);
                inode->i_size = pageofs;
-               up(&f->sem);
+               mutex_unlock(&f->sem);
        }
 
        /*
@@ -209,9 +209,9 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
         * case of a short-copy.
         */
        if (!PageUptodate(pg)) {
-               down(&f->sem);
+               mutex_lock(&f->sem);
                ret = jffs2_do_readpage_nolock(inode, pg);
-               up(&f->sem);
+               mutex_unlock(&f->sem);
                if (ret)
                        goto out_page;
        }
index e26ea78c7892f7a4f157819a06e052add03057fd..3eb1c84b0a33289b62dfef1dd21d774647302d64 100644 (file)
@@ -36,6 +36,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
        unsigned int ivalid;
        uint32_t alloclen;
        int ret;
+       int alloc_type = ALLOC_NORMAL;
 
        D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino));
 
@@ -50,20 +51,20 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
                mdata = (char *)&dev;
                D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen));
        } else if (S_ISLNK(inode->i_mode)) {
-               down(&f->sem);
+               mutex_lock(&f->sem);
                mdatalen = f->metadata->size;
                mdata = kmalloc(f->metadata->size, GFP_USER);
                if (!mdata) {
-                       up(&f->sem);
+                       mutex_unlock(&f->sem);
                        return -ENOMEM;
                }
                ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen);
                if (ret) {
-                       up(&f->sem);
+                       mutex_unlock(&f->sem);
                        kfree(mdata);
                        return ret;
                }
-               up(&f->sem);
+               mutex_unlock(&f->sem);
                D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen));
        }
 
@@ -82,7 +83,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
                         kfree(mdata);
                return ret;
        }
-       down(&f->sem);
+       mutex_lock(&f->sem);
        ivalid = iattr->ia_valid;
 
        ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -115,6 +116,10 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
                ri->compr = JFFS2_COMPR_ZERO;
                ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size);
                ri->offset = cpu_to_je32(inode->i_size);
+       } else if (ivalid & ATTR_SIZE && !iattr->ia_size) {
+               /* For truncate-to-zero, treat it as deletion because
+                  it'll always be obsoleting all previous nodes */
+               alloc_type = ALLOC_DELETION;
        }
        ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
        if (mdatalen)
@@ -122,14 +127,14 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
        else
                ri->data_crc = cpu_to_je32(0);
 
-       new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, ALLOC_NORMAL);
+       new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, alloc_type);
        if (S_ISLNK(inode->i_mode))
                kfree(mdata);
 
        if (IS_ERR(new_metadata)) {
                jffs2_complete_reservation(c);
                jffs2_free_raw_inode(ri);
-               up(&f->sem);
+               mutex_unlock(&f->sem);
                return PTR_ERR(new_metadata);
        }
        /* It worked. Update the inode */
@@ -149,6 +154,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
        if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) {
                jffs2_add_full_dnode_to_inode(c, f, new_metadata);
                inode->i_size = iattr->ia_size;
+               inode->i_blocks = (inode->i_size + 511) >> 9;
                f->metadata = NULL;
        } else {
                f->metadata = new_metadata;
@@ -159,7 +165,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
        }
        jffs2_free_raw_inode(ri);
 
-       up(&f->sem);
+       mutex_unlock(&f->sem);
        jffs2_complete_reservation(c);
 
        /* We have to do the vmtruncate() without f->sem held, since
@@ -167,8 +173,10 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
           We are protected from a simultaneous write() extending i_size
           back past iattr->ia_size, because do_truncate() holds the
           generic inode semaphore. */
-       if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size)
-               vmtruncate(inode, iattr->ia_size);
+       if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) {
+               vmtruncate(inode, iattr->ia_size);      
+               inode->i_blocks = (inode->i_size + 511) >> 9;
+       }       
 
        return 0;
 }
@@ -248,12 +256,12 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
        c = JFFS2_SB_INFO(inode->i_sb);
 
        jffs2_init_inode_info(f);
-       down(&f->sem);
+       mutex_lock(&f->sem);
 
        ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
 
        if (ret) {
-               up(&f->sem);
+               mutex_unlock(&f->sem);
                iget_failed(inode);
                return ERR_PTR(ret);
        }
@@ -330,7 +338,7 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
                printk(KERN_WARNING "jffs2_read_inode(): Bogus imode %o for ino %lu\n", inode->i_mode, (unsigned long)inode->i_ino);
        }
 
-       up(&f->sem);
+       mutex_unlock(&f->sem);
 
        D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n"));
        unlock_new_inode(inode);
@@ -339,7 +347,7 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
 error_io:
        ret = -EIO;
 error:
-       up(&f->sem);
+       mutex_unlock(&f->sem);
        jffs2_do_clear_inode(c, f);
        iget_failed(inode);
        return ERR_PTR(ret);
@@ -380,9 +388,9 @@ int jffs2_remount_fs (struct super_block *sb, int *flags, char *data)
           Flush the writebuffer, if neccecary, else we loose it */
        if (!(sb->s_flags & MS_RDONLY)) {
                jffs2_stop_garbage_collect_thread(c);
-               down(&c->alloc_sem);
+               mutex_lock(&c->alloc_sem);
                jffs2_flush_wbuf_pad(c);
-               up(&c->alloc_sem);
+               mutex_unlock(&c->alloc_sem);
        }
 
        if (!(*flags & MS_RDONLY))
@@ -429,7 +437,7 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
 
        f = JFFS2_INODE_INFO(inode);
        jffs2_init_inode_info(f);
-       down(&f->sem);
+       mutex_lock(&f->sem);
 
        memset(ri, 0, sizeof(*ri));
        /* Set OS-specific defaults for new inodes */
index 32ff0373aa04d0c9f709ec22c64ad9086c343448..bad005664e308b1fd2f30e49ccad91d7afd57b91 100644 (file)
@@ -126,7 +126,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
        int ret = 0, inum, nlink;
        int xattr = 0;
 
-       if (down_interruptible(&c->alloc_sem))
+       if (mutex_lock_interruptible(&c->alloc_sem))
                return -EINTR;
 
        for (;;) {
@@ -143,7 +143,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
                               c->unchecked_size);
                        jffs2_dbg_dump_block_lists_nolock(c);
                        spin_unlock(&c->erase_completion_lock);
-                       up(&c->alloc_sem);
+                       mutex_unlock(&c->alloc_sem);
                        return -ENOSPC;
                }
 
@@ -190,7 +190,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
                         made no progress in this case, but that should be OK */
                        c->checked_ino--;
 
-                       up(&c->alloc_sem);
+                       mutex_unlock(&c->alloc_sem);
                        sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
                        return 0;
 
@@ -210,7 +210,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
                        printk(KERN_WARNING "Returned error for crccheck of ino #%u. Expect badness...\n", ic->ino);
 
                jffs2_set_inocache_state(c, ic, INO_STATE_CHECKEDABSENT);
-               up(&c->alloc_sem);
+               mutex_unlock(&c->alloc_sem);
                return ret;
        }
 
@@ -221,9 +221,15 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
                jeb = jffs2_find_gc_block(c);
 
        if (!jeb) {
-               D1 (printk(KERN_NOTICE "jffs2: Couldn't find erase block to garbage collect!\n"));
+               /* Couldn't find a free block. But maybe we can just erase one and make 'progress'? */
+               if (!list_empty(&c->erase_pending_list)) {
+                       spin_unlock(&c->erase_completion_lock);
+                       mutex_unlock(&c->alloc_sem);
+                       return -EAGAIN;
+               }
+               D1(printk(KERN_NOTICE "jffs2: Couldn't find erase block to garbage collect!\n"));
                spin_unlock(&c->erase_completion_lock);
-               up(&c->alloc_sem);
+               mutex_unlock(&c->alloc_sem);
                return -EIO;
        }
 
@@ -232,7 +238,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
           printk(KERN_DEBUG "Nextblock at  %08x, used_size %08x, dirty_size %08x, wasted_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->free_size));
 
        if (!jeb->used_size) {
-               up(&c->alloc_sem);
+               mutex_unlock(&c->alloc_sem);
                goto eraseit;
        }
 
@@ -248,7 +254,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
                               jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size);
                        jeb->gc_node = raw;
                        spin_unlock(&c->erase_completion_lock);
-                       up(&c->alloc_sem);
+                       mutex_unlock(&c->alloc_sem);
                        BUG();
                }
        }
@@ -266,7 +272,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
                        /* Just mark it obsolete */
                        jffs2_mark_node_obsolete(c, raw);
                }
-               up(&c->alloc_sem);
+               mutex_unlock(&c->alloc_sem);
                goto eraseit_lock;
        }
 
@@ -334,7 +340,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
                */
                printk(KERN_CRIT "Inode #%u already in state %d in jffs2_garbage_collect_pass()!\n",
                       ic->ino, ic->state);
-               up(&c->alloc_sem);
+               mutex_unlock(&c->alloc_sem);
                spin_unlock(&c->inocache_lock);
                BUG();
 
@@ -345,7 +351,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
                   the alloc_sem() (for marking nodes invalid) so we must
                   drop the alloc_sem before sleeping. */
 
-               up(&c->alloc_sem);
+               mutex_unlock(&c->alloc_sem);
                D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() waiting for ino #%u in state %d\n",
                          ic->ino, ic->state));
                sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
@@ -416,7 +422,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
                ret = -ENOSPC;
        }
  release_sem:
-       up(&c->alloc_sem);
+       mutex_unlock(&c->alloc_sem);
 
  eraseit_lock:
        /* If we've finished this block, start it erasing */
@@ -445,7 +451,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c,  struct jffs2_era
        uint32_t start = 0, end = 0, nrfrags = 0;
        int ret = 0;
 
-       down(&f->sem);
+       mutex_lock(&f->sem);
 
        /* Now we have the lock for this inode. Check that it's still the one at the head
           of the list. */
@@ -525,7 +531,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c,  struct jffs2_era
                }
        }
  upnout:
-       up(&f->sem);
+       mutex_unlock(&f->sem);
 
        return ret;
 }
@@ -846,7 +852,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
                /* Prevent the erase code from nicking the obsolete node refs while
                   we're looking at them. I really don't like this extra lock but
                   can't see any alternative. Suggestions on a postcard to... */
-               down(&c->erase_free_sem);
+               mutex_lock(&c->erase_free_sem);
 
                for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) {
 
@@ -899,7 +905,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
                        /* OK. The name really does match. There really is still an older node on
                           the flash which our deletion dirent obsoletes. So we have to write out
                           a new deletion dirent to replace it */
-                       up(&c->erase_free_sem);
+                       mutex_unlock(&c->erase_free_sem);
 
                        D1(printk(KERN_DEBUG "Deletion dirent at %08x still obsoletes real dirent \"%s\" at %08x for ino #%u\n",
                                  ref_offset(fd->raw), fd->name, ref_offset(raw), je32_to_cpu(rd->ino)));
@@ -908,7 +914,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
                        return jffs2_garbage_collect_dirent(c, jeb, f, fd);
                }
 
-               up(&c->erase_free_sem);
+               mutex_unlock(&c->erase_free_sem);
                kfree(rd);
        }
 
@@ -1081,7 +1087,7 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras
        return 0;
 }
 
-static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
+static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *orig_jeb,
                                       struct jffs2_inode_info *f, struct jffs2_full_dnode *fn,
                                       uint32_t start, uint32_t end)
 {
index f4d525b0ea5372d950494cae2e34a1553d445d5d..e2177210f62153bec393482eb6f2e2b58b48f0eb 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <linux/fs.h>
+#include "nodelist.h"
 
 int jffs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                unsigned long arg)
index a841f4973a74824667b94e16f0cf7fe343ac82fa..31559f45fdde31eb511fc89bc564aa180fc1099b 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/version.h>
 #include <linux/rbtree.h>
 #include <linux/posix_acl.h>
-#include <linux/semaphore.h>
+#include <linux/mutex.h>
 
 struct jffs2_inode_info {
        /* We need an internal mutex similar to inode->i_mutex.
@@ -24,7 +24,7 @@ struct jffs2_inode_info {
           before letting GC proceed. Or we'd have to put ugliness
           into the GC code so it didn't attempt to obtain the i_mutex
           for the inode(s) which are already locked */
-       struct semaphore sem;
+       struct mutex sem;
 
        /* The highest (datanode) version number used for this ino */
        uint32_t highest_version;
index 18fca2b9e53192355fe26ca16f71c76b7af35d93..85ef6dbb1be7adb3dbbd3553f008a32fe1c35dfc 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 #include <linux/completion.h>
-#include <linux/semaphore.h>
+#include <linux/mutex.h>
 #include <linux/timer.h>
 #include <linux/wait.h>
 #include <linux/list.h>
@@ -44,7 +44,7 @@ struct jffs2_sb_info {
        struct completion gc_thread_start; /* GC thread start completion */
        struct completion gc_thread_exit; /* GC thread exit completion port */
 
-       struct semaphore alloc_sem;     /* Used to protect all the following
+       struct mutex alloc_sem;         /* Used to protect all the following
                                           fields, and also to protect against
                                           out-of-order writing of nodes. And GC. */
        uint32_t cleanmarker_size;      /* Size of an _inline_ CLEANMARKER
@@ -87,6 +87,7 @@ struct jffs2_sb_info {
        struct list_head erasable_list;         /* Blocks which are completely dirty, and need erasing */
        struct list_head erasable_pending_wbuf_list;    /* Blocks which need erasing but only after the current wbuf is flushed */
        struct list_head erasing_list;          /* Blocks which are currently erasing */
+       struct list_head erase_checking_list;   /* Blocks which are being checked and marked */
        struct list_head erase_pending_list;    /* Blocks which need erasing now */
        struct list_head erase_complete_list;   /* Blocks which are erased and need the clean marker written to them */
        struct list_head free_list;             /* Blocks which are free and ready to be used */
@@ -104,7 +105,7 @@ struct jffs2_sb_info {
        /* Sem to allow jffs2_garbage_collect_deletion_dirent to
           drop the erase_completion_lock while it's holding a pointer
           to an obsoleted node. I don't like this. Alternatives welcomed. */
-       struct semaphore erase_free_sem;
+       struct mutex erase_free_sem;
 
        uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
 
index ec1aae9e695e9fc8955889659b59649a3fe45135..8219df6eb6d8c4191c78745c285272e5ce06f636 100644 (file)
@@ -87,7 +87,7 @@ struct jffs2_raw_node_ref
                xattr_ref or xattr_datum instead. The common part of those structures
                has NULL in the first word. See jffs2_raw_ref_to_ic() below */
        uint32_t flash_offset;
-#define TEST_TOTLEN
+#undef TEST_TOTLEN
 #ifdef TEST_TOTLEN
        uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */
 #endif
index a0313fa8748e375d5ee1c2438794e5052faa360f..9df8f3ef20dfd8d8a39d59ee02d4e14ea2713927 100644 (file)
@@ -48,7 +48,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
        minsize = PAD(minsize);
 
        D1(printk(KERN_DEBUG "jffs2_reserve_space(): Requested 0x%x bytes\n", minsize));
-       down(&c->alloc_sem);
+       mutex_lock(&c->alloc_sem);
 
        D1(printk(KERN_DEBUG "jffs2_reserve_space(): alloc sem got\n"));
 
@@ -57,7 +57,6 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
        /* this needs a little more thought (true <tglx> :)) */
        while(ret == -EAGAIN) {
                while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) {
-                       int ret;
                        uint32_t dirty, avail;
 
                        /* calculate real dirty size
@@ -82,7 +81,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
                                          dirty, c->unchecked_size, c->sector_size));
 
                                spin_unlock(&c->erase_completion_lock);
-                               up(&c->alloc_sem);
+                               mutex_unlock(&c->alloc_sem);
                                return -ENOSPC;
                        }
 
@@ -105,11 +104,11 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
                                D1(printk(KERN_DEBUG "max. available size 0x%08x  < blocksneeded * sector_size 0x%08x, returning -ENOSPC\n",
                                          avail, blocksneeded * c->sector_size));
                                spin_unlock(&c->erase_completion_lock);
-                               up(&c->alloc_sem);
+                               mutex_unlock(&c->alloc_sem);
                                return -ENOSPC;
                        }
 
-                       up(&c->alloc_sem);
+                       mutex_unlock(&c->alloc_sem);
 
                        D1(printk(KERN_DEBUG "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, wasted_size 0x%08x, used_size 0x%08x, erasing_size 0x%08x, bad_size 0x%08x (total 0x%08x of 0x%08x)\n",
                                  c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->wasted_size, c->used_size, c->erasing_size, c->bad_size,
@@ -117,7 +116,10 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
                        spin_unlock(&c->erase_completion_lock);
 
                        ret = jffs2_garbage_collect_pass(c);
-                       if (ret)
+
+                       if (ret == -EAGAIN)
+                               jffs2_erase_pending_blocks(c, 1);
+                       else if (ret)
                                return ret;
 
                        cond_resched();
@@ -125,7 +127,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
                        if (signal_pending(current))
                                return -EINTR;
 
-                       down(&c->alloc_sem);
+                       mutex_lock(&c->alloc_sem);
                        spin_lock(&c->erase_completion_lock);
                }
 
@@ -138,7 +140,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
        if (!ret)
                ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
        if (ret)
-               up(&c->alloc_sem);
+               mutex_unlock(&c->alloc_sem);
        return ret;
 }
 
@@ -463,7 +465,7 @@ void jffs2_complete_reservation(struct jffs2_sb_info *c)
 {
        D1(printk(KERN_DEBUG "jffs2_complete_reservation()\n"));
        jffs2_garbage_collect_trigger(c);
-       up(&c->alloc_sem);
+       mutex_unlock(&c->alloc_sem);
 }
 
 static inline int on_list(struct list_head *obj, struct list_head *head)
@@ -512,7 +514,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                   any jffs2_raw_node_refs. So we don't need to stop erases from
                   happening, or protect against people holding an obsolete
                   jffs2_raw_node_ref without the erase_completion_lock. */
-               down(&c->erase_free_sem);
+               mutex_lock(&c->erase_free_sem);
        }
 
        spin_lock(&c->erase_completion_lock);
@@ -715,7 +717,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
        }
 
  out_erase_sem:
-       up(&c->erase_free_sem);
+       mutex_unlock(&c->erase_free_sem);
 }
 
 int jffs2_thread_should_wake(struct jffs2_sb_info *c)
index e512a93d624954e04b70ab0a27bf85eb43a61fea..4cb4d76de07f4810771e33edb6c8021d0a7896d1 100644 (file)
@@ -825,8 +825,9 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
        else // normal case...
                tn->fn->size = je32_to_cpu(rd->dsize);
 
-       dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n",
-                 ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize);
+       dbg_readinode2("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n",
+                      ref_offset(ref), je32_to_cpu(rd->version),
+                      je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize);
 
        ret = jffs2_add_tn_to_tree(c, rii, tn);
 
@@ -836,13 +837,13 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                jffs2_free_tmp_dnode_info(tn);
                return ret;
        }
-#ifdef JFFS2_DBG_READINODE_MESSAGES
-       dbg_readinode("After adding ver %d:\n", je32_to_cpu(rd->version));
+#ifdef JFFS2_DBG_READINODE2_MESSAGES
+       dbg_readinode2("After adding ver %d:\n", je32_to_cpu(rd->version));
        tn = tn_first(&rii->tn_root);
        while (tn) {
-               dbg_readinode("%p: v %d r 0x%x-0x%x ov %d\n",
-                            tn, tn->version, tn->fn->ofs,
-                            tn->fn->ofs+tn->fn->size, tn->overlapped);
+               dbg_readinode2("%p: v %d r 0x%x-0x%x ov %d\n",
+                              tn, tn->version, tn->fn->ofs,
+                              tn->fn->ofs+tn->fn->size, tn->overlapped);
                tn = tn_next(tn);
        }
 #endif
@@ -1193,7 +1194,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
                JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n",
                        ret, retlen, sizeof(*latest_node));
                /* FIXME: If this fails, there seems to be a memory leak. Find it. */
-               up(&f->sem);
+               mutex_unlock(&f->sem);
                jffs2_do_clear_inode(c, f);
                return ret?ret:-EIO;
        }
@@ -1202,7 +1203,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
        if (crc != je32_to_cpu(latest_node->node_crc)) {
                JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n",
                        f->inocache->ino, ref_offset(rii.latest_ref));
-               up(&f->sem);
+               mutex_unlock(&f->sem);
                jffs2_do_clear_inode(c, f);
                return -EIO;
        }
@@ -1242,7 +1243,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
                        f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL);
                        if (!f->target) {
                                JFFS2_ERROR("can't allocate %d bytes of memory for the symlink target path cache\n", je32_to_cpu(latest_node->csize));
-                               up(&f->sem);
+                               mutex_unlock(&f->sem);
                                jffs2_do_clear_inode(c, f);
                                return -ENOMEM;
                        }
@@ -1255,7 +1256,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
                                        ret = -EIO;
                                kfree(f->target);
                                f->target = NULL;
-                               up(&f->sem);
+                               mutex_unlock(&f->sem);
                                jffs2_do_clear_inode(c, f);
                                return -ret;
                        }
@@ -1273,14 +1274,14 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
                if (f->metadata) {
                        JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n",
                               f->inocache->ino, jemode_to_cpu(latest_node->mode));
-                       up(&f->sem);
+                       mutex_unlock(&f->sem);
                        jffs2_do_clear_inode(c, f);
                        return -EIO;
                }
                if (!frag_first(&f->fragtree)) {
                        JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n",
                               f->inocache->ino, jemode_to_cpu(latest_node->mode));
-                       up(&f->sem);
+                       mutex_unlock(&f->sem);
                        jffs2_do_clear_inode(c, f);
                        return -EIO;
                }
@@ -1289,7 +1290,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
                        JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n",
                               f->inocache->ino, jemode_to_cpu(latest_node->mode));
                        /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
-                       up(&f->sem);
+                       mutex_unlock(&f->sem);
                        jffs2_do_clear_inode(c, f);
                        return -EIO;
                }
@@ -1379,12 +1380,13 @@ int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i
        if (!f)
                return -ENOMEM;
 
-       init_MUTEX_LOCKED(&f->sem);
+       mutex_init(&f->sem);
+       mutex_lock(&f->sem);
        f->inocache = ic;
 
        ret = jffs2_do_read_inode_internal(c, f, &n);
        if (!ret) {
-               up(&f->sem);
+               mutex_unlock(&f->sem);
                jffs2_do_clear_inode(c, f);
        }
        kfree (f);
@@ -1398,7 +1400,7 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
 
        jffs2_clear_acl(f);
        jffs2_xattr_delete_inode(c, f->inocache);
-       down(&f->sem);
+       mutex_lock(&f->sem);
        deleted = f->inocache && !f->inocache->nlink;
 
        if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
@@ -1430,5 +1432,5 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
                        jffs2_del_ino_cache(c, f->inocache);
        }
 
-       up(&f->sem);
+       mutex_unlock(&f->sem);
 }
index 4677355996cc8c49a284e56a909502fe788cf234..f3353df178e707e8072e048e46b23753e5c88d5d 100644 (file)
@@ -47,7 +47,7 @@ static void jffs2_i_init_once(struct kmem_cache *cachep, void *foo)
 {
        struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo;
 
-       init_MUTEX(&ei->sem);
+       mutex_init(&ei->sem);
        inode_init_once(&ei->vfs_inode);
 }
 
@@ -55,9 +55,9 @@ static int jffs2_sync_fs(struct super_block *sb, int wait)
 {
        struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
 
-       down(&c->alloc_sem);
+       mutex_lock(&c->alloc_sem);
        jffs2_flush_wbuf_pad(c);
-       up(&c->alloc_sem);
+       mutex_unlock(&c->alloc_sem);
        return 0;
 }
 
@@ -95,8 +95,8 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
 
        /* Initialize JFFS2 superblock locks, the further initialization will
         * be done later */
-       init_MUTEX(&c->alloc_sem);
-       init_MUTEX(&c->erase_free_sem);
+       mutex_init(&c->alloc_sem);
+       mutex_init(&c->erase_free_sem);
        init_waitqueue_head(&c->erase_wait);
        init_waitqueue_head(&c->inocache_wq);
        spin_lock_init(&c->erase_completion_lock);
@@ -125,9 +125,9 @@ static void jffs2_put_super (struct super_block *sb)
 
        D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n"));
 
-       down(&c->alloc_sem);
+       mutex_lock(&c->alloc_sem);
        jffs2_flush_wbuf_pad(c);
-       up(&c->alloc_sem);
+       mutex_unlock(&c->alloc_sem);
 
        jffs2_sum_exit(c);
 
index d1d4f27464baf879825eb72ac4ad4812acfaa0fd..8de52b6076785816abf1625fbb2b64534a7c5610 100644 (file)
@@ -578,8 +578,8 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
        if (!jffs2_is_writebuffered(c))
                return 0;
 
-       if (!down_trylock(&c->alloc_sem)) {
-               up(&c->alloc_sem);
+       if (mutex_trylock(&c->alloc_sem)) {
+               mutex_unlock(&c->alloc_sem);
                printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n");
                BUG();
        }
@@ -702,10 +702,10 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino)
        if (!c->wbuf)
                return 0;
 
-       down(&c->alloc_sem);
+       mutex_lock(&c->alloc_sem);
        if (!jffs2_wbuf_pending_for_ino(c, ino)) {
                D1(printk(KERN_DEBUG "Ino #%d not pending in wbuf. Returning\n", ino));
-               up(&c->alloc_sem);
+               mutex_unlock(&c->alloc_sem);
                return 0;
        }
 
@@ -725,14 +725,14 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino)
        } else while (old_wbuf_len &&
                      old_wbuf_ofs == c->wbuf_ofs) {
 
-               up(&c->alloc_sem);
+               mutex_unlock(&c->alloc_sem);
 
                D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() calls gc pass\n"));
 
                ret = jffs2_garbage_collect_pass(c);
                if (ret) {
                        /* GC failed. Flush it with padding instead */
-                       down(&c->alloc_sem);
+                       mutex_lock(&c->alloc_sem);
                        down_write(&c->wbuf_sem);
                        ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);
                        /* retry flushing wbuf in case jffs2_wbuf_recover
@@ -742,12 +742,12 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino)
                        up_write(&c->wbuf_sem);
                        break;
                }
-               down(&c->alloc_sem);
+               mutex_lock(&c->alloc_sem);
        }
 
        D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() ends...\n"));
 
-       up(&c->alloc_sem);
+       mutex_unlock(&c->alloc_sem);
        return ret;
 }
 
@@ -1236,12 +1236,24 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) {
        if (!c->wbuf)
                return -ENOMEM;
 
+#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
+       c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
+       if (!c->wbuf_verify) {
+               kfree(c->oobbuf);
+               kfree(c->wbuf);
+               return -ENOMEM;
+       }
+#endif
+
        printk(KERN_INFO "JFFS2 write-buffering enabled buffer (%d) erasesize (%d)\n", c->wbuf_pagesize, c->sector_size);
 
        return 0;
 }
 
 void jffs2_dataflash_cleanup(struct jffs2_sb_info *c) {
+#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
+       kfree(c->wbuf_verify);
+#endif
        kfree(c->wbuf);
 }
 
index 776f13cbf2b5e62fef50abfee752e71f93b5e0ee..665fce9797d38d4569a92056f1391bdb5c0a9279 100644 (file)
@@ -137,12 +137,12 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
                                                             JFFS2_SUMMARY_INODE_SIZE);
                        } else {
                                /* Locking pain */
-                               up(&f->sem);
+                               mutex_unlock(&f->sem);
                                jffs2_complete_reservation(c);
 
                                ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &dummy,
                                                          alloc_mode, JFFS2_SUMMARY_INODE_SIZE);
-                               down(&f->sem);
+                               mutex_lock(&f->sem);
                        }
 
                        if (!ret) {
@@ -285,12 +285,12 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
                                                             JFFS2_SUMMARY_DIRENT_SIZE(namelen));
                        } else {
                                /* Locking pain */
-                               up(&f->sem);
+                               mutex_unlock(&f->sem);
                                jffs2_complete_reservation(c);
 
                                ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &dummy,
                                                          alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
-                               down(&f->sem);
+                               mutex_lock(&f->sem);
                        }
 
                        if (!ret) {
@@ -353,7 +353,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
                        D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret));
                        break;
                }
-               down(&f->sem);
+               mutex_lock(&f->sem);
                datalen = min_t(uint32_t, writelen, PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1)));
                cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen);
 
@@ -381,7 +381,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
 
                if (IS_ERR(fn)) {
                        ret = PTR_ERR(fn);
-                       up(&f->sem);
+                       mutex_unlock(&f->sem);
                        jffs2_complete_reservation(c);
                        if (!retried) {
                                /* Write error to be retried */
@@ -403,11 +403,11 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
                        jffs2_mark_node_obsolete(c, fn->raw);
                        jffs2_free_full_dnode(fn);
 
-                       up(&f->sem);
+                       mutex_unlock(&f->sem);
                        jffs2_complete_reservation(c);
                        break;
                }
-               up(&f->sem);
+               mutex_unlock(&f->sem);
                jffs2_complete_reservation(c);
                if (!datalen) {
                        printk(KERN_WARNING "Eep. We didn't actually write any data in jffs2_write_inode_range()\n");
@@ -439,7 +439,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
                                JFFS2_SUMMARY_INODE_SIZE);
        D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen));
        if (ret) {
-               up(&f->sem);
+               mutex_unlock(&f->sem);
                return ret;
        }
 
@@ -454,7 +454,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
        if (IS_ERR(fn)) {
                D1(printk(KERN_DEBUG "jffs2_write_dnode() failed\n"));
                /* Eeek. Wave bye bye */
-               up(&f->sem);
+               mutex_unlock(&f->sem);
                jffs2_complete_reservation(c);
                return PTR_ERR(fn);
        }
@@ -463,7 +463,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
        */
        f->metadata = fn;
 
-       up(&f->sem);
+       mutex_unlock(&f->sem);
        jffs2_complete_reservation(c);
 
        ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode);
@@ -489,7 +489,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
                return -ENOMEM;
        }
 
-       down(&dir_f->sem);
+       mutex_lock(&dir_f->sem);
 
        rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
        rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
@@ -513,7 +513,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
                /* dirent failed to write. Delete the inode normally
                   as if it were the final unlink() */
                jffs2_complete_reservation(c);
-               up(&dir_f->sem);
+               mutex_unlock(&dir_f->sem);
                return PTR_ERR(fd);
        }
 
@@ -522,7 +522,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
        jffs2_add_fd_to_list(c, fd, &dir_f->dents);
 
        jffs2_complete_reservation(c);
-       up(&dir_f->sem);
+       mutex_unlock(&dir_f->sem);
 
        return 0;
 }
@@ -551,7 +551,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
                        return ret;
                }
 
-               down(&dir_f->sem);
+               mutex_lock(&dir_f->sem);
 
                /* Build a deletion node */
                rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -574,21 +574,21 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
 
                if (IS_ERR(fd)) {
                        jffs2_complete_reservation(c);
-                       up(&dir_f->sem);
+                       mutex_unlock(&dir_f->sem);
                        return PTR_ERR(fd);
                }
 
                /* File it. This will mark the old one obsolete. */
                jffs2_add_fd_to_list(c, fd, &dir_f->dents);
-               up(&dir_f->sem);
+               mutex_unlock(&dir_f->sem);
        } else {
-               struct jffs2_full_dirent *fd = dir_f->dents;
                uint32_t nhash = full_name_hash(name, namelen);
 
+               fd = dir_f->dents;
                /* We don't actually want to reserve any space, but we do
                   want to be holding the alloc_sem when we write to flash */
-               down(&c->alloc_sem);
-               down(&dir_f->sem);
+               mutex_lock(&c->alloc_sem);
+               mutex_lock(&dir_f->sem);
 
                for (fd = dir_f->dents; fd; fd = fd->next) {
                        if (fd->nhash == nhash &&
@@ -607,7 +607,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
                                break;
                        }
                }
-               up(&dir_f->sem);
+               mutex_unlock(&dir_f->sem);
        }
 
        /* dead_f is NULL if this was a rename not a real unlink */
@@ -615,7 +615,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
           pointing to an inode which didn't exist. */
        if (dead_f && dead_f->inocache) {
 
-               down(&dead_f->sem);
+               mutex_lock(&dead_f->sem);
 
                if (S_ISDIR(OFNI_EDONI_2SFFJ(dead_f)->i_mode)) {
                        while (dead_f->dents) {
@@ -639,7 +639,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
 
                dead_f->inocache->nlink--;
                /* NB: Caller must set inode nlink if appropriate */
-               up(&dead_f->sem);
+               mutex_unlock(&dead_f->sem);
        }
 
        jffs2_complete_reservation(c);
@@ -666,7 +666,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
                return ret;
        }
 
-       down(&dir_f->sem);
+       mutex_lock(&dir_f->sem);
 
        /* Build a deletion node */
        rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -691,7 +691,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
 
        if (IS_ERR(fd)) {
                jffs2_complete_reservation(c);
-               up(&dir_f->sem);
+               mutex_unlock(&dir_f->sem);
                return PTR_ERR(fd);
        }
 
@@ -699,7 +699,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
        jffs2_add_fd_to_list(c, fd, &dir_f->dents);
 
        jffs2_complete_reservation(c);
-       up(&dir_f->sem);
+       mutex_unlock(&dir_f->sem);
 
        return 0;
 }
index 1f122c1940afa069a6deb31f82103b990867136a..4d81553d29485e69dd19e746a1edadf4618c8d91 100644 (file)
@@ -632,7 +632,7 @@ nlmsvc_update_deferred_block(struct nlm_block *block, struct file_lock *conf,
                block->b_flags |= B_TIMED_OUT;
        if (conf) {
                if (block->b_fl)
-                       locks_copy_lock(block->b_fl, conf);
+                       __locks_copy_lock(block->b_fl, conf);
        }
 }
 
index dbbefbcd671255935c61783e5cf73d4122346cd7..d1c48b539df8723bd8979e502448eee35d4f9adf 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/lockd/lockd.h>
 #include <linux/lockd/share.h>
 #include <linux/lockd/sm_inter.h>
+#include <linux/module.h>
+#include <linux/mount.h>
 
 #define NLMDBG_FACILITY                NLMDBG_SVCSUBS
 
@@ -194,6 +196,12 @@ again:
        return 0;
 }
 
+static int
+nlmsvc_always_match(void *dummy1, struct nlm_host *dummy2)
+{
+       return 1;
+}
+
 /*
  * Inspect a single file
  */
@@ -230,7 +238,8 @@ nlm_file_inuse(struct nlm_file *file)
  * Loop over all files in the file table.
  */
 static int
-nlm_traverse_files(struct nlm_host *host, nlm_host_match_fn_t match)
+nlm_traverse_files(void *data, nlm_host_match_fn_t match,
+               int (*is_failover_file)(void *data, struct nlm_file *file))
 {
        struct hlist_node *pos, *next;
        struct nlm_file *file;
@@ -239,12 +248,14 @@ nlm_traverse_files(struct nlm_host *host, nlm_host_match_fn_t match)
        mutex_lock(&nlm_file_mutex);
        for (i = 0; i < FILE_NRHASH; i++) {
                hlist_for_each_entry_safe(file, pos, next, &nlm_files[i], f_list) {
+                       if (is_failover_file && !is_failover_file(data, file))
+                               continue;
                        file->f_count++;
                        mutex_unlock(&nlm_file_mutex);
 
                        /* Traverse locks, blocks and shares of this file
                         * and update file->f_locks count */
-                       if (nlm_inspect_file(host, file, match))
+                       if (nlm_inspect_file(data, file, match))
                                ret = 1;
 
                        mutex_lock(&nlm_file_mutex);
@@ -303,21 +314,27 @@ nlm_release_file(struct nlm_file *file)
  *     Used by nlmsvc_invalidate_all
  */
 static int
-nlmsvc_mark_host(struct nlm_host *host, struct nlm_host *dummy)
+nlmsvc_mark_host(void *data, struct nlm_host *dummy)
 {
+       struct nlm_host *host = data;
+
        host->h_inuse = 1;
        return 0;
 }
 
 static int
-nlmsvc_same_host(struct nlm_host *host, struct nlm_host *other)
+nlmsvc_same_host(void *data, struct nlm_host *other)
 {
+       struct nlm_host *host = data;
+
        return host == other;
 }
 
 static int
-nlmsvc_is_client(struct nlm_host *host, struct nlm_host *dummy)
+nlmsvc_is_client(void *data, struct nlm_host *dummy)
 {
+       struct nlm_host *host = data;
+
        if (host->h_server) {
                /* we are destroying locks even though the client
                 * hasn't asked us too, so don't unmonitor the
@@ -337,7 +354,7 @@ void
 nlmsvc_mark_resources(void)
 {
        dprintk("lockd: nlmsvc_mark_resources\n");
-       nlm_traverse_files(NULL, nlmsvc_mark_host);
+       nlm_traverse_files(NULL, nlmsvc_mark_host, NULL);
 }
 
 /*
@@ -348,7 +365,7 @@ nlmsvc_free_host_resources(struct nlm_host *host)
 {
        dprintk("lockd: nlmsvc_free_host_resources\n");
 
-       if (nlm_traverse_files(host, nlmsvc_same_host)) {
+       if (nlm_traverse_files(host, nlmsvc_same_host, NULL)) {
                printk(KERN_WARNING
                        "lockd: couldn't remove all locks held by %s\n",
                        host->h_name);
@@ -368,5 +385,41 @@ nlmsvc_invalidate_all(void)
         * turn, which is about as inefficient as it gets.
         * Now we just do it once in nlm_traverse_files.
         */
-       nlm_traverse_files(NULL, nlmsvc_is_client);
+       nlm_traverse_files(NULL, nlmsvc_is_client, NULL);
+}
+
+static int
+nlmsvc_match_sb(void *datap, struct nlm_file *file)
+{
+       struct super_block *sb = datap;
+
+       return sb == file->f_file->f_path.mnt->mnt_sb;
+}
+
+int
+nlmsvc_unlock_all_by_sb(struct super_block *sb)
+{
+       int ret;
+
+       ret = nlm_traverse_files(sb, nlmsvc_always_match, nlmsvc_match_sb);
+       return ret ? -EIO : 0;
+}
+EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_sb);
+
+static int
+nlmsvc_match_ip(void *datap, struct nlm_host *host)
+{
+       __be32 *server_addr = datap;
+
+       return host->h_saddr.sin_addr.s_addr == *server_addr;
+}
+
+int
+nlmsvc_unlock_all_by_ip(__be32 server_addr)
+{
+       int ret;
+       ret = nlm_traverse_files(&server_addr, nlmsvc_match_ip, NULL);
+       return ret ? -EIO : 0;
+
 }
+EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_ip);
index 592faadbcec12f19b2f6ea158e956e2a3b01c838..44d9a6a7ec50caad376e36d721a3a42bc5028948 100644 (file)
@@ -224,7 +224,7 @@ static void locks_copy_private(struct file_lock *new, struct file_lock *fl)
 /*
  * Initialize a new lock from an existing file_lock structure.
  */
-static void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)
+void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)
 {
        new->fl_owner = fl->fl_owner;
        new->fl_pid = fl->fl_pid;
@@ -236,6 +236,7 @@ static void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)
        new->fl_ops = NULL;
        new->fl_lmops = NULL;
 }
+EXPORT_SYMBOL(__locks_copy_lock);
 
 void locks_copy_lock(struct file_lock *new, struct file_lock *fl)
 {
@@ -833,7 +834,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
                        if (!posix_locks_conflict(request, fl))
                                continue;
                        if (conflock)
-                               locks_copy_lock(conflock, fl);
+                               __locks_copy_lock(conflock, fl);
                        error = -EAGAIN;
                        if (!(request->fl_flags & FL_SLEEP))
                                goto out;
@@ -1367,18 +1368,20 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
 
        lease = *flp;
 
-       error = -EAGAIN;
-       if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
-               goto out;
-       if ((arg == F_WRLCK)
-           && ((atomic_read(&dentry->d_count) > 1)
-               || (atomic_read(&inode->i_count) > 1)))
-               goto out;
+       if (arg != F_UNLCK) {
+               error = -ENOMEM;
+               new_fl = locks_alloc_lock();
+               if (new_fl == NULL)
+                       goto out;
 
-       error = -ENOMEM;
-       new_fl = locks_alloc_lock();
-       if (new_fl == NULL)
-               goto out;
+               error = -EAGAIN;
+               if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
+                       goto out;
+               if ((arg == F_WRLCK)
+                   && ((atomic_read(&dentry->d_count) > 1)
+                       || (atomic_read(&inode->i_count) > 1)))
+                       goto out;
+       }
 
        /*
         * At this point, we know that if there is an exclusive
@@ -1404,6 +1407,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
                        rdlease_count++;
        }
 
+       error = -EAGAIN;
        if ((arg == F_RDLCK && (wrlease_count > 0)) ||
            (arg == F_WRLCK && ((rdlease_count + wrlease_count) > 0)))
                goto out;
@@ -1490,8 +1494,7 @@ EXPORT_SYMBOL_GPL(vfs_setlease);
 int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
 {
        struct file_lock fl, *flp = &fl;
-       struct dentry *dentry = filp->f_path.dentry;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        int error;
 
        locks_init_lock(&fl);
index 0505fb61aa740182cfabe890cc668724378c5791..f48f98110c30aefaa114ff0f15c0b7cece3f938d 100644 (file)
@@ -1061,10 +1061,11 @@ static int do_umount(struct vfsmount *mnt, int flags)
         * about for the moment.
         */
 
-       lock_kernel();
-       if (sb->s_op->umount_begin)
-               sb->s_op->umount_begin(mnt, flags);
-       unlock_kernel();
+       if (flags & MNT_FORCE && sb->s_op->umount_begin) {
+               lock_kernel();
+               sb->s_op->umount_begin(sb);
+               unlock_kernel();
+       }
 
        /*
         * No sense to grab the lock for this test, but test itself looks
index 20a1cb1810fef50c9a4ce67f5ec9a5f1312e25ba..fa220dc74609abc1635bbc55b740bd523156ccf0 100644 (file)
@@ -198,7 +198,7 @@ static match_table_t nfs_secflavor_tokens = {
 };
 
 
-static void nfs_umount_begin(struct vfsmount *, int);
+static void nfs_umount_begin(struct super_block *);
 static int  nfs_statfs(struct dentry *, struct kstatfs *);
 static int  nfs_show_options(struct seq_file *, struct vfsmount *);
 static int  nfs_show_stats(struct seq_file *, struct vfsmount *);
@@ -647,13 +647,11 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
  * Begin unmount by attempting to remove all automounted mountpoints we added
  * in response to xdev traversals and referrals
  */
-static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
+static void nfs_umount_begin(struct super_block *sb)
 {
-       struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb);
+       struct nfs_server *server = NFS_SB(sb);
        struct rpc_clnt *rpc;
 
-       if (!(flags & MNT_FORCE))
-               return;
        /* -EIO all pending I/O */
        rpc = server->client_acl;
        if (!IS_ERR(rpc))
index 55dfdd71f1b0d8be42a3ce01a4a15e8228b9aaa0..8799b8708188a3acf901f1d09b8e773865d139c5 100644 (file)
@@ -2712,9 +2712,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        * Note: locks.c uses the BKL to protect the inode's lock list.
        */
 
-       /* XXX?: Just to divert the locks_release_private at the start of
-        * locks_copy_lock: */
-       locks_init_lock(&conflock);
        err = vfs_lock_file(filp, cmd, &file_lock, &conflock);
        switch (-err) {
        case 0: /* success! */
index 1ba7ad981935d6f455d5c3185c78ba0842913898..c513bbdf2d36a2188d286ae1e32cbb81fab16107 100644 (file)
@@ -376,20 +376,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
                        goto xdr_error;
                }
        }
-       if (bmval[1] & FATTR4_WORD1_TIME_METADATA) {
-               /* We require the high 32 bits of 'seconds' to be 0, and we ignore
-                  all 32 bits of 'nseconds'. */
-               READ_BUF(12);
-               len += 12;
-               READ32(dummy32);
-               if (dummy32)
-                       return nfserr_inval;
-               READ32(iattr->ia_ctime.tv_sec);
-               READ32(iattr->ia_ctime.tv_nsec);
-               if (iattr->ia_ctime.tv_nsec >= (u32)1000000000)
-                       return nfserr_inval;
-               iattr->ia_valid |= ATTR_CTIME;
-       }
        if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
                READ_BUF(4);
                len += 4;
index 613bcb8171a5da1a649f5a5ab01601e42830a9f5..42f3820ee8f543ca022d019b3b1de49e5907648c 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/seq_file.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
+#include <linux/inet.h>
 #include <linux/string.h>
 #include <linux/smp_lock.h>
 #include <linux/ctype.h>
@@ -35,6 +36,7 @@
 #include <linux/nfsd/cache.h>
 #include <linux/nfsd/xdr.h>
 #include <linux/nfsd/syscall.h>
+#include <linux/lockd/lockd.h>
 
 #include <asm/uaccess.h>
 #include <net/ipv6.h>
@@ -53,6 +55,8 @@ enum {
        NFSD_Getfs,
        NFSD_List,
        NFSD_Fh,
+       NFSD_FO_UnlockIP,
+       NFSD_FO_UnlockFS,
        NFSD_Threads,
        NFSD_Pool_Threads,
        NFSD_Versions,
@@ -89,6 +93,9 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
 #endif
 
+static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size);
+static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size);
+
 static ssize_t (*write_op[])(struct file *, char *, size_t) = {
        [NFSD_Svc] = write_svc,
        [NFSD_Add] = write_add,
@@ -98,6 +105,8 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
        [NFSD_Getfd] = write_getfd,
        [NFSD_Getfs] = write_getfs,
        [NFSD_Fh] = write_filehandle,
+       [NFSD_FO_UnlockIP] = failover_unlock_ip,
+       [NFSD_FO_UnlockFS] = failover_unlock_fs,
        [NFSD_Threads] = write_threads,
        [NFSD_Pool_Threads] = write_pool_threads,
        [NFSD_Versions] = write_versions,
@@ -298,6 +307,58 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
        return err;
 }
 
+static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size)
+{
+       __be32 server_ip;
+       char *fo_path, c;
+       int b1, b2, b3, b4;
+
+       /* sanity check */
+       if (size == 0)
+               return -EINVAL;
+
+       if (buf[size-1] != '\n')
+               return -EINVAL;
+
+       fo_path = buf;
+       if (qword_get(&buf, fo_path, size) < 0)
+               return -EINVAL;
+
+       /* get ipv4 address */
+       if (sscanf(fo_path, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
+               return -EINVAL;
+       server_ip = htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
+
+       return nlmsvc_unlock_all_by_ip(server_ip);
+}
+
+static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size)
+{
+       struct nameidata nd;
+       char *fo_path;
+       int error;
+
+       /* sanity check */
+       if (size == 0)
+               return -EINVAL;
+
+       if (buf[size-1] != '\n')
+               return -EINVAL;
+
+       fo_path = buf;
+       if (qword_get(&buf, fo_path, size) < 0)
+               return -EINVAL;
+
+       error = path_lookup(fo_path, 0, &nd);
+       if (error)
+               return error;
+
+       error = nlmsvc_unlock_all_by_sb(nd.path.mnt->mnt_sb);
+
+       path_put(&nd.path);
+       return error;
+}
+
 static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
 {
        /* request is:
@@ -700,6 +761,10 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
                [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
                [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
                [NFSD_List] = {"exports", &exports_operations, S_IRUGO},
+               [NFSD_FO_UnlockIP] = {"unlock_ip",
+                                       &transaction_ops, S_IWUSR|S_IRUSR},
+               [NFSD_FO_UnlockFS] = {"unlock_filesystem",
+                                       &transaction_ops, S_IWUSR|S_IRUSR},
                [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
                [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
                [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},
index ade9a7e6a75763cd11304a638113f86e18f09d01..dbdfabbfd609661b6c585b8bc9962dae2d057634 100644 (file)
@@ -477,11 +477,10 @@ const struct file_operations sysfs_file_operations = {
        .poll           = sysfs_poll,
 };
 
-
-int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
-                  int type)
+int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,
+                       const struct attribute *attr, int type, mode_t amode)
 {
-       umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
+       umode_t mode = (amode & S_IALLUGO) | S_IFREG;
        struct sysfs_addrm_cxt acxt;
        struct sysfs_dirent *sd;
        int rc;
@@ -502,6 +501,13 @@ int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
 }
 
 
+int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
+                  int type)
+{
+       return sysfs_add_file_mode(dir_sd, attr, type, attr->mode);
+}
+
+
 /**
  *     sysfs_create_file - create an attribute file for an object.
  *     @kobj:  object we're creating for. 
index 477904915032e9359893d6128f3515a1d86963c7..eeba38417b1d4c5db2a54e381fb68b8441eb7743 100644 (file)
@@ -23,35 +23,50 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
        int i;
 
        for (i = 0, attr = grp->attrs; *attr; i++, attr++)
-               if (!grp->is_visible ||
-                   grp->is_visible(kobj, *attr, i))
-                       sysfs_hash_and_remove(dir_sd, (*attr)->name);
+               sysfs_hash_and_remove(dir_sd, (*attr)->name);
 }
 
 static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
-                       const struct attribute_group *grp)
+                       const struct attribute_group *grp, int update)
 {
        struct attribute *const* attr;
        int error = 0, i;
 
-       for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++)
-               if (!grp->is_visible ||
-                   grp->is_visible(kobj, *attr, i))
-                       error |=
-                               sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
+       for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) {
+               mode_t mode = 0;
+
+               /* in update mode, we're changing the permissions or
+                * visibility.  Do this by first removing then
+                * re-adding (if required) the file */
+               if (update)
+                       sysfs_hash_and_remove(dir_sd, (*attr)->name);
+               if (grp->is_visible) {
+                       mode = grp->is_visible(kobj, *attr, i);
+                       if (!mode)
+                               continue;
+               }
+               error = sysfs_add_file_mode(dir_sd, *attr, SYSFS_KOBJ_ATTR,
+                                           (*attr)->mode | mode);
+               if (unlikely(error))
+                       break;
+       }
        if (error)
                remove_files(dir_sd, kobj, grp);
        return error;
 }
 
 
-int sysfs_create_group(struct kobject * kobj, 
-                      const struct attribute_group * grp)
+static int internal_create_group(struct kobject *kobj, int update,
+                                const struct attribute_group *grp)
 {
        struct sysfs_dirent *sd;
        int error;
 
-       BUG_ON(!kobj || !kobj->sd);
+       BUG_ON(!kobj || (!update && !kobj->sd));
+
+       /* Updates may happen before the object has been instantiated */
+       if (unlikely(update && !kobj->sd))
+               return -EINVAL;
 
        if (grp->name) {
                error = sysfs_create_subdir(kobj, grp->name, &sd);
@@ -60,7 +75,7 @@ int sysfs_create_group(struct kobject * kobj,
        } else
                sd = kobj->sd;
        sysfs_get(sd);
-       error = create_files(sd, kobj, grp);
+       error = create_files(sd, kobj, grp, update);
        if (error) {
                if (grp->name)
                        sysfs_remove_subdir(sd);
@@ -69,6 +84,47 @@ int sysfs_create_group(struct kobject * kobj,
        return error;
 }
 
+/**
+ * sysfs_create_group - given a directory kobject, create an attribute group
+ * @kobj:      The kobject to create the group on
+ * @grp:       The attribute group to create
+ *
+ * This function creates a group for the first time.  It will explicitly
+ * warn and error if any of the attribute files being created already exist.
+ *
+ * Returns 0 on success or error.
+ */
+int sysfs_create_group(struct kobject *kobj,
+                      const struct attribute_group *grp)
+{
+       return internal_create_group(kobj, 0, grp);
+}
+
+/**
+ * sysfs_update_group - given a directory kobject, create an attribute group
+ * @kobj:      The kobject to create the group on
+ * @grp:       The attribute group to create
+ *
+ * This function updates an attribute group.  Unlike
+ * sysfs_create_group(), it will explicitly not warn or error if any
+ * of the attribute files being created already exist.  Furthermore,
+ * if the visibility of the files has changed through the is_visible()
+ * callback, it will update the permissions and add or remove the
+ * relevant files.
+ *
+ * The primary use for this function is to call it after making a change
+ * that affects group visibility.
+ *
+ * Returns 0 on success or error.
+ */
+int sysfs_update_group(struct kobject *kobj,
+                      const struct attribute_group *grp)
+{
+       return internal_create_group(kobj, 1, grp);
+}
+
+
+
 void sysfs_remove_group(struct kobject * kobj, 
                        const struct attribute_group * grp)
 {
@@ -95,4 +151,5 @@ void sysfs_remove_group(struct kobject * kobj,
 
 
 EXPORT_SYMBOL_GPL(sysfs_create_group);
+EXPORT_SYMBOL_GPL(sysfs_update_group);
 EXPORT_SYMBOL_GPL(sysfs_remove_group);
index ff17f8da9b43f5d47ec69a80021e51aa04ffed8b..ce4e15f8aaebce521b4e8b4469c5923307cedad3 100644 (file)
@@ -154,6 +154,8 @@ extern const struct file_operations sysfs_file_operations;
 int sysfs_add_file(struct sysfs_dirent *dir_sd,
                   const struct attribute *attr, int type);
 
+int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,
+                       const struct attribute *attr, int type, mode_t amode);
 /*
  * bin.c
  */
index 9e19a704d4840693a31bd88413060024e3623266..15f3ae25c51137bb8af4a67b5d5e8cbbea328241 100644 (file)
@@ -388,6 +388,11 @@ static inline int fls64(unsigned long x)
 }
 #endif
 
+static inline unsigned long __fls(unsigned long x)
+{
+       return fls64(x) - 1;
+}
+
 static inline int fls(int x)
 {
        return fls64((unsigned int) x);
index 50c77eacbd5e435526ff36d1a5027181cfe19672..b6c8fe37768315bcc5081490572e2493e15910cf 100644 (file)
 /* ITE8152 irqs */
 /* add IT8152 IRQs beyond BOARD_END */
 #ifdef CONFIG_PCI_HOST_ITE8152
-#define IT8152_IRQ(x)   (IRQ_GPIO(IRQ_BOARD_END) + 1 + (x))
+#define IT8152_IRQ(x)   (IRQ_BOARD_END + (x))
 
 /* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */
 #define IT8152_LD_IRQ_COUNT     9
 
 #define IT8152_LAST_IRQ         IT8152_LD_IRQ(IT8152_LD_IRQ_COUNT - 1)
 
+#if NR_IRQS < (IT8152_LAST_IRQ+1)
 #undef NR_IRQS
 #define NR_IRQS (IT8152_LAST_IRQ+1)
 #endif
+
+#endif /* CONFIG_PCI_HOST_ITE8152 */
index b34fd5683e2d20876805e6b7abe25a8708babced..169b374f9921968031b0b7dccb22673e3366256a 100644 (file)
@@ -13,7 +13,6 @@
 #define _MAGICIAN_H_
 
 #include <asm/arch/irqs.h>
-#include <asm/arch/pxa2xx-gpio.h>
 
 /*
  * PXA GPIOs
 #define GPIO119_MAGICIAN_UNKNOWN               119
 #define GPIO120_MAGICIAN_UNKNOWN               120
 
-/*
- * PXA GPIO alternate function mode & direction
- */
-
-#define GPIO0_MAGICIAN_KEY_POWER_MD            (0 | GPIO_IN)
-#define GPIO9_MAGICIAN_UNKNOWN_MD              (9 | GPIO_IN)
-#define GPIO10_MAGICIAN_GSM_IRQ_MD             (10 | GPIO_IN)
-#define GPIO11_MAGICIAN_GSM_OUT1_MD            (11 | GPIO_OUT)
-#define GPIO13_MAGICIAN_CPLD_IRQ_MD            (13 | GPIO_IN)
-#define GPIO18_MAGICIAN_UNKNOWN_MD             (18 | GPIO_OUT)
-#define GPIO22_MAGICIAN_VIBRA_EN_MD            (22 | GPIO_OUT)
-#define GPIO26_MAGICIAN_GSM_POWER_MD           (26 | GPIO_OUT)
-#define GPIO27_MAGICIAN_USBC_PUEN_MD           (27 | GPIO_OUT)
-#define GPIO30_MAGICIAN_nCHARGE_EN_MD          (30 | GPIO_OUT)
-#define GPIO37_MAGICIAN_KEY_HANGUP_MD          (37 | GPIO_OUT)
-#define GPIO38_MAGICIAN_KEY_CONTACTS_MD                (38 | GPIO_OUT)
-#define GPIO40_MAGICIAN_GSM_OUT2_MD            (40 | GPIO_OUT)
-#define GPIO48_MAGICIAN_UNKNOWN_MD             (48 | GPIO_OUT)
-#define GPIO56_MAGICIAN_UNKNOWN_MD             (56 | GPIO_OUT)
-#define GPIO57_MAGICIAN_CAM_RESET_MD           (57 | GPIO_OUT)
-#define GPIO75_MAGICIAN_SAMSUNG_POWER_MD       (75 | GPIO_OUT)
-#define GPIO83_MAGICIAN_nIR_EN_MD              (83 | GPIO_OUT)
-#define GPIO86_MAGICIAN_GSM_RESET_MD           (86 | GPIO_OUT)
-#define GPIO87_MAGICIAN_GSM_SELECT_MD          (87 | GPIO_OUT)
-#define GPIO90_MAGICIAN_KEY_CALENDAR_MD                (90 | GPIO_OUT)
-#define GPIO91_MAGICIAN_KEY_CAMERA_MD          (91 | GPIO_OUT)
-#define GPIO93_MAGICIAN_KEY_UP_MD              (93 | GPIO_IN)
-#define GPIO94_MAGICIAN_KEY_DOWN_MD            (94 | GPIO_IN)
-#define GPIO95_MAGICIAN_KEY_LEFT_MD            (95 | GPIO_IN)
-#define GPIO96_MAGICIAN_KEY_RIGHT_MD           (96 | GPIO_IN)
-#define GPIO97_MAGICIAN_KEY_ENTER_MD           (97 | GPIO_IN)
-#define GPIO98_MAGICIAN_KEY_RECORD_MD          (98 | GPIO_IN)
-#define GPIO99_MAGICIAN_HEADPHONE_IN_MD                (99 | GPIO_IN)
-#define GPIO100_MAGICIAN_KEY_VOL_UP_MD         (100 | GPIO_IN)
-#define GPIO101_MAGICIAN_KEY_VOL_DOWN_MD       (101 | GPIO_IN)
-#define GPIO102_MAGICIAN_KEY_PHONE_MD          (102 | GPIO_IN)
-#define GPIO103_MAGICIAN_LED_KP_MD             (103 | GPIO_OUT)
-#define GPIO104_MAGICIAN_LCD_POWER_1_MD        (104 | GPIO_OUT)
-#define GPIO105_MAGICIAN_LCD_POWER_2_MD                (105 | GPIO_OUT)
-#define GPIO106_MAGICIAN_LCD_POWER_3_MD                (106 | GPIO_OUT)
-#define GPIO107_MAGICIAN_DS1WM_IRQ_MD          (107 | GPIO_IN)
-#define GPIO108_MAGICIAN_GSM_READY_MD          (108 | GPIO_IN)
-#define GPIO114_MAGICIAN_UNKNOWN_MD            (114 | GPIO_OUT)
-#define GPIO115_MAGICIAN_nPEN_IRQ_MD           (115 | GPIO_IN)
-#define GPIO116_MAGICIAN_nCAM_EN_MD            (116 | GPIO_OUT)
-#define GPIO119_MAGICIAN_UNKNOWN_MD            (119 | GPIO_OUT)
-#define GPIO120_MAGICIAN_UNKNOWN_MD            (120 | GPIO_OUT)
-
 /*
  * CPLD IRQs
  */
diff --git a/include/asm-arm/arch-pxa/pxa3xx_nand.h b/include/asm-arm/arch-pxa/pxa3xx_nand.h
new file mode 100644 (file)
index 0000000..81a8937
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef __ASM_ARCH_PXA3XX_NAND_H
+#define __ASM_ARCH_PXA3XX_NAND_H
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+struct pxa3xx_nand_platform_data {
+
+       /* the data flash bus is shared between the Static Memory
+        * Controller and the Data Flash Controller,  the arbiter
+        * controls the ownership of the bus
+        */
+       int     enable_arbiter;
+
+       struct mtd_partition *parts;
+       unsigned int    nr_parts;
+};
+#endif /* __ASM_ARCH_PXA3XX_NAND_H */
index 1d56a3ef89fd3844df65403921f6a6b6c6ad45ab..a758a719180f64e5f4167eea0e9b6ca8b6ff3a75 100644 (file)
@@ -22,6 +22,8 @@ static inline void arch_idle(void)
 
 static inline void arch_reset(char mode)
 {
+       RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+
        if (mode == 's') {
                /* Jump into ROM at address 0 */
                cpu_reset(0);
index 98b10bcf9f1b87d44058bed3c1f9753415fd1de8..b14cbda01dc3cce14c715ffef836dde3d1fbabe9 100644 (file)
@@ -37,12 +37,12 @@ static inline void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
 
        memset(hw, 0, sizeof(*hw));
 
-       for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-               hw->io_ports[i] = reg;
+       for (i = 0; i <= 7; i++) {
+               hw->io_ports_array[i] = reg;
                reg += regincr;
        }
 
-       hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+       hw->io_ports.ctl_addr = ctrl_port;
 
        if (irq)
                *irq = 0;
index 8816f7f9cee15add2e5614d281db721c374c0392..ad6bbe90616e2e026810deabffe71f90fafd2ab5 100644 (file)
 */
 
 struct s3c2410_nand_set {
+       unsigned int            disable_ecc : 1;
+
        int                     nr_chips;
        int                     nr_partitions;
        char                    *name;
        int                     *nr_map;
        struct mtd_partition    *partitions;
+       struct nand_ecclayout   *ecc_layout;
 };
 
 struct s3c2410_platform_nand {
@@ -36,6 +39,8 @@ struct s3c2410_platform_nand {
        int     twrph0; /* active time for nWE/nOE */
        int     twrph1; /* time for release CLE/ALE from nWE/nOE inactive */
 
+       unsigned int    ignore_unset_ecc : 1;
+
        int                     nr_sets;
        struct s3c2410_nand_set *sets;
 
index ea34e0d0a3884690a3e66ff7fd1bdeb6a24f596e..5366e62393288e20225811fd764cbfbd04fa367b 100644 (file)
@@ -59,22 +59,19 @@ static inline void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, u
        int i;
 
        /* fill in ports for ATA addresses 0 to 7 */
-
-       for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-               hw->io_ports[i] = data_port |
+       for (i = 0; i <= 7; i++) {
+               hw->io_ports_array[i] = data_port |
                        IO_FIELD(R_ATA_CTRL_DATA, addr, i) |
                        IO_STATE(R_ATA_CTRL_DATA, cs0, active);
        }
 
        /* the IDE control register is at ATA address 6, with CS1 active instead of CS0 */
-
-       hw->io_ports[IDE_CONTROL_OFFSET] = data_port |
+       hw->io_ports.ctl_addr = data_port |
                        IO_FIELD(R_ATA_CTRL_DATA, addr, 6) |
                        IO_STATE(R_ATA_CTRL_DATA, cs1, active);
 
        /* whats this for ? */
-
-       hw->io_ports[IDE_IRQ_OFFSET] = 0;
+       hw->io_ports.irq_addr = 0;
 }
 
 static inline void ide_init_default_hwifs(void)
diff --git a/include/asm-generic/bitops/__fls.h b/include/asm-generic/bitops/__fls.h
new file mode 100644 (file)
index 0000000..be24465
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef _ASM_GENERIC_BITOPS___FLS_H_
+#define _ASM_GENERIC_BITOPS___FLS_H_
+
+#include <asm/types.h>
+
+/**
+ * __fls - find last (most-significant) set bit in a long word
+ * @word: the word to search
+ *
+ * Undefined if no set bit exists, so code should check against 0 first.
+ */
+static inline unsigned long __fls(unsigned long word)
+{
+       int num = BITS_PER_LONG - 1;
+
+#if BITS_PER_LONG == 64
+       if (!(word & (~0ul << 32))) {
+               num -= 32;
+               word <<= 32;
+       }
+#endif
+       if (!(word & (~0ul << (BITS_PER_LONG-16)))) {
+               num -= 16;
+               word <<= 16;
+       }
+       if (!(word & (~0ul << (BITS_PER_LONG-8)))) {
+               num -= 8;
+               word <<= 8;
+       }
+       if (!(word & (~0ul << (BITS_PER_LONG-4)))) {
+               num -= 4;
+               word <<= 4;
+       }
+       if (!(word & (~0ul << (BITS_PER_LONG-2)))) {
+               num -= 2;
+               word <<= 2;
+       }
+       if (!(word & (~0ul << (BITS_PER_LONG-1))))
+               num -= 1;
+       return num;
+}
+
+#endif /* _ASM_GENERIC_BITOPS___FLS_H_ */
index 72a51e5a12ef1b3738f25249eeed3417745788c1..1914e9742512db6d9bd5e9be5bc9be30ad510c0f 100644 (file)
@@ -1,11 +1,13 @@
 #ifndef _ASM_GENERIC_BITOPS_FIND_H_
 #define _ASM_GENERIC_BITOPS_FIND_H_
 
+#ifndef CONFIG_GENERIC_FIND_NEXT_BIT
 extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
                size, unsigned long offset);
 
 extern unsigned long find_next_zero_bit(const unsigned long *addr, unsigned
                long size, unsigned long offset);
+#endif
 
 #define find_first_bit(addr, size) find_next_bit((addr), (size), 0)
 #define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
index 1b6b17ce2428091e605c8cbda7103b1d42836780..86d403f8b256815761270e822b84b438cc87f5d2 100644 (file)
@@ -3,6 +3,18 @@
 
 #include <asm/types.h>
 
+/**
+ * fls64 - find last set bit in a 64-bit word
+ * @x: the word to search
+ *
+ * This is defined in a similar way as the libc and compiler builtin
+ * ffsll, but returns the position of the most significant set bit.
+ *
+ * fls64(value) returns 0 if value is 0 or the position of the last
+ * set bit if value is nonzero. The last (most significant) bit is
+ * at position 64.
+ */
+#if BITS_PER_LONG == 32
 static inline int fls64(__u64 x)
 {
        __u32 h = x >> 32;
@@ -10,5 +22,15 @@ static inline int fls64(__u64 x)
                return fls(h) + 32;
        return fls(x);
 }
+#elif BITS_PER_LONG == 64
+static inline int fls64(__u64 x)
+{
+       if (x == 0)
+               return 0;
+       return __fls(x) + 1;
+}
+#else
+#error BITS_PER_LONG not 32 or 64
+#endif
 
 #endif /* _ASM_GENERIC_BITOPS_FLS64_H_ */
index 67dc84cd1343dd6d1674b64f2be832481f0ed072..76b0cc5637f842f211953de68b462244fc62ca6e 100644 (file)
@@ -60,6 +60,10 @@ extern void iowrite32_rep(void __iomem *port, const void *buf, unsigned long cou
 extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
 extern void ioport_unmap(void __iomem *);
 
+#ifndef ARCH_HAS_IOREMAP_WC
+#define ioremap_wc ioremap_nocache
+#endif
+
 /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
 struct pci_dev;
 extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
index 953d3df9dd22670f16fec92440a9dc18f5431593..e2ca800373351d26b1042394275ebe10f6c8d23e 100644 (file)
@@ -407,6 +407,22 @@ fls (int t)
        return ia64_popcnt(x);
 }
 
+/*
+ * Find the last (most significant) bit set.  Undefined for x==0.
+ * Bits are numbered from 0..63 (e.g., __fls(9) == 3).
+ */
+static inline unsigned long
+__fls (unsigned long x)
+{
+       x |= x >> 1;
+       x |= x >> 2;
+       x |= x >> 4;
+       x |= x >> 8;
+       x |= x >> 16;
+       x |= x >> 32;
+       return ia64_popcnt(x) - 1;
+}
+
 #include <asm-generic/bitops/fls64.h>
 
 /*
index de2ed2cbdd845d9404c4036de78cba661f7a6ea5..2fe292c275fe9ab142271e0015b1a87391698f38 100644 (file)
 
 #define ia64_invala_fr(regnum) asm volatile ("invala.e f%0" :: "i"(regnum))
 
+#define ia64_flushrs() asm volatile ("flushrs;;":::"memory")
+
+#define ia64_loadrs() asm volatile ("loadrs;;":::"memory")
+
 extern void ia64_bad_param_for_setreg (void);
 extern void ia64_bad_param_for_getreg (void);
 
@@ -517,6 +521,14 @@ do {                                                                               \
 #define ia64_ptrd(addr, size)                                          \
        asm volatile ("ptr.d %0,%1" :: "r"(addr), "r"(size) : "memory")
 
+#define ia64_ttag(addr)                                                        \
+({                                                                       \
+       __u64 ia64_intri_res;                                              \
+       asm volatile ("ttag %0=%1" : "=r"(ia64_intri_res) : "r" (addr));   \
+       ia64_intri_res;                                                  \
+})
+
+
 /* Values for lfhint in ia64_lfetch and ia64_lfetch_fault */
 
 #define ia64_lfhint_none   0
index 030d29b4b26b249a116cef8d4bf46337346d115d..eb2d3559d089a52c24d7df5cecc1bf0b82cccdab 100644 (file)
@@ -1,6 +1,205 @@
-#ifndef __LINUX_KVM_IA64_H
-#define __LINUX_KVM_IA64_H
+#ifndef __ASM_IA64_KVM_H
+#define __ASM_IA64_KVM_H
 
-/* ia64 does not support KVM */
+/*
+ * asm-ia64/kvm.h: kvm structure definitions  for ia64
+ *
+ * Copyright (C) 2007 Xiantao Zhang <xiantao.zhang@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <asm/types.h>
+#include <asm/fpu.h>
+
+#include <linux/ioctl.h>
+
+/* Architectural interrupt line count. */
+#define KVM_NR_INTERRUPTS 256
+
+#define KVM_IOAPIC_NUM_PINS  24
+
+struct kvm_ioapic_state {
+       __u64 base_address;
+       __u32 ioregsel;
+       __u32 id;
+       __u32 irr;
+       __u32 pad;
+       union {
+               __u64 bits;
+               struct {
+                       __u8 vector;
+                       __u8 delivery_mode:3;
+                       __u8 dest_mode:1;
+                       __u8 delivery_status:1;
+                       __u8 polarity:1;
+                       __u8 remote_irr:1;
+                       __u8 trig_mode:1;
+                       __u8 mask:1;
+                       __u8 reserve:7;
+                       __u8 reserved[4];
+                       __u8 dest_id;
+               } fields;
+       } redirtbl[KVM_IOAPIC_NUM_PINS];
+};
+
+#define KVM_IRQCHIP_PIC_MASTER   0
+#define KVM_IRQCHIP_PIC_SLAVE    1
+#define KVM_IRQCHIP_IOAPIC       2
+
+#define KVM_CONTEXT_SIZE       8*1024
+
+union context {
+       /* 8K size */
+       char    dummy[KVM_CONTEXT_SIZE];
+       struct {
+               unsigned long       psr;
+               unsigned long       pr;
+               unsigned long       caller_unat;
+               unsigned long       pad;
+               unsigned long       gr[32];
+               unsigned long       ar[128];
+               unsigned long       br[8];
+               unsigned long       cr[128];
+               unsigned long       rr[8];
+               unsigned long       ibr[8];
+               unsigned long       dbr[8];
+               unsigned long       pkr[8];
+               struct ia64_fpreg   fr[128];
+       };
+};
+
+struct thash_data {
+       union {
+               struct {
+                       unsigned long p    :  1; /* 0 */
+                       unsigned long rv1  :  1; /* 1 */
+                       unsigned long ma   :  3; /* 2-4 */
+                       unsigned long a    :  1; /* 5 */
+                       unsigned long d    :  1; /* 6 */
+                       unsigned long pl   :  2; /* 7-8 */
+                       unsigned long ar   :  3; /* 9-11 */
+                       unsigned long ppn  : 38; /* 12-49 */
+                       unsigned long rv2  :  2; /* 50-51 */
+                       unsigned long ed   :  1; /* 52 */
+                       unsigned long ig1  : 11; /* 53-63 */
+               };
+               struct {
+                       unsigned long __rv1 : 53;     /* 0-52 */
+                       unsigned long contiguous : 1; /*53 */
+                       unsigned long tc : 1;         /* 54 TR or TC */
+                       unsigned long cl : 1;
+                       /* 55 I side or D side cache line */
+                       unsigned long len  :  4;      /* 56-59 */
+                       unsigned long io  : 1;  /* 60 entry is for io or not */
+                       unsigned long nomap : 1;
+                       /* 61 entry cann't be inserted into machine TLB.*/
+                       unsigned long checked : 1;
+                       /* 62 for VTLB/VHPT sanity check */
+                       unsigned long invalid : 1;
+                       /* 63 invalid entry */
+               };
+               unsigned long page_flags;
+       };                  /* same for VHPT and TLB */
+
+       union {
+               struct {
+                       unsigned long rv3  :  2;
+                       unsigned long ps   :  6;
+                       unsigned long key  : 24;
+                       unsigned long rv4  : 32;
+               };
+               unsigned long itir;
+       };
+       union {
+               struct {
+                       unsigned long ig2  :  12;
+                       unsigned long vpn  :  49;
+                       unsigned long vrn  :   3;
+               };
+               unsigned long ifa;
+               unsigned long vadr;
+               struct {
+                       unsigned long tag  :  63;
+                       unsigned long ti   :  1;
+               };
+               unsigned long etag;
+       };
+       union {
+               struct thash_data *next;
+               unsigned long rid;
+               unsigned long gpaddr;
+       };
+};
+
+#define        NITRS   8
+#define NDTRS  8
+
+struct saved_vpd {
+       unsigned long  vhpi;
+       unsigned long  vgr[16];
+       unsigned long  vbgr[16];
+       unsigned long  vnat;
+       unsigned long  vbnat;
+       unsigned long  vcpuid[5];
+       unsigned long  vpsr;
+       unsigned long  vpr;
+       unsigned long  vcr[128];
+};
+
+struct kvm_regs {
+       char *saved_guest;
+       char *saved_stack;
+       struct saved_vpd vpd;
+       /*Arch-regs*/
+       int mp_state;
+       unsigned long vmm_rr;
+       /* TR and TC.  */
+       struct thash_data itrs[NITRS];
+       struct thash_data dtrs[NDTRS];
+       /* Bit is set if there is a tr/tc for the region.  */
+       unsigned char itr_regions;
+       unsigned char dtr_regions;
+       unsigned char tc_regions;
+
+       char irq_check;
+       unsigned long saved_itc;
+       unsigned long itc_check;
+       unsigned long timer_check;
+       unsigned long timer_pending;
+       unsigned long last_itc;
+
+       unsigned long vrr[8];
+       unsigned long ibr[8];
+       unsigned long dbr[8];
+       unsigned long insvc[4];         /* Interrupt in service.  */
+       unsigned long xtp;
+
+       unsigned long metaphysical_rr0; /* from kvm_arch (so is pinned) */
+       unsigned long metaphysical_rr4; /* from kvm_arch (so is pinned) */
+       unsigned long metaphysical_saved_rr0; /* from kvm_arch          */
+       unsigned long metaphysical_saved_rr4; /* from kvm_arch          */
+       unsigned long fp_psr;       /*used for lazy float register */
+       unsigned long saved_gp;
+       /*for phycial  emulation */
+};
+
+struct kvm_sregs {
+};
+
+struct kvm_fpu {
+};
 
 #endif
diff --git a/include/asm-ia64/kvm_host.h b/include/asm-ia64/kvm_host.h
new file mode 100644 (file)
index 0000000..c082c20
--- /dev/null
@@ -0,0 +1,524 @@
+/*
+ * kvm_host.h: used for kvm module, and hold ia64-specific sections.
+ *
+ * Copyright (C) 2007, Intel Corporation.
+ *
+ * Xiantao Zhang <xiantao.zhang@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#ifndef __ASM_KVM_HOST_H
+#define __ASM_KVM_HOST_H
+
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/kvm.h>
+#include <linux/kvm_para.h>
+#include <linux/kvm_types.h>
+
+#include <asm/pal.h>
+#include <asm/sal.h>
+
+#define KVM_MAX_VCPUS 4
+#define KVM_MEMORY_SLOTS 32
+/* memory slots that does not exposed to userspace */
+#define KVM_PRIVATE_MEM_SLOTS 4
+
+
+/* define exit reasons from vmm to kvm*/
+#define EXIT_REASON_VM_PANIC           0
+#define EXIT_REASON_MMIO_INSTRUCTION   1
+#define EXIT_REASON_PAL_CALL           2
+#define EXIT_REASON_SAL_CALL           3
+#define EXIT_REASON_SWITCH_RR6         4
+#define EXIT_REASON_VM_DESTROY         5
+#define EXIT_REASON_EXTERNAL_INTERRUPT 6
+#define EXIT_REASON_IPI                        7
+#define EXIT_REASON_PTC_G              8
+
+/*Define vmm address space and vm data space.*/
+#define KVM_VMM_SIZE (16UL<<20)
+#define KVM_VMM_SHIFT 24
+#define KVM_VMM_BASE 0xD000000000000000UL
+#define VMM_SIZE (8UL<<20)
+
+/*
+ * Define vm_buffer, used by PAL Services, base address.
+ * Note: vmbuffer is in the VMM-BLOCK, the size must be < 8M
+ */
+#define KVM_VM_BUFFER_BASE (KVM_VMM_BASE + VMM_SIZE)
+#define KVM_VM_BUFFER_SIZE (8UL<<20)
+
+/*Define Virtual machine data layout.*/
+#define KVM_VM_DATA_SHIFT  24
+#define KVM_VM_DATA_SIZE (1UL << KVM_VM_DATA_SHIFT)
+#define KVM_VM_DATA_BASE (KVM_VMM_BASE + KVM_VMM_SIZE)
+
+
+#define KVM_P2M_BASE    KVM_VM_DATA_BASE
+#define KVM_P2M_OFS     0
+#define KVM_P2M_SIZE    (8UL << 20)
+
+#define KVM_VHPT_BASE   (KVM_P2M_BASE + KVM_P2M_SIZE)
+#define KVM_VHPT_OFS    KVM_P2M_SIZE
+#define KVM_VHPT_BLOCK_SIZE   (2UL << 20)
+#define VHPT_SHIFT      18
+#define VHPT_SIZE       (1UL << VHPT_SHIFT)
+#define VHPT_NUM_ENTRIES (1<<(VHPT_SHIFT-5))
+
+#define KVM_VTLB_BASE   (KVM_VHPT_BASE+KVM_VHPT_BLOCK_SIZE)
+#define KVM_VTLB_OFS    (KVM_VHPT_OFS+KVM_VHPT_BLOCK_SIZE)
+#define KVM_VTLB_BLOCK_SIZE   (1UL<<20)
+#define VTLB_SHIFT      17
+#define VTLB_SIZE       (1UL<<VTLB_SHIFT)
+#define VTLB_NUM_ENTRIES (1<<(VTLB_SHIFT-5))
+
+#define KVM_VPD_BASE   (KVM_VTLB_BASE+KVM_VTLB_BLOCK_SIZE)
+#define KVM_VPD_OFS    (KVM_VTLB_OFS+KVM_VTLB_BLOCK_SIZE)
+#define KVM_VPD_BLOCK_SIZE   (2UL<<20)
+#define VPD_SHIFT       16
+#define VPD_SIZE        (1UL<<VPD_SHIFT)
+
+#define KVM_VCPU_BASE   (KVM_VPD_BASE+KVM_VPD_BLOCK_SIZE)
+#define KVM_VCPU_OFS    (KVM_VPD_OFS+KVM_VPD_BLOCK_SIZE)
+#define KVM_VCPU_BLOCK_SIZE   (2UL<<20)
+#define VCPU_SHIFT 18
+#define VCPU_SIZE (1UL<<VCPU_SHIFT)
+#define MAX_VCPU_NUM KVM_VCPU_BLOCK_SIZE/VCPU_SIZE
+
+#define KVM_VM_BASE     (KVM_VCPU_BASE+KVM_VCPU_BLOCK_SIZE)
+#define KVM_VM_OFS      (KVM_VCPU_OFS+KVM_VCPU_BLOCK_SIZE)
+#define KVM_VM_BLOCK_SIZE     (1UL<<19)
+
+#define KVM_MEM_DIRTY_LOG_BASE (KVM_VM_BASE+KVM_VM_BLOCK_SIZE)
+#define KVM_MEM_DIRTY_LOG_OFS  (KVM_VM_OFS+KVM_VM_BLOCK_SIZE)
+#define KVM_MEM_DIRTY_LOG_SIZE (1UL<<19)
+
+/* Get vpd, vhpt, tlb, vcpu, base*/
+#define VPD_ADDR(n) (KVM_VPD_BASE+n*VPD_SIZE)
+#define VHPT_ADDR(n) (KVM_VHPT_BASE+n*VHPT_SIZE)
+#define VTLB_ADDR(n) (KVM_VTLB_BASE+n*VTLB_SIZE)
+#define VCPU_ADDR(n) (KVM_VCPU_BASE+n*VCPU_SIZE)
+
+/*IO section definitions*/
+#define IOREQ_READ      1
+#define IOREQ_WRITE     0
+
+#define STATE_IOREQ_NONE        0
+#define STATE_IOREQ_READY       1
+#define STATE_IOREQ_INPROCESS   2
+#define STATE_IORESP_READY      3
+
+/*Guest Physical address layout.*/
+#define GPFN_MEM        (0UL << 60) /* Guest pfn is normal mem */
+#define GPFN_FRAME_BUFFER   (1UL << 60) /* VGA framebuffer */
+#define GPFN_LOW_MMIO       (2UL << 60) /* Low MMIO range */
+#define GPFN_PIB        (3UL << 60) /* PIB base */
+#define GPFN_IOSAPIC        (4UL << 60) /* IOSAPIC base */
+#define GPFN_LEGACY_IO      (5UL << 60) /* Legacy I/O base */
+#define GPFN_GFW        (6UL << 60) /* Guest Firmware */
+#define GPFN_HIGH_MMIO      (7UL << 60) /* High MMIO range */
+
+#define GPFN_IO_MASK        (7UL << 60) /* Guest pfn is I/O type */
+#define GPFN_INV_MASK       (1UL << 63) /* Guest pfn is invalid */
+#define INVALID_MFN       (~0UL)
+#define MEM_G   (1UL << 30)
+#define MEM_M   (1UL << 20)
+#define MMIO_START       (3 * MEM_G)
+#define MMIO_SIZE        (512 * MEM_M)
+#define VGA_IO_START     0xA0000UL
+#define VGA_IO_SIZE      0x20000
+#define LEGACY_IO_START  (MMIO_START + MMIO_SIZE)
+#define LEGACY_IO_SIZE   (64 * MEM_M)
+#define IO_SAPIC_START   0xfec00000UL
+#define IO_SAPIC_SIZE    0x100000
+#define PIB_START 0xfee00000UL
+#define PIB_SIZE 0x200000
+#define GFW_START        (4 * MEM_G - 16 * MEM_M)
+#define GFW_SIZE         (16 * MEM_M)
+
+/*Deliver mode, defined for ioapic.c*/
+#define dest_Fixed IOSAPIC_FIXED
+#define dest_LowestPrio IOSAPIC_LOWEST_PRIORITY
+
+#define NMI_VECTOR                     2
+#define ExtINT_VECTOR                  0
+#define NULL_VECTOR                    (-1)
+#define IA64_SPURIOUS_INT_VECTOR       0x0f
+
+#define VCPU_LID(v) (((u64)(v)->vcpu_id) << 24)
+
+/*
+ *Delivery mode
+ */
+#define SAPIC_DELIV_SHIFT      8
+#define SAPIC_FIXED            0x0
+#define SAPIC_LOWEST_PRIORITY  0x1
+#define SAPIC_PMI              0x2
+#define SAPIC_NMI              0x4
+#define SAPIC_INIT             0x5
+#define SAPIC_EXTINT           0x7
+
+/*
+ * vcpu->requests bit members for arch
+ */
+#define KVM_REQ_PTC_G          32
+#define KVM_REQ_RESUME         33
+
+#define KVM_PAGES_PER_HPAGE    1
+
+struct kvm;
+struct kvm_vcpu;
+struct kvm_guest_debug{
+};
+
+struct kvm_mmio_req {
+       uint64_t addr;          /*  physical address            */
+       uint64_t size;          /*  size in bytes               */
+       uint64_t data;          /*  data (or paddr of data)     */
+       uint8_t state:4;
+       uint8_t dir:1;          /*  1=read, 0=write             */
+};
+
+/*Pal data struct */
+struct kvm_pal_call{
+       /*In area*/
+       uint64_t gr28;
+       uint64_t gr29;
+       uint64_t gr30;
+       uint64_t gr31;
+       /*Out area*/
+       struct ia64_pal_retval ret;
+};
+
+/* Sal data structure */
+struct kvm_sal_call{
+       /*In area*/
+       uint64_t in0;
+       uint64_t in1;
+       uint64_t in2;
+       uint64_t in3;
+       uint64_t in4;
+       uint64_t in5;
+       uint64_t in6;
+       uint64_t in7;
+       struct sal_ret_values ret;
+};
+
+/*Guest change rr6*/
+struct kvm_switch_rr6 {
+       uint64_t old_rr;
+       uint64_t new_rr;
+};
+
+union ia64_ipi_a{
+       unsigned long val;
+       struct {
+               unsigned long rv  : 3;
+               unsigned long ir  : 1;
+               unsigned long eid : 8;
+               unsigned long id  : 8;
+               unsigned long ib_base : 44;
+       };
+};
+
+union ia64_ipi_d {
+       unsigned long val;
+       struct {
+               unsigned long vector : 8;
+               unsigned long dm  : 3;
+               unsigned long ig  : 53;
+       };
+};
+
+/*ipi check exit data*/
+struct kvm_ipi_data{
+       union ia64_ipi_a addr;
+       union ia64_ipi_d data;
+};
+
+/*global purge data*/
+struct kvm_ptc_g {
+       unsigned long vaddr;
+       unsigned long rr;
+       unsigned long ps;
+       struct kvm_vcpu *vcpu;
+};
+
+/*Exit control data */
+struct exit_ctl_data{
+       uint32_t exit_reason;
+       uint32_t vm_status;
+       union {
+               struct kvm_mmio_req     ioreq;
+               struct kvm_pal_call     pal_data;
+               struct kvm_sal_call     sal_data;
+               struct kvm_switch_rr6   rr_data;
+               struct kvm_ipi_data     ipi_data;
+               struct kvm_ptc_g        ptc_g_data;
+       } u;
+};
+
+union pte_flags {
+       unsigned long val;
+       struct {
+               unsigned long p    :  1; /*0      */
+               unsigned long      :  1; /* 1     */
+               unsigned long ma   :  3; /* 2-4   */
+               unsigned long a    :  1; /* 5     */
+               unsigned long d    :  1; /* 6     */
+               unsigned long pl   :  2; /* 7-8   */
+               unsigned long ar   :  3; /* 9-11  */
+               unsigned long ppn  : 38; /* 12-49 */
+               unsigned long      :  2; /* 50-51 */
+               unsigned long ed   :  1; /* 52    */
+       };
+};
+
+union ia64_pta {
+       unsigned long val;
+       struct {
+               unsigned long ve : 1;
+               unsigned long reserved0 : 1;
+               unsigned long size : 6;
+               unsigned long vf : 1;
+               unsigned long reserved1 : 6;
+               unsigned long base : 49;
+       };
+};
+
+struct thash_cb {
+       /* THASH base information */
+       struct thash_data       *hash; /* hash table pointer */
+       union ia64_pta          pta;
+       int           num;
+};
+
+struct kvm_vcpu_stat {
+};
+
+struct kvm_vcpu_arch {
+       int launched;
+       int last_exit;
+       int last_run_cpu;
+       int vmm_tr_slot;
+       int vm_tr_slot;
+
+#define KVM_MP_STATE_RUNNABLE          0
+#define KVM_MP_STATE_UNINITIALIZED     1
+#define KVM_MP_STATE_INIT_RECEIVED     2
+#define KVM_MP_STATE_HALTED            3
+       int mp_state;
+
+#define MAX_PTC_G_NUM                  3
+       int ptc_g_count;
+       struct kvm_ptc_g ptc_g_data[MAX_PTC_G_NUM];
+
+       /*halt timer to wake up sleepy vcpus*/
+       struct hrtimer hlt_timer;
+       long ht_active;
+
+       struct kvm_lapic *apic;    /* kernel irqchip context */
+       struct vpd *vpd;
+
+       /* Exit data for vmm_transition*/
+       struct exit_ctl_data exit_data;
+
+       cpumask_t cache_coherent_map;
+
+       unsigned long vmm_rr;
+       unsigned long host_rr6;
+       unsigned long psbits[8];
+       unsigned long cr_iipa;
+       unsigned long cr_isr;
+       unsigned long vsa_base;
+       unsigned long dirty_log_lock_pa;
+       unsigned long __gp;
+       /* TR and TC.  */
+       struct thash_data itrs[NITRS];
+       struct thash_data dtrs[NDTRS];
+       /* Bit is set if there is a tr/tc for the region.  */
+       unsigned char itr_regions;
+       unsigned char dtr_regions;
+       unsigned char tc_regions;
+       /* purge all */
+       unsigned long ptce_base;
+       unsigned long ptce_count[2];
+       unsigned long ptce_stride[2];
+       /* itc/itm */
+       unsigned long last_itc;
+       long itc_offset;
+       unsigned long itc_check;
+       unsigned long timer_check;
+       unsigned long timer_pending;
+
+       unsigned long vrr[8];
+       unsigned long ibr[8];
+       unsigned long dbr[8];
+       unsigned long insvc[4];         /* Interrupt in service.  */
+       unsigned long xtp;
+
+       unsigned long metaphysical_rr0; /* from kvm_arch (so is pinned) */
+       unsigned long metaphysical_rr4; /* from kvm_arch (so is pinned) */
+       unsigned long metaphysical_saved_rr0; /* from kvm_arch          */
+       unsigned long metaphysical_saved_rr4; /* from kvm_arch          */
+       unsigned long fp_psr;       /*used for lazy float register */
+       unsigned long saved_gp;
+       /*for phycial  emulation */
+       int mode_flags;
+       struct thash_cb vtlb;
+       struct thash_cb vhpt;
+       char irq_check;
+       char irq_new_pending;
+
+       unsigned long opcode;
+       unsigned long cause;
+       union context host;
+       union context guest;
+};
+
+struct kvm_vm_stat {
+       u64 remote_tlb_flush;
+};
+
+struct kvm_sal_data {
+       unsigned long boot_ip;
+       unsigned long boot_gp;
+};
+
+struct kvm_arch {
+       unsigned long   vm_base;
+       unsigned long   metaphysical_rr0;
+       unsigned long   metaphysical_rr4;
+       unsigned long   vmm_init_rr;
+       unsigned long   vhpt_base;
+       unsigned long   vtlb_base;
+       unsigned long   vpd_base;
+       spinlock_t dirty_log_lock;
+       struct kvm_ioapic *vioapic;
+       struct kvm_vm_stat stat;
+       struct kvm_sal_data rdv_sal_data;
+};
+
+union cpuid3_t {
+       u64 value;
+       struct {
+               u64 number : 8;
+               u64 revision : 8;
+               u64 model : 8;
+               u64 family : 8;
+               u64 archrev : 8;
+               u64 rv : 24;
+       };
+};
+
+struct kvm_pt_regs {
+       /* The following registers are saved by SAVE_MIN: */
+       unsigned long b6;  /* scratch */
+       unsigned long b7;  /* scratch */
+
+       unsigned long ar_csd; /* used by cmp8xchg16 (scratch) */
+       unsigned long ar_ssd; /* reserved for future use (scratch) */
+
+       unsigned long r8;  /* scratch (return value register 0) */
+       unsigned long r9;  /* scratch (return value register 1) */
+       unsigned long r10; /* scratch (return value register 2) */
+       unsigned long r11; /* scratch (return value register 3) */
+
+       unsigned long cr_ipsr; /* interrupted task's psr */
+       unsigned long cr_iip;  /* interrupted task's instruction pointer */
+       unsigned long cr_ifs;  /* interrupted task's function state */
+
+       unsigned long ar_unat; /* interrupted task's NaT register (preserved) */
+       unsigned long ar_pfs;  /* prev function state  */
+       unsigned long ar_rsc;  /* RSE configuration */
+       /* The following two are valid only if cr_ipsr.cpl > 0: */
+       unsigned long ar_rnat;  /* RSE NaT */
+       unsigned long ar_bspstore; /* RSE bspstore */
+
+       unsigned long pr;  /* 64 predicate registers (1 bit each) */
+       unsigned long b0;  /* return pointer (bp) */
+       unsigned long loadrs;  /* size of dirty partition << 16 */
+
+       unsigned long r1;  /* the gp pointer */
+       unsigned long r12; /* interrupted task's memory stack pointer */
+       unsigned long r13; /* thread pointer */
+
+       unsigned long ar_fpsr;  /* floating point status (preserved) */
+       unsigned long r15;  /* scratch */
+
+       /* The remaining registers are NOT saved for system calls.  */
+       unsigned long r14;  /* scratch */
+       unsigned long r2;  /* scratch */
+       unsigned long r3;  /* scratch */
+       unsigned long r16;  /* scratch */
+       unsigned long r17;  /* scratch */
+       unsigned long r18;  /* scratch */
+       unsigned long r19;  /* scratch */
+       unsigned long r20;  /* scratch */
+       unsigned long r21;  /* scratch */
+       unsigned long r22;  /* scratch */
+       unsigned long r23;  /* scratch */
+       unsigned long r24;  /* scratch */
+       unsigned long r25;  /* scratch */
+       unsigned long r26;  /* scratch */
+       unsigned long r27;  /* scratch */
+       unsigned long r28;  /* scratch */
+       unsigned long r29;  /* scratch */
+       unsigned long r30;  /* scratch */
+       unsigned long r31;  /* scratch */
+       unsigned long ar_ccv;  /* compare/exchange value (scratch) */
+
+       /*
+        * Floating point registers that the kernel considers scratch:
+        */
+       struct ia64_fpreg f6;  /* scratch */
+       struct ia64_fpreg f7;  /* scratch */
+       struct ia64_fpreg f8;  /* scratch */
+       struct ia64_fpreg f9;  /* scratch */
+       struct ia64_fpreg f10;  /* scratch */
+       struct ia64_fpreg f11;  /* scratch */
+
+       unsigned long r4;  /* preserved */
+       unsigned long r5;  /* preserved */
+       unsigned long r6;  /* preserved */
+       unsigned long r7;  /* preserved */
+       unsigned long eml_unat;    /* used for emulating instruction */
+       unsigned long pad0;     /* alignment pad */
+};
+
+static inline struct kvm_pt_regs *vcpu_regs(struct kvm_vcpu *v)
+{
+       return (struct kvm_pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1;
+}
+
+typedef int kvm_vmm_entry(void);
+typedef void kvm_tramp_entry(union context *host, union context *guest);
+
+struct kvm_vmm_info{
+       struct module   *module;
+       kvm_vmm_entry   *vmm_entry;
+       kvm_tramp_entry *tramp_entry;
+       unsigned long   vmm_ivt;
+};
+
+int kvm_highest_pending_irq(struct kvm_vcpu *vcpu);
+int kvm_emulate_halt(struct kvm_vcpu *vcpu);
+int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run);
+void kvm_sal_emul(struct kvm_vcpu *vcpu);
+
+#endif
diff --git a/include/asm-ia64/kvm_para.h b/include/asm-ia64/kvm_para.h
new file mode 100644 (file)
index 0000000..9f9796b
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __IA64_KVM_PARA_H
+#define __IA64_KVM_PARA_H
+
+/*
+ * asm-ia64/kvm_para.h
+ *
+ * Copyright (C) 2007 Xiantao Zhang <xiantao.zhang@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+static inline unsigned int kvm_arch_para_features(void)
+{
+       return 0;
+}
+
+#endif
index 741f7ecb986a90fb28ed9c0a8020da5b67654f46..6aff126fc07ea31802ec249613e9237c16472875 100644 (file)
@@ -119,6 +119,69 @@ struct ia64_psr {
        __u64 reserved4 : 19;
 };
 
+union ia64_isr {
+       __u64  val;
+       struct {
+               __u64 code : 16;
+               __u64 vector : 8;
+               __u64 reserved1 : 8;
+               __u64 x : 1;
+               __u64 w : 1;
+               __u64 r : 1;
+               __u64 na : 1;
+               __u64 sp : 1;
+               __u64 rs : 1;
+               __u64 ir : 1;
+               __u64 ni : 1;
+               __u64 so : 1;
+               __u64 ei : 2;
+               __u64 ed : 1;
+               __u64 reserved2 : 20;
+       };
+};
+
+union ia64_lid {
+       __u64 val;
+       struct {
+               __u64  rv  : 16;
+               __u64  eid : 8;
+               __u64  id  : 8;
+               __u64  ig  : 32;
+       };
+};
+
+union ia64_tpr {
+       __u64 val;
+       struct {
+               __u64 ig0 : 4;
+               __u64 mic : 4;
+               __u64 rsv : 8;
+               __u64 mmi : 1;
+               __u64 ig1 : 47;
+       };
+};
+
+union ia64_itir {
+       __u64 val;
+       struct {
+               __u64 rv3  :  2; /* 0-1 */
+               __u64 ps   :  6; /* 2-7 */
+               __u64 key  : 24; /* 8-31 */
+               __u64 rv4  : 32; /* 32-63 */
+       };
+};
+
+union  ia64_rr {
+       __u64 val;
+       struct {
+               __u64  ve       :  1;  /* enable hw walker */
+               __u64  reserved0:  1;  /* reserved */
+               __u64  ps       :  6;  /* log page size */
+               __u64  rid      : 24;  /* region id */
+               __u64  reserved1: 32;  /* reserved */
+       };
+};
+
 /*
  * CPU type, hardware bug flags, and per-CPU state.  Frequently used
  * state comes earlier:
index ec75ce4cdb8c3e90307e51350c2d7dc4b950a4d5..c2bd126c3b4eda2613c73e26335bb0f8694abd9d 100644 (file)
@@ -591,6 +591,11 @@ static inline int __ilog2(unsigned long x)
        return 63 - lz;
 }
 
+static inline unsigned long __fls(unsigned long x)
+{
+       return __ilog2(x);
+}
+
 #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
 
 /*
index 89655c0cdcd6bb4e4760d344fb1c98872ce881c9..b493a5e46c639598f9066f0591a6d983b0073c57 100644 (file)
@@ -70,7 +70,6 @@ typedef struct
         ide_hwif_t              *hwif;
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
         ide_drive_t             *drive;
-        u8                      white_list, black_list;
         struct dbdma_cmd        *dma_table_cpu;
         dma_addr_t              dma_table_dma;
 #endif
@@ -81,47 +80,6 @@ typedef struct
 #endif
 } _auide_hwif;
 
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-/* HD white list */
-static const struct drive_list_entry dma_white_list [] = {
-/*
- * Hitachi
- */
-        { "HITACHI_DK14FA-20"    ,       NULL            },
-        { "HTS726060M9AT00"      ,       NULL            },
-/*
- * Maxtor
- */
-        { "Maxtor 6E040L0"      ,       NULL            },
-        { "Maxtor 6Y080P0"      ,       NULL            },
-        { "Maxtor 6Y160P0"      ,       NULL            },
-/*
- * Seagate
- */
-        { "ST3120026A"          ,       NULL            },
-        { "ST320014A"           ,       NULL            },
-        { "ST94011A"            ,       NULL            },
-        { "ST340016A"           ,       NULL            },
-/*
- * Western Digital
- */
-        { "WDC WD400UE-00HCT0"  ,       NULL            },
-        { "WDC WD400JB-00JJC0"  ,       NULL            },
-        { NULL                  ,       NULL            }
-};
-
-/* HD black list */
-static const struct drive_list_entry dma_black_list [] = {
-/*
- * Western Digital
- */
-        { "WDC WD100EB-00CGH0"  ,       NULL            },
-        { "WDC WD200BB-00AUA1"  ,       NULL            },
-        { "WDC AC24300L"        ,       NULL            },
-        { NULL                  ,       NULL            }
-};
-#endif
-
 /*******************************************************************************
 * PIO Mode timing calculation :                                                *
 *                                                                              *
index f8eebcbad01f81d57e0a222d4573d9044f114e96..7a6ea10bd231a051217ddd00b0f9318a604b1878 100644 (file)
@@ -210,6 +210,7 @@ static __inline__ int fls(int x)
        return ret;
 }
 
+#include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
 #include <asm-generic/bitops/lock.h>
index a99a749294753b3a77688a203998111ef01eff13..897eade3afbeb0109159de4e1eb855f42ddab4e0 100644 (file)
@@ -313,6 +313,11 @@ static __inline__ int fls(unsigned int x)
        return 32 - lz;
 }
 
+static __inline__ unsigned long __fls(unsigned long x)
+{
+       return __ilog2(x);
+}
+
 /*
  * 64-bit can do this using one cntlzd (count leading zeroes doubleword)
  * instruction; for 32-bit we use the generic version, which does two
diff --git a/include/asm-powerpc/fixmap.h b/include/asm-powerpc/fixmap.h
new file mode 100644 (file)
index 0000000..8428b38
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * fixmap.h: compile-time virtual memory allocation
+ *
+ * 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) 1998 Ingo Molnar
+ *
+ * Copyright 2008 Freescale Semiconductor Inc.
+ *   Port to powerpc added by Kumar Gala
+ */
+
+#ifndef _ASM_FIXMAP_H
+#define _ASM_FIXMAP_H
+
+extern unsigned long FIXADDR_TOP;
+
+#ifndef __ASSEMBLY__
+#include <linux/kernel.h>
+#include <asm/page.h>
+#ifdef CONFIG_HIGHMEM
+#include <linux/threads.h>
+#include <asm/kmap_types.h>
+#endif
+
+/*
+ * Here we define all the compile-time 'special' virtual
+ * addresses. The point is to have a constant address at
+ * compile time, but to set the physical address only
+ * in the boot process. We allocate these special addresses
+ * from the end of virtual memory (0xfffff000) backwards.
+ * Also this lets us do fail-safe vmalloc(), we
+ * can guarantee that these special addresses and
+ * vmalloc()-ed addresses never overlap.
+ *
+ * these 'compile-time allocated' memory buffers are
+ * fixed-size 4k pages. (or larger if used with an increment
+ * highger than 1) use fixmap_set(idx,phys) to associate
+ * physical memory with fixmap indices.
+ *
+ * TLB entries of such buffers will not be flushed across
+ * task switches.
+ */
+enum fixed_addresses {
+       FIX_HOLE,
+#ifdef CONFIG_HIGHMEM
+       FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
+       FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+#endif
+       /* FIX_PCIE_MCFG, */
+       __end_of_fixed_addresses
+};
+
+extern void __set_fixmap (enum fixed_addresses idx,
+                                       phys_addr_t phys, pgprot_t flags);
+
+#define set_fixmap(idx, phys) \
+               __set_fixmap(idx, phys, PAGE_KERNEL)
+/*
+ * Some hardware wants to get fixmapped without caching.
+ */
+#define set_fixmap_nocache(idx, phys) \
+               __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
+
+#define clear_fixmap(idx) \
+               __set_fixmap(idx, 0, __pgprot(0))
+
+#define __FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_START          (FIXADDR_TOP - __FIXADDR_SIZE)
+
+#define __fix_to_virt(x)       (FIXADDR_TOP - ((x) << PAGE_SHIFT))
+#define __virt_to_fix(x)       ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
+
+extern void __this_fixmap_does_not_exist(void);
+
+/*
+ * 'index to address' translation. If anyone tries to use the idx
+ * directly without tranlation, we catch the bug with a NULL-deference
+ * kernel oops. Illegal ranges of incoming indices are caught too.
+ */
+static __always_inline unsigned long fix_to_virt(const unsigned int idx)
+{
+       /*
+        * this branch gets completely eliminated after inlining,
+        * except when someone tries to use fixaddr indices in an
+        * illegal way. (such as mixing up address types or using
+        * out-of-range indices).
+        *
+        * If it doesn't get removed, the linker will complain
+        * loudly with a reasonably clear error message..
+        */
+       if (idx >= __end_of_fixed_addresses)
+               __this_fixmap_does_not_exist();
+
+        return __fix_to_virt(idx);
+}
+
+static inline unsigned long virt_to_fix(const unsigned long vaddr)
+{
+       BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
+       return __virt_to_fix(vaddr);
+}
+
+#endif /* !__ASSEMBLY__ */
+#endif
index f7b21ee302b4f1b7fcd1e923fa14c3da0e708f6e..5d99b6489d569d44e54a3781734e797d72100b5c 100644 (file)
@@ -27,9 +27,7 @@
 #include <asm/kmap_types.h>
 #include <asm/tlbflush.h>
 #include <asm/page.h>
-
-/* undef for production */
-#define HIGHMEM_DEBUG 1
+#include <asm/fixmap.h>
 
 extern pte_t *kmap_pte;
 extern pgprot_t kmap_prot;
@@ -40,14 +38,12 @@ extern pte_t *pkmap_page_table;
  * easily, subsequent pte tables have to be allocated in one physical
  * chunk of RAM.
  */
-#define PKMAP_BASE     CONFIG_HIGHMEM_START
 #define LAST_PKMAP     (1 << PTE_SHIFT)
 #define LAST_PKMAP_MASK (LAST_PKMAP-1)
+#define PKMAP_BASE     ((FIXADDR_START - PAGE_SIZE*(LAST_PKMAP + 1)) & PMD_MASK)
 #define PKMAP_NR(virt)  ((virt-PKMAP_BASE) >> PAGE_SHIFT)
 #define PKMAP_ADDR(nr)  (PKMAP_BASE + ((nr) << PAGE_SHIFT))
 
-#define KMAP_FIX_BEGIN (PKMAP_BASE + 0x00400000UL)
-
 extern void *kmap_high(struct page *page);
 extern void kunmap_high(struct page *page);
 
@@ -73,7 +69,7 @@ static inline void kunmap(struct page *page)
  * be used in IRQ contexts, so in some (very limited) cases we need
  * it.
  */
-static inline void *kmap_atomic(struct page *page, enum km_type type)
+static inline void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
 {
        unsigned int idx;
        unsigned long vaddr;
@@ -84,34 +80,39 @@ static inline void *kmap_atomic(struct page *page, enum km_type type)
                return page_address(page);
 
        idx = type + KM_TYPE_NR*smp_processor_id();
-       vaddr = KMAP_FIX_BEGIN + idx * PAGE_SIZE;
-#ifdef HIGHMEM_DEBUG
-       BUG_ON(!pte_none(*(kmap_pte+idx)));
+       vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+#ifdef CONFIG_DEBUG_HIGHMEM
+       BUG_ON(!pte_none(*(kmap_pte-idx)));
 #endif
-       set_pte_at(&init_mm, vaddr, kmap_pte+idx, mk_pte(page, kmap_prot));
+       set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
        flush_tlb_page(NULL, vaddr);
 
        return (void*) vaddr;
 }
 
+static inline void *kmap_atomic(struct page *page, enum km_type type)
+{
+       return kmap_atomic_prot(page, type, kmap_prot);
+}
+
 static inline void kunmap_atomic(void *kvaddr, enum km_type type)
 {
-#ifdef HIGHMEM_DEBUG
+#ifdef CONFIG_DEBUG_HIGHMEM
        unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-       unsigned int idx = type + KM_TYPE_NR*smp_processor_id();
+       enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
 
-       if (vaddr < KMAP_FIX_BEGIN) { // FIXME
+       if (vaddr < __fix_to_virt(FIX_KMAP_END)) {
                pagefault_enable();
                return;
        }
 
-       BUG_ON(vaddr != KMAP_FIX_BEGIN + idx * PAGE_SIZE);
+       BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
 
        /*
         * force other mappings to Oops if they'll try to access
         * this pte without first remap it
         */
-       pte_clear(&init_mm, vaddr, kmap_pte+idx);
+       pte_clear(&init_mm, vaddr, kmap_pte-idx);
        flush_tlb_page(NULL, vaddr);
 #endif
        pagefault_enable();
@@ -120,12 +121,14 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type)
 static inline struct page *kmap_atomic_to_page(void *ptr)
 {
        unsigned long idx, vaddr = (unsigned long) ptr;
+       pte_t *pte;
 
-       if (vaddr < KMAP_FIX_BEGIN)
+       if (vaddr < FIXADDR_START)
                return virt_to_page(ptr);
 
-       idx = (vaddr - KMAP_FIX_BEGIN) >> PAGE_SHIFT;
-       return pte_page(kmap_pte[idx]);
+       idx = virt_to_fix(vaddr);
+       pte = kmap_pte - (idx - FIX_KMAP_BEGIN);
+       return pte_page(*pte);
 }
 
 #define flush_cache_kmaps()    flush_cache_all()
index 03691ab6921732f7df4b0b86e809a90bb61bda68..44d7927aec692ebb36d15ff3de4395d4f4651108 100644 (file)
@@ -1,59 +1,60 @@
 /* This file is meant to be include multiple times by other headers */
+/* last 2 argments are used by platforms/cell/io-workarounds.[ch] */
 
-DEF_PCI_AC_RET(readb, u8, (const PCI_IO_ADDR addr), (addr))
-DEF_PCI_AC_RET(readw, u16, (const PCI_IO_ADDR addr), (addr))
-DEF_PCI_AC_RET(readl, u32, (const PCI_IO_ADDR addr), (addr))
-DEF_PCI_AC_RET(readw_be, u16, (const PCI_IO_ADDR addr), (addr))
-DEF_PCI_AC_RET(readl_be, u32, (const PCI_IO_ADDR addr), (addr))
-DEF_PCI_AC_NORET(writeb, (u8 val, PCI_IO_ADDR addr), (val, addr))
-DEF_PCI_AC_NORET(writew, (u16 val, PCI_IO_ADDR addr), (val, addr))
-DEF_PCI_AC_NORET(writel, (u32 val, PCI_IO_ADDR addr), (val, addr))
-DEF_PCI_AC_NORET(writew_be, (u16 val, PCI_IO_ADDR addr), (val, addr))
-DEF_PCI_AC_NORET(writel_be, (u32 val, PCI_IO_ADDR addr), (val, addr))
+DEF_PCI_AC_RET(readb, u8, (const PCI_IO_ADDR addr), (addr), mem, addr)
+DEF_PCI_AC_RET(readw, u16, (const PCI_IO_ADDR addr), (addr), mem, addr)
+DEF_PCI_AC_RET(readl, u32, (const PCI_IO_ADDR addr), (addr), mem, addr)
+DEF_PCI_AC_RET(readw_be, u16, (const PCI_IO_ADDR addr), (addr), mem, addr)
+DEF_PCI_AC_RET(readl_be, u32, (const PCI_IO_ADDR addr), (addr), mem, addr)
+DEF_PCI_AC_NORET(writeb, (u8 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
+DEF_PCI_AC_NORET(writew, (u16 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
+DEF_PCI_AC_NORET(writel, (u32 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
+DEF_PCI_AC_NORET(writew_be, (u16 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
+DEF_PCI_AC_NORET(writel_be, (u32 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
 
 #ifdef __powerpc64__
-DEF_PCI_AC_RET(readq, u64, (const PCI_IO_ADDR addr), (addr))
-DEF_PCI_AC_RET(readq_be, u64, (const PCI_IO_ADDR addr), (addr))
-DEF_PCI_AC_NORET(writeq, (u64 val, PCI_IO_ADDR addr), (val, addr))
-DEF_PCI_AC_NORET(writeq_be, (u64 val, PCI_IO_ADDR addr), (val, addr))
+DEF_PCI_AC_RET(readq, u64, (const PCI_IO_ADDR addr), (addr), mem, addr)
+DEF_PCI_AC_RET(readq_be, u64, (const PCI_IO_ADDR addr), (addr), mem, addr)
+DEF_PCI_AC_NORET(writeq, (u64 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
+DEF_PCI_AC_NORET(writeq_be, (u64 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
 #endif /* __powerpc64__ */
 
-DEF_PCI_AC_RET(inb, u8, (unsigned long port), (port))
-DEF_PCI_AC_RET(inw, u16, (unsigned long port), (port))
-DEF_PCI_AC_RET(inl, u32, (unsigned long port), (port))
-DEF_PCI_AC_NORET(outb, (u8 val, unsigned long port), (val, port))
-DEF_PCI_AC_NORET(outw, (u16 val, unsigned long port), (val, port))
-DEF_PCI_AC_NORET(outl, (u32 val, unsigned long port), (val, port))
+DEF_PCI_AC_RET(inb, u8, (unsigned long port), (port), pio, port)
+DEF_PCI_AC_RET(inw, u16, (unsigned long port), (port), pio, port)
+DEF_PCI_AC_RET(inl, u32, (unsigned long port), (port), pio, port)
+DEF_PCI_AC_NORET(outb, (u8 val, unsigned long port), (val, port), pio, port)
+DEF_PCI_AC_NORET(outw, (u16 val, unsigned long port), (val, port), pio, port)
+DEF_PCI_AC_NORET(outl, (u32 val, unsigned long port), (val, port), pio, port)
 
-DEF_PCI_AC_NORET(readsb, (const PCI_IO_ADDR a, void *b, unsigned long c), \
-                (a, b, c))
-DEF_PCI_AC_NORET(readsw, (const PCI_IO_ADDR a, void *b, unsigned long c), \
-                (a, b, c))
-DEF_PCI_AC_NORET(readsl, (const PCI_IO_ADDR a, void *b, unsigned long c), \
-                (a, b, c))
-DEF_PCI_AC_NORET(writesb, (PCI_IO_ADDR a, const void *b, unsigned long c), \
-                (a, b, c))
-DEF_PCI_AC_NORET(writesw, (PCI_IO_ADDR a, const void *b, unsigned long c), \
-                (a, b, c))
-DEF_PCI_AC_NORET(writesl, (PCI_IO_ADDR a, const void *b, unsigned long c), \
-                (a, b, c))
+DEF_PCI_AC_NORET(readsb, (const PCI_IO_ADDR a, void *b, unsigned long c),
+                (a, b, c), mem, a)
+DEF_PCI_AC_NORET(readsw, (const PCI_IO_ADDR a, void *b, unsigned long c),
+                (a, b, c), mem, a)
+DEF_PCI_AC_NORET(readsl, (const PCI_IO_ADDR a, void *b, unsigned long c),
+                (a, b, c), mem, a)
+DEF_PCI_AC_NORET(writesb, (PCI_IO_ADDR a, const void *b, unsigned long c),
+                (a, b, c), mem, a)
+DEF_PCI_AC_NORET(writesw, (PCI_IO_ADDR a, const void *b, unsigned long c),
+                (a, b, c), mem, a)
+DEF_PCI_AC_NORET(writesl, (PCI_IO_ADDR a, const void *b, unsigned long c),
+                (a, b, c), mem, a)
 
-DEF_PCI_AC_NORET(insb, (unsigned long p, void *b, unsigned long c), \
-                (p, b, c))
-DEF_PCI_AC_NORET(insw, (unsigned long p, void *b, unsigned long c), \
-                (p, b, c))
-DEF_PCI_AC_NORET(insl, (unsigned long p, void *b, unsigned long c), \
-                (p, b, c))
-DEF_PCI_AC_NORET(outsb, (unsigned long p, const void *b, unsigned long c), \
-                (p, b, c))
-DEF_PCI_AC_NORET(outsw, (unsigned long p, const void *b, unsigned long c), \
-                (p, b, c))
-DEF_PCI_AC_NORET(outsl, (unsigned long p, const void *b, unsigned long c), \
-                (p, b, c))
+DEF_PCI_AC_NORET(insb, (unsigned long p, void *b, unsigned long c),
+                (p, b, c), pio, p)
+DEF_PCI_AC_NORET(insw, (unsigned long p, void *b, unsigned long c),
+                (p, b, c), pio, p)
+DEF_PCI_AC_NORET(insl, (unsigned long p, void *b, unsigned long c),
+                (p, b, c), pio, p)
+DEF_PCI_AC_NORET(outsb, (unsigned long p, const void *b, unsigned long c),
+                (p, b, c), pio, p)
+DEF_PCI_AC_NORET(outsw, (unsigned long p, const void *b, unsigned long c),
+                (p, b, c), pio, p)
+DEF_PCI_AC_NORET(outsl, (unsigned long p, const void *b, unsigned long c),
+                (p, b, c), pio, p)
 
-DEF_PCI_AC_NORET(memset_io, (PCI_IO_ADDR a, int c, unsigned long n),      \
-                (a, c, n))
-DEF_PCI_AC_NORET(memcpy_fromio,(void *d,const PCI_IO_ADDR s,unsigned long n), \
-                (d, s, n))
-DEF_PCI_AC_NORET(memcpy_toio,(PCI_IO_ADDR d,const void *s,unsigned long n),   \
-                (d, s, n))
+DEF_PCI_AC_NORET(memset_io, (PCI_IO_ADDR a, int c, unsigned long n),
+                (a, c, n), mem, a)
+DEF_PCI_AC_NORET(memcpy_fromio, (void *d, const PCI_IO_ADDR s, unsigned long n),
+                (d, s, n), mem, s)
+DEF_PCI_AC_NORET(memcpy_toio, (PCI_IO_ADDR d, const void *s, unsigned long n),
+                (d, s, n), mem, d)
index 7be26f615755ad5a80c84aa3867facf781f3db03..afae0697e8ce441b60d219b17530391591fe0484 100644 (file)
@@ -458,8 +458,8 @@ __do_out_asm(_rec_outl, "stwbrx")
 /* Structure containing all the hooks */
 extern struct ppc_pci_io {
 
-#define DEF_PCI_AC_RET(name, ret, at, al)      ret (*name) at;
-#define DEF_PCI_AC_NORET(name, at, al)         void (*name) at;
+#define DEF_PCI_AC_RET(name, ret, at, al, space, aa)   ret (*name) at;
+#define DEF_PCI_AC_NORET(name, at, al, space, aa)      void (*name) at;
 
 #include <asm/io-defs.h>
 
@@ -469,7 +469,7 @@ extern struct ppc_pci_io {
 } ppc_pci_io;
 
 /* The inline wrappers */
-#define DEF_PCI_AC_RET(name, ret, at, al)                      \
+#define DEF_PCI_AC_RET(name, ret, at, al, space, aa)           \
 static inline ret name at                                      \
 {                                                              \
        if (DEF_PCI_HOOK(ppc_pci_io.name) != NULL)              \
@@ -477,7 +477,7 @@ static inline ret name at                                   \
        return __do_##name al;                                  \
 }
 
-#define DEF_PCI_AC_NORET(name, at, al)                         \
+#define DEF_PCI_AC_NORET(name, at, al, space, aa)              \
 static inline void name at                                     \
 {                                                              \
        if (DEF_PCI_HOOK(ppc_pci_io.name) != NULL)              \
index 10e8eb1e6f4f67e9ec9d1577927980481659926d..f6c93c7168988664ad6144d06936ac3ebfc964ca 100644 (file)
 
 #ifdef CONFIG_CRASH_DUMP
 
-#define PHYSICAL_START KDUMP_KERNELBASE
 #define KDUMP_TRAMPOLINE_START 0x0100
 #define KDUMP_TRAMPOLINE_END   0x3000
 
 #define KDUMP_MIN_TCE_ENTRIES  2048
 
-#else /* !CONFIG_CRASH_DUMP */
-
-#define PHYSICAL_START 0x0
-
 #endif /* CONFIG_CRASH_DUMP */
 
 #ifndef __ASSEMBLY__
index d1b530fbf8dd667b31658b5fcbeb8b39a6198c68..f993e4198d5ca0d3554fc68ee4c64c92c25243ca 100644 (file)
@@ -1,6 +1,55 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
 #ifndef __LINUX_KVM_POWERPC_H
 #define __LINUX_KVM_POWERPC_H
 
-/* powerpc does not support KVM */
+#include <asm/types.h>
+
+struct kvm_regs {
+       __u64 pc;
+       __u64 cr;
+       __u64 ctr;
+       __u64 lr;
+       __u64 xer;
+       __u64 msr;
+       __u64 srr0;
+       __u64 srr1;
+       __u64 pid;
+
+       __u64 sprg0;
+       __u64 sprg1;
+       __u64 sprg2;
+       __u64 sprg3;
+       __u64 sprg4;
+       __u64 sprg5;
+       __u64 sprg6;
+       __u64 sprg7;
+
+       __u64 gpr[32];
+};
+
+struct kvm_sregs {
+};
+
+struct kvm_fpu {
+       __u64 fpr[32];
+};
 
-#endif
+#endif /* __LINUX_KVM_POWERPC_H */
diff --git a/include/asm-powerpc/kvm_asm.h b/include/asm-powerpc/kvm_asm.h
new file mode 100644 (file)
index 0000000..2197764
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#ifndef __POWERPC_KVM_ASM_H__
+#define __POWERPC_KVM_ASM_H__
+
+/* IVPR must be 64KiB-aligned. */
+#define VCPU_SIZE_ORDER 4
+#define VCPU_SIZE_LOG   (VCPU_SIZE_ORDER + 12)
+#define VCPU_TLB_PGSZ   PPC44x_TLB_64K
+#define VCPU_SIZE_BYTES (1<<VCPU_SIZE_LOG)
+
+#define BOOKE_INTERRUPT_CRITICAL 0
+#define BOOKE_INTERRUPT_MACHINE_CHECK 1
+#define BOOKE_INTERRUPT_DATA_STORAGE 2
+#define BOOKE_INTERRUPT_INST_STORAGE 3
+#define BOOKE_INTERRUPT_EXTERNAL 4
+#define BOOKE_INTERRUPT_ALIGNMENT 5
+#define BOOKE_INTERRUPT_PROGRAM 6
+#define BOOKE_INTERRUPT_FP_UNAVAIL 7
+#define BOOKE_INTERRUPT_SYSCALL 8
+#define BOOKE_INTERRUPT_AP_UNAVAIL 9
+#define BOOKE_INTERRUPT_DECREMENTER 10
+#define BOOKE_INTERRUPT_FIT 11
+#define BOOKE_INTERRUPT_WATCHDOG 12
+#define BOOKE_INTERRUPT_DTLB_MISS 13
+#define BOOKE_INTERRUPT_ITLB_MISS 14
+#define BOOKE_INTERRUPT_DEBUG 15
+#define BOOKE_MAX_INTERRUPT 15
+
+#define RESUME_FLAG_NV          (1<<0)  /* Reload guest nonvolatile state? */
+#define RESUME_FLAG_HOST        (1<<1)  /* Resume host? */
+
+#define RESUME_GUEST            0
+#define RESUME_GUEST_NV         RESUME_FLAG_NV
+#define RESUME_HOST             RESUME_FLAG_HOST
+#define RESUME_HOST_NV          (RESUME_FLAG_HOST|RESUME_FLAG_NV)
+
+#endif /* __POWERPC_KVM_ASM_H__ */
diff --git a/include/asm-powerpc/kvm_host.h b/include/asm-powerpc/kvm_host.h
new file mode 100644 (file)
index 0000000..04ffbb8
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#ifndef __POWERPC_KVM_HOST_H__
+#define __POWERPC_KVM_HOST_H__
+
+#include <linux/mutex.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/kvm_types.h>
+#include <asm/kvm_asm.h>
+
+#define KVM_MAX_VCPUS 1
+#define KVM_MEMORY_SLOTS 32
+/* memory slots that does not exposed to userspace */
+#define KVM_PRIVATE_MEM_SLOTS 4
+
+/* We don't currently support large pages. */
+#define KVM_PAGES_PER_HPAGE (1<<31)
+
+struct kvm;
+struct kvm_run;
+struct kvm_vcpu;
+
+struct kvm_vm_stat {
+       u32 remote_tlb_flush;
+};
+
+struct kvm_vcpu_stat {
+       u32 sum_exits;
+       u32 mmio_exits;
+       u32 dcr_exits;
+       u32 signal_exits;
+       u32 light_exits;
+       /* Account for special types of light exits: */
+       u32 itlb_real_miss_exits;
+       u32 itlb_virt_miss_exits;
+       u32 dtlb_real_miss_exits;
+       u32 dtlb_virt_miss_exits;
+       u32 syscall_exits;
+       u32 isi_exits;
+       u32 dsi_exits;
+       u32 emulated_inst_exits;
+       u32 dec_exits;
+       u32 ext_intr_exits;
+};
+
+struct tlbe {
+       u32 tid; /* Only the low 8 bits are used. */
+       u32 word0;
+       u32 word1;
+       u32 word2;
+};
+
+struct kvm_arch {
+};
+
+struct kvm_vcpu_arch {
+       /* Unmodified copy of the guest's TLB. */
+       struct tlbe guest_tlb[PPC44x_TLB_SIZE];
+       /* TLB that's actually used when the guest is running. */
+       struct tlbe shadow_tlb[PPC44x_TLB_SIZE];
+       /* Pages which are referenced in the shadow TLB. */
+       struct page *shadow_pages[PPC44x_TLB_SIZE];
+       /* Copy of the host's TLB. */
+       struct tlbe host_tlb[PPC44x_TLB_SIZE];
+
+       u32 host_stack;
+       u32 host_pid;
+
+       u64 fpr[32];
+       u32 gpr[32];
+
+       u32 pc;
+       u32 cr;
+       u32 ctr;
+       u32 lr;
+       u32 xer;
+
+       u32 msr;
+       u32 mmucr;
+       u32 sprg0;
+       u32 sprg1;
+       u32 sprg2;
+       u32 sprg3;
+       u32 sprg4;
+       u32 sprg5;
+       u32 sprg6;
+       u32 sprg7;
+       u32 srr0;
+       u32 srr1;
+       u32 csrr0;
+       u32 csrr1;
+       u32 dsrr0;
+       u32 dsrr1;
+       u32 dear;
+       u32 esr;
+       u32 dec;
+       u32 decar;
+       u32 tbl;
+       u32 tbu;
+       u32 tcr;
+       u32 tsr;
+       u32 ivor[16];
+       u32 ivpr;
+       u32 pir;
+       u32 pid;
+       u32 pvr;
+       u32 ccr0;
+       u32 ccr1;
+       u32 dbcr0;
+       u32 dbcr1;
+
+       u32 last_inst;
+       u32 fault_dear;
+       u32 fault_esr;
+       gpa_t paddr_accessed;
+
+       u8 io_gpr; /* GPR used as IO source/target */
+       u8 mmio_is_bigendian;
+       u8 dcr_needed;
+       u8 dcr_is_write;
+
+       u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */
+
+       struct timer_list dec_timer;
+       unsigned long pending_exceptions;
+};
+
+struct kvm_guest_debug {
+       int enabled;
+       unsigned long bp[4];
+       int singlestep;
+};
+
+#endif /* __POWERPC_KVM_HOST_H__ */
diff --git a/include/asm-powerpc/kvm_para.h b/include/asm-powerpc/kvm_para.h
new file mode 100644 (file)
index 0000000..2d48f6a
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#ifndef __POWERPC_KVM_PARA_H__
+#define __POWERPC_KVM_PARA_H__
+
+#ifdef __KERNEL__
+
+static inline int kvm_para_available(void)
+{
+       return 0;
+}
+
+static inline unsigned int kvm_arch_para_features(void)
+{
+       return 0;
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* __POWERPC_KVM_PARA_H__ */
diff --git a/include/asm-powerpc/kvm_ppc.h b/include/asm-powerpc/kvm_ppc.h
new file mode 100644 (file)
index 0000000..7ac8203
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#ifndef __POWERPC_KVM_PPC_H__
+#define __POWERPC_KVM_PPC_H__
+
+/* This file exists just so we can dereference kvm_vcpu, avoiding nested header
+ * dependencies. */
+
+#include <linux/mutex.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/kvm_types.h>
+#include <linux/kvm_host.h>
+
+struct kvm_tlb {
+       struct tlbe guest_tlb[PPC44x_TLB_SIZE];
+       struct tlbe shadow_tlb[PPC44x_TLB_SIZE];
+};
+
+enum emulation_result {
+       EMULATE_DONE,         /* no further processing */
+       EMULATE_DO_MMIO,      /* kvm_run filled with MMIO request */
+       EMULATE_DO_DCR,       /* kvm_run filled with DCR request */
+       EMULATE_FAIL,         /* can't emulate this instruction */
+};
+
+extern const unsigned char exception_priority[];
+extern const unsigned char priority_exception[];
+
+extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
+extern char kvmppc_handlers_start[];
+extern unsigned long kvmppc_handler_len;
+
+extern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu);
+extern int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
+                              unsigned int rt, unsigned int bytes,
+                              int is_bigendian);
+extern int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
+                               u32 val, unsigned int bytes, int is_bigendian);
+
+extern int kvmppc_emulate_instruction(struct kvm_run *run,
+                                      struct kvm_vcpu *vcpu);
+
+extern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn,
+                           u64 asid, u32 flags);
+extern void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, u64 eaddr, u64 asid);
+extern void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode);
+
+extern void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu);
+
+static inline void kvmppc_queue_exception(struct kvm_vcpu *vcpu, int exception)
+{
+       unsigned int priority = exception_priority[exception];
+       set_bit(priority, &vcpu->arch.pending_exceptions);
+}
+
+static inline void kvmppc_clear_exception(struct kvm_vcpu *vcpu, int exception)
+{
+       unsigned int priority = exception_priority[exception];
+       clear_bit(priority, &vcpu->arch.pending_exceptions);
+}
+
+static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
+{
+       if ((new_msr & MSR_PR) != (vcpu->arch.msr & MSR_PR))
+               kvmppc_mmu_priv_switch(vcpu, new_msr & MSR_PR);
+
+       vcpu->arch.msr = new_msr;
+}
+
+#endif /* __POWERPC_KVM_PPC_H__ */
index c8b02d97f75378c6c42b81c3adadfed7a57ffbd8..a825524c981a3965bda27107e53e83b62e7b4c13 100644 (file)
@@ -53,6 +53,8 @@
 
 #ifndef __ASSEMBLY__
 
+extern unsigned int tlb_44x_hwater;
+
 typedef struct {
        unsigned long id;
        unsigned long vdso_base;
index eb61b9c1edfdf91b167bddb4f306e9b2ad43afe4..7b564444ff619ad1a280c962602392681712bb83 100644 (file)
@@ -108,6 +108,7 @@ struct paca_struct {
 };
 
 extern struct paca_struct paca[];
+extern void initialise_pacas(void);
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_PACA_H */
index 6c850609b847c01900db5ec9fdb7f40cce92eede..cffdf0eb0df68068fb0720a8ba9adff870be5fbe 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <asm/asm-compat.h>
 #include <asm/kdump.h>
+#include <asm/types.h>
 
 /*
  * On PPC32 page size is 4K. For PPC64 we support either 4K or 64K software
  *
  * The kdump dump kernel is one example where KERNELBASE != PAGE_OFFSET.
  *
- * To get a physical address from a virtual one you subtract PAGE_OFFSET,
- * _not_ KERNELBASE.
+ * PAGE_OFFSET is the virtual address of the start of lowmem.
+ *
+ * PHYSICAL_START is the physical address of the start of the kernel.
+ *
+ * MEMORY_START is the physical address of the start of lowmem.
+ *
+ * KERNELBASE, PAGE_OFFSET, and PHYSICAL_START are all configurable on
+ * ppc32 and based on how they are set we determine MEMORY_START.
+ *
+ * For the linear mapping the following equation should be true:
+ * KERNELBASE - PAGE_OFFSET = PHYSICAL_START - MEMORY_START
+ *
+ * Also, KERNELBASE >= PAGE_OFFSET and PHYSICAL_START >= MEMORY_START
+ *
+ * There are two was to determine a physical address from a virtual one:
+ * va = pa + PAGE_OFFSET - MEMORY_START
+ * va = pa + KERNELBASE - PHYSICAL_START
  *
  * If you want to know something's offset from the start of the kernel you
  * should subtract KERNELBASE.
  * If you want to test if something's a kernel address, use is_kernel_addr().
  */
 
-#define PAGE_OFFSET     ASM_CONST(CONFIG_KERNEL_START)
-#define KERNELBASE      (PAGE_OFFSET + PHYSICAL_START)
-#define LOAD_OFFSET    PAGE_OFFSET
+#define KERNELBASE      ASM_CONST(CONFIG_KERNEL_START)
+#define PAGE_OFFSET    ASM_CONST(CONFIG_PAGE_OFFSET)
+#define LOAD_OFFSET    ASM_CONST((CONFIG_KERNEL_START-CONFIG_PHYSICAL_START))
+
+#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_FLATMEM)
+#ifndef __ASSEMBLY__
+extern phys_addr_t memstart_addr;
+extern phys_addr_t kernstart_addr;
+#endif
+#define PHYSICAL_START kernstart_addr
+#define MEMORY_START   memstart_addr
+#else
+#define PHYSICAL_START ASM_CONST(CONFIG_PHYSICAL_START)
+#define MEMORY_START   (PHYSICAL_START + PAGE_OFFSET - KERNELBASE)
+#endif
 
 #ifdef CONFIG_FLATMEM
-#define pfn_valid(pfn)         ((pfn) < max_mapnr)
+#define ARCH_PFN_OFFSET                (MEMORY_START >> PAGE_SHIFT)
+#define pfn_valid(pfn)         ((pfn) >= ARCH_PFN_OFFSET && (pfn) < (ARCH_PFN_OFFSET + max_mapnr))
 #endif
 
 #define virt_to_page(kaddr)    pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 #define pfn_to_kaddr(pfn)      __va((pfn) << PAGE_SHIFT)
 #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
-#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
-#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
+#define __va(x) ((void *)((unsigned long)(x) - PHYSICAL_START + KERNELBASE))
+#define __pa(x) ((unsigned long)(x) + PHYSICAL_START - KERNELBASE)
 
 /*
  * Unfortunately the PLT is in the BSS in the PPC32 ELF ABI,
index 51f8134b5939393e66072a66935f642e7f322f55..ebfae530a3799b075c201df143394d1694ef74e7 100644 (file)
@@ -1,6 +1,12 @@
 #ifndef _ASM_POWERPC_PAGE_32_H
 #define _ASM_POWERPC_PAGE_32_H
 
+#if defined(CONFIG_PHYSICAL_ALIGN) && (CONFIG_PHYSICAL_START != 0)
+#if (CONFIG_PHYSICAL_START % CONFIG_PHYSICAL_ALIGN) != 0
+#error "CONFIG_PHYSICAL_START must be a multiple of CONFIG_PHYSICAL_ALIGN"
+#endif
+#endif
+
 #define VM_DATA_DEFAULT_FLAGS  VM_DATA_DEFAULT_FLAGS32
 
 #ifdef CONFIG_NOT_COHERENT_CACHE
index 40d5f98c44fca2f79fbdae31feb791bfff247bdc..d030f5ce39adafdac57aa0fd93d88bc8f985b2ea 100644 (file)
@@ -80,12 +80,8 @@ struct thread_info {
 
 #else /* THREAD_SHIFT < PAGE_SHIFT */
 
-#ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk) kzalloc(THREAD_SIZE, GFP_KERNEL)
-#else
-#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
-#endif
-#define free_thread_info(ti)   kfree(ti)
+extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
+extern void free_thread_info(struct thread_info *ti);
 
 #endif /* THREAD_SHIFT < PAGE_SHIFT */
 
index d46b57b589ae75334c041af4d4bac4f9f15990cb..d76ef098ed37efc613dbf87276d3d9b29a13ca49 100644 (file)
  * physical need a larger than native word size type. -Matt
  */
 #ifndef CONFIG_PHYS_64BIT
-typedef unsigned long phys_addr_t;
 #define PHYS_FMT       "%.8lx"
 #else
-typedef unsigned long long phys_addr_t;
 extern phys_addr_t fixup_bigphys_addr(phys_addr_t, phys_addr_t);
 #define PHYS_FMT       "%16Lx"
 #endif
index 23579d4afae7549880454074171c4683b3e13fda..402ba15c2e80f3f19d1330a10619bf1823c092d0 100644 (file)
 #include <platforms/tqm8260.h>
 #endif
 
-#if defined(CONFIG_PQ2ADS) || defined (CONFIG_PQ2FADS)
-#include <platforms/pq2ads.h>
-#endif
-
 #ifdef CONFIG_PCI_8260
 #include <syslib/m82xx_pci.h>
 #endif
index d3a2f2fe230c2181dcad280df11d0b8c20a58612..b9e3060b0278e1a102a47f2b5da052921df5cdd1 100644 (file)
 #include <platforms/lantec.h>
 #endif
 
-#if defined(CONFIG_MPC885ADS)
-#include <platforms/mpc885ads.h>
-#endif
-
 /* Currently, all 8xx boards that support a processor to PCI/ISA bridge
  * use the same memory map.
  */
index e92b429d2be1be16176a4246eb4e10d135dcc736..13c9805349f170deda0308100707ba856390a730 100644 (file)
@@ -7,6 +7,7 @@ header-y += tape390.h
 header-y += ucontext.h
 header-y += vtoc.h
 header-y += zcrypt.h
+header-y += kvm.h
 
 unifdef-y += cmb.h
 unifdef-y += debug.h
index 965394e69452daf2cf856a5a54472cbb7f1ab8e4..b4eb24ab5af97811e5a0ca1845607de238210863 100644 (file)
@@ -769,6 +769,7 @@ static inline int sched_find_first_bit(unsigned long *b)
 }
 
 #include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 
 #include <asm-generic/bitops/hweight.h>
index 573f2a35138662f698c72e0978450db22fba74b6..d74002f9579482f1bb13fc0a223b88802e6c1826 100644 (file)
@@ -1,6 +1,45 @@
 #ifndef __LINUX_KVM_S390_H
 #define __LINUX_KVM_S390_H
 
-/* s390 does not support KVM */
+/*
+ * asm-s390/kvm.h - KVM s390 specific structures and definitions
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Carsten Otte <cotte@de.ibm.com>
+ *               Christian Borntraeger <borntraeger@de.ibm.com>
+ */
+#include <asm/types.h>
+
+/* for KVM_GET_IRQCHIP and KVM_SET_IRQCHIP */
+struct kvm_pic_state {
+       /* no PIC for s390 */
+};
+
+struct kvm_ioapic_state {
+       /* no IOAPIC for s390 */
+};
+
+/* for KVM_GET_REGS and KVM_SET_REGS */
+struct kvm_regs {
+       /* general purpose regs for s390 */
+       __u64 gprs[16];
+};
+
+/* for KVM_GET_SREGS and KVM_SET_SREGS */
+struct kvm_sregs {
+       __u32 acrs[16];
+       __u64 crs[16];
+};
+
+/* for KVM_GET_FPU and KVM_SET_FPU */
+struct kvm_fpu {
+       __u32 fpc;
+       __u64 fprs[16];
+};
 
 #endif
diff --git a/include/asm-s390/kvm_host.h b/include/asm-s390/kvm_host.h
new file mode 100644 (file)
index 0000000..f8204a4
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * asm-s390/kvm_host.h - definition for kernel virtual machines on s390
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Carsten Otte <cotte@de.ibm.com>
+ */
+
+
+#ifndef ASM_KVM_HOST_H
+#define ASM_KVM_HOST_H
+#include <linux/kvm_host.h>
+#include <asm/debug.h>
+
+#define KVM_MAX_VCPUS 64
+#define KVM_MEMORY_SLOTS 32
+/* memory slots that does not exposed to userspace */
+#define KVM_PRIVATE_MEM_SLOTS 4
+
+struct kvm_guest_debug {
+};
+
+struct sca_entry {
+       atomic_t scn;
+       __u64   reserved;
+       __u64   sda;
+       __u64   reserved2[2];
+} __attribute__((packed));
+
+
+struct sca_block {
+       __u64   ipte_control;
+       __u64   reserved[5];
+       __u64   mcn;
+       __u64   reserved2;
+       struct sca_entry cpu[64];
+} __attribute__((packed));
+
+#define KVM_PAGES_PER_HPAGE 256
+
+#define CPUSTAT_HOST       0x80000000
+#define CPUSTAT_WAIT       0x10000000
+#define CPUSTAT_ECALL_PEND 0x08000000
+#define CPUSTAT_STOP_INT   0x04000000
+#define CPUSTAT_IO_INT     0x02000000
+#define CPUSTAT_EXT_INT    0x01000000
+#define CPUSTAT_RUNNING    0x00800000
+#define CPUSTAT_RETAINED   0x00400000
+#define CPUSTAT_TIMING_SUB 0x00020000
+#define CPUSTAT_SIE_SUB    0x00010000
+#define CPUSTAT_RRF        0x00008000
+#define CPUSTAT_SLSV       0x00004000
+#define CPUSTAT_SLSR       0x00002000
+#define CPUSTAT_ZARCH      0x00000800
+#define CPUSTAT_MCDS       0x00000100
+#define CPUSTAT_SM         0x00000080
+#define CPUSTAT_G          0x00000008
+#define CPUSTAT_J          0x00000002
+#define CPUSTAT_P          0x00000001
+
+struct sie_block {
+       atomic_t cpuflags;              /* 0x0000 */
+       __u32   prefix;                 /* 0x0004 */
+       __u8    reserved8[32];          /* 0x0008 */
+       __u64   cputm;                  /* 0x0028 */
+       __u64   ckc;                    /* 0x0030 */
+       __u64   epoch;                  /* 0x0038 */
+       __u8    reserved40[4];          /* 0x0040 */
+#define LCTL_CR0       0x8000
+       __u16   lctl;                   /* 0x0044 */
+       __s16   icpua;                  /* 0x0046 */
+       __u32   ictl;                   /* 0x0048 */
+       __u32   eca;                    /* 0x004c */
+       __u8    icptcode;               /* 0x0050 */
+       __u8    reserved51;             /* 0x0051 */
+       __u16   ihcpu;                  /* 0x0052 */
+       __u8    reserved54[2];          /* 0x0054 */
+       __u16   ipa;                    /* 0x0056 */
+       __u32   ipb;                    /* 0x0058 */
+       __u32   scaoh;                  /* 0x005c */
+       __u8    reserved60;             /* 0x0060 */
+       __u8    ecb;                    /* 0x0061 */
+       __u8    reserved62[2];          /* 0x0062 */
+       __u32   scaol;                  /* 0x0064 */
+       __u8    reserved68[4];          /* 0x0068 */
+       __u32   todpr;                  /* 0x006c */
+       __u8    reserved70[16];         /* 0x0070 */
+       __u64   gmsor;                  /* 0x0080 */
+       __u64   gmslm;                  /* 0x0088 */
+       psw_t   gpsw;                   /* 0x0090 */
+       __u64   gg14;                   /* 0x00a0 */
+       __u64   gg15;                   /* 0x00a8 */
+       __u8    reservedb0[30];         /* 0x00b0 */
+       __u16   iprcc;                  /* 0x00ce */
+       __u8    reservedd0[48];         /* 0x00d0 */
+       __u64   gcr[16];                /* 0x0100 */
+       __u64   gbea;                   /* 0x0180 */
+       __u8    reserved188[120];       /* 0x0188 */
+} __attribute__((packed));
+
+struct kvm_vcpu_stat {
+       u32 exit_userspace;
+       u32 exit_external_request;
+       u32 exit_external_interrupt;
+       u32 exit_stop_request;
+       u32 exit_validity;
+       u32 exit_instruction;
+       u32 instruction_lctl;
+       u32 instruction_lctg;
+       u32 exit_program_interruption;
+       u32 exit_instr_and_program;
+       u32 deliver_emergency_signal;
+       u32 deliver_service_signal;
+       u32 deliver_virtio_interrupt;
+       u32 deliver_stop_signal;
+       u32 deliver_prefix_signal;
+       u32 deliver_restart_signal;
+       u32 deliver_program_int;
+       u32 exit_wait_state;
+       u32 instruction_stidp;
+       u32 instruction_spx;
+       u32 instruction_stpx;
+       u32 instruction_stap;
+       u32 instruction_storage_key;
+       u32 instruction_stsch;
+       u32 instruction_chsc;
+       u32 instruction_stsi;
+       u32 instruction_stfl;
+       u32 instruction_sigp_sense;
+       u32 instruction_sigp_emergency;
+       u32 instruction_sigp_stop;
+       u32 instruction_sigp_arch;
+       u32 instruction_sigp_prefix;
+       u32 instruction_sigp_restart;
+       u32 diagnose_44;
+};
+
+struct io_info {
+       __u16        subchannel_id;            /* 0x0b8 */
+       __u16        subchannel_nr;            /* 0x0ba */
+       __u32        io_int_parm;              /* 0x0bc */
+       __u32        io_int_word;              /* 0x0c0 */
+};
+
+struct ext_info {
+       __u32 ext_params;
+       __u64 ext_params2;
+};
+
+#define PGM_OPERATION            0x01
+#define PGM_PRIVILEGED_OPERATION 0x02
+#define PGM_EXECUTE              0x03
+#define PGM_PROTECTION           0x04
+#define PGM_ADDRESSING           0x05
+#define PGM_SPECIFICATION        0x06
+#define PGM_DATA                 0x07
+
+struct pgm_info {
+       __u16 code;
+};
+
+struct prefix_info {
+       __u32 address;
+};
+
+struct interrupt_info {
+       struct list_head list;
+       u64     type;
+       union {
+               struct io_info io;
+               struct ext_info ext;
+               struct pgm_info pgm;
+               struct prefix_info prefix;
+       };
+};
+
+/* for local_interrupt.action_flags */
+#define ACTION_STORE_ON_STOP 1
+#define ACTION_STOP_ON_STOP  2
+
+struct local_interrupt {
+       spinlock_t lock;
+       struct list_head list;
+       atomic_t active;
+       struct float_interrupt *float_int;
+       int timer_due; /* event indicator for waitqueue below */
+       wait_queue_head_t wq;
+       atomic_t *cpuflags;
+       unsigned int action_bits;
+};
+
+struct float_interrupt {
+       spinlock_t lock;
+       struct list_head list;
+       atomic_t active;
+       int next_rr_cpu;
+       unsigned long idle_mask [(64 + sizeof(long) - 1) / sizeof(long)];
+       struct local_interrupt *local_int[64];
+};
+
+
+struct kvm_vcpu_arch {
+       struct sie_block *sie_block;
+       unsigned long     guest_gprs[16];
+       s390_fp_regs      host_fpregs;
+       unsigned int      host_acrs[NUM_ACRS];
+       s390_fp_regs      guest_fpregs;
+       unsigned int      guest_acrs[NUM_ACRS];
+       struct local_interrupt local_int;
+       struct timer_list ckc_timer;
+       union  {
+               cpuid_t   cpu_id;
+               u64       stidp_data;
+       };
+};
+
+struct kvm_vm_stat {
+       u32 remote_tlb_flush;
+};
+
+struct kvm_arch{
+       unsigned long guest_origin;
+       unsigned long guest_memsize;
+       struct sca_block *sca;
+       debug_info_t *dbf;
+       struct float_interrupt float_int;
+};
+
+extern int sie64a(struct sie_block *, __u64 *);
+#endif
diff --git a/include/asm-s390/kvm_para.h b/include/asm-s390/kvm_para.h
new file mode 100644 (file)
index 0000000..2c50379
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * asm-s390/kvm_para.h - definition for paravirtual devices on s390
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
+ */
+
+#ifndef __S390_KVM_PARA_H
+#define __S390_KVM_PARA_H
+
+/*
+ * Hypercalls for KVM on s390. The calling convention is similar to the
+ * s390 ABI, so we use R2-R6 for parameters 1-5. In addition we use R1
+ * as hypercall number and R7 as parameter 6. The return value is
+ * written to R2. We use the diagnose instruction as hypercall. To avoid
+ * conflicts with existing diagnoses for LPAR and z/VM, we do not use
+ * the instruction encoded number, but specify the number in R1 and
+ * use 0x500 as KVM hypercall
+ *
+ * Copyright IBM Corp. 2007,2008
+ * Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ */
+
+static inline long kvm_hypercall0(unsigned long nr)
+{
+       register unsigned long __nr asm("1") = nr;
+       register long __rc asm("2");
+
+       asm volatile ("diag 2,4,0x500\n"
+                     : "=d" (__rc) : "d" (__nr): "memory", "cc");
+       return __rc;
+}
+
+static inline long kvm_hypercall1(unsigned long nr, unsigned long p1)
+{
+       register unsigned long __nr asm("1") = nr;
+       register unsigned long __p1 asm("2") = p1;
+       register long __rc asm("2");
+
+       asm volatile ("diag 2,4,0x500\n"
+                     : "=d" (__rc) : "d" (__nr), "0" (__p1) : "memory", "cc");
+       return __rc;
+}
+
+static inline long kvm_hypercall2(unsigned long nr, unsigned long p1,
+                              unsigned long p2)
+{
+       register unsigned long __nr asm("1") = nr;
+       register unsigned long __p1 asm("2") = p1;
+       register unsigned long __p2 asm("3") = p2;
+       register long __rc asm("2");
+
+       asm volatile ("diag 2,4,0x500\n"
+                     : "=d" (__rc) : "d" (__nr), "0" (__p1), "d" (__p2)
+                     : "memory", "cc");
+       return __rc;
+}
+
+static inline long kvm_hypercall3(unsigned long nr, unsigned long p1,
+                              unsigned long p2, unsigned long p3)
+{
+       register unsigned long __nr asm("1") = nr;
+       register unsigned long __p1 asm("2") = p1;
+       register unsigned long __p2 asm("3") = p2;
+       register unsigned long __p3 asm("4") = p3;
+       register long __rc asm("2");
+
+       asm volatile ("diag 2,4,0x500\n"
+                     : "=d" (__rc) : "d" (__nr), "0" (__p1), "d" (__p2),
+                       "d" (__p3) : "memory", "cc");
+       return __rc;
+}
+
+
+static inline long kvm_hypercall4(unsigned long nr, unsigned long p1,
+                              unsigned long p2, unsigned long p3,
+                              unsigned long p4)
+{
+       register unsigned long __nr asm("1") = nr;
+       register unsigned long __p1 asm("2") = p1;
+       register unsigned long __p2 asm("3") = p2;
+       register unsigned long __p3 asm("4") = p3;
+       register unsigned long __p4 asm("5") = p4;
+       register long __rc asm("2");
+
+       asm volatile ("diag 2,4,0x500\n"
+                     : "=d" (__rc) : "d" (__nr), "0" (__p1), "d" (__p2),
+                       "d" (__p3), "d" (__p4) : "memory", "cc");
+       return __rc;
+}
+
+static inline long kvm_hypercall5(unsigned long nr, unsigned long p1,
+                              unsigned long p2, unsigned long p3,
+                              unsigned long p4, unsigned long p5)
+{
+       register unsigned long __nr asm("1") = nr;
+       register unsigned long __p1 asm("2") = p1;
+       register unsigned long __p2 asm("3") = p2;
+       register unsigned long __p3 asm("4") = p3;
+       register unsigned long __p4 asm("5") = p4;
+       register unsigned long __p5 asm("6") = p5;
+       register long __rc asm("2");
+
+       asm volatile ("diag 2,4,0x500\n"
+                     : "=d" (__rc) : "d" (__nr), "0" (__p1), "d" (__p2),
+                       "d" (__p3), "d" (__p4), "d" (__p5)  : "memory", "cc");
+       return __rc;
+}
+
+static inline long kvm_hypercall6(unsigned long nr, unsigned long p1,
+                              unsigned long p2, unsigned long p3,
+                              unsigned long p4, unsigned long p5,
+                              unsigned long p6)
+{
+       register unsigned long __nr asm("1") = nr;
+       register unsigned long __p1 asm("2") = p1;
+       register unsigned long __p2 asm("3") = p2;
+       register unsigned long __p3 asm("4") = p3;
+       register unsigned long __p4 asm("5") = p4;
+       register unsigned long __p5 asm("6") = p5;
+       register unsigned long __p6 asm("7") = p6;
+       register long __rc asm("2");
+
+       asm volatile ("diag 2,4,0x500\n"
+                     : "=d" (__rc) : "d" (__nr), "0" (__p1), "d" (__p2),
+                       "d" (__p3), "d" (__p4), "d" (__p5), "d" (__p6)
+                     : "memory", "cc");
+       return __rc;
+}
+
+/* kvm on s390 is always paravirtualization enabled */
+static inline int kvm_para_available(void)
+{
+       return 1;
+}
+
+/* No feature bits are currently assigned for kvm on s390 */
+static inline unsigned int kvm_arch_para_features(void)
+{
+       return 0;
+}
+
+#endif /* __S390_KVM_PARA_H */
diff --git a/include/asm-s390/kvm_virtio.h b/include/asm-s390/kvm_virtio.h
new file mode 100644 (file)
index 0000000..5c871a9
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * kvm_virtio.h - definition for virtio for kvm on s390
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
+ */
+
+#ifndef __KVM_S390_VIRTIO_H
+#define __KVM_S390_VIRTIO_H
+
+#include <linux/types.h>
+
+struct kvm_device_desc {
+       /* The device type: console, network, disk etc.  Type 0 terminates. */
+       __u8 type;
+       /* The number of virtqueues (first in config array) */
+       __u8 num_vq;
+       /*
+        * The number of bytes of feature bits.  Multiply by 2: one for host
+        * features and one for guest acknowledgements.
+        */
+       __u8 feature_len;
+       /* The number of bytes of the config array after virtqueues. */
+       __u8 config_len;
+       /* A status byte, written by the Guest. */
+       __u8 status;
+       __u8 config[0];
+};
+
+/*
+ * This is how we expect the device configuration field for a virtqueue
+ * to be laid out in config space.
+ */
+struct kvm_vqconfig {
+       /* The token returned with an interrupt. Set by the guest */
+       __u64 token;
+       /* The address of the virtio ring */
+       __u64 address;
+       /* The number of entries in the virtio_ring */
+       __u16 num;
+
+};
+
+#define KVM_S390_VIRTIO_NOTIFY         0
+#define KVM_S390_VIRTIO_RESET          1
+#define KVM_S390_VIRTIO_SET_STATUS     2
+
+#endif
index 5de3efb31445a88f986a1e5480b059088042d520..0bc51d52a899d5b1d07b3bd1dceafa6858a0a3ef 100644 (file)
@@ -381,27 +381,32 @@ struct _lowcore
         /* whether the kernel died with panic() or not */
         __u32        panic_magic;              /* 0xe00 */
 
-       __u8         pad13[0x1200-0xe04];      /* 0xe04 */
+       __u8         pad13[0x11b8-0xe04];      /* 0xe04 */
+
+       /* 64 bit extparam used for pfault, diag 250 etc  */
+       __u64        ext_params2;               /* 0x11B8 */
+
+       __u8         pad14[0x1200-0x11C0];      /* 0x11C0 */
 
         /* System info area */ 
 
        __u64        floating_pt_save_area[16]; /* 0x1200 */
        __u64        gpregs_save_area[16];      /* 0x1280 */
        __u32        st_status_fixed_logout[4]; /* 0x1300 */
-       __u8         pad14[0x1318-0x1310];      /* 0x1310 */
+       __u8         pad15[0x1318-0x1310];      /* 0x1310 */
        __u32        prefixreg_save_area;       /* 0x1318 */
        __u32        fpt_creg_save_area;        /* 0x131c */
-       __u8         pad15[0x1324-0x1320];      /* 0x1320 */
+       __u8         pad16[0x1324-0x1320];      /* 0x1320 */
        __u32        tod_progreg_save_area;     /* 0x1324 */
        __u32        cpu_timer_save_area[2];    /* 0x1328 */
        __u32        clock_comp_save_area[2];   /* 0x1330 */
-       __u8         pad16[0x1340-0x1338];      /* 0x1338 */ 
+       __u8         pad17[0x1340-0x1338];      /* 0x1338 */
        __u32        access_regs_save_area[16]; /* 0x1340 */ 
        __u64        cregs_save_area[16];       /* 0x1380 */
 
        /* align to the top of the prefix area */
 
-       __u8         pad17[0x2000-0x1400];      /* 0x1400 */
+       __u8         pad18[0x2000-0x1400];      /* 0x1400 */
 #endif /* !__s390x__ */
 } __attribute__((packed)); /* End structure*/
 
index 1698e29c5b20fc5b38831bfe0a4b7de80b1487ba..5dd5e7b3476ff1e431fc034f04fe4241a1ea7878 100644 (file)
@@ -7,6 +7,7 @@ typedef struct {
        unsigned long asce_bits;
        unsigned long asce_limit;
        int noexec;
+       int pgstes;
 } mm_context_t;
 
 #endif
index b5a34c6f91a932c0841933c6db88da84ed5a7318..4c2fbf48c9c43fe2fa0a7384bc55c576d6dfc23c 100644 (file)
@@ -20,7 +20,13 @@ static inline int init_new_context(struct task_struct *tsk,
 #ifdef CONFIG_64BIT
        mm->context.asce_bits |= _ASCE_TYPE_REGION3;
 #endif
-       mm->context.noexec = s390_noexec;
+       if (current->mm->context.pgstes) {
+               mm->context.noexec = 0;
+               mm->context.pgstes = 1;
+       } else {
+               mm->context.noexec = s390_noexec;
+               mm->context.pgstes = 0;
+       }
        mm->context.asce_limit = STACK_TOP_MAX;
        crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm));
        return 0;
index 65154dc9a9e538aea84f867c8aab6ac19cdeba3e..4c0698c0dda5f78ce2d6079a8c303408122142bf 100644 (file)
@@ -30,6 +30,7 @@
  */
 #ifndef __ASSEMBLY__
 #include <linux/mm_types.h>
+#include <asm/bitops.h>
 #include <asm/bug.h>
 #include <asm/processor.h>
 
@@ -258,6 +259,13 @@ extern char empty_zero_page[PAGE_SIZE];
  * swap pte is 1011 and 0001, 0011, 0101, 0111 are invalid.
  */
 
+/* Page status table bits for virtualization */
+#define RCP_PCL_BIT    55
+#define RCP_HR_BIT     54
+#define RCP_HC_BIT     53
+#define RCP_GR_BIT     50
+#define RCP_GC_BIT     49
+
 #ifndef __s390x__
 
 /* Bits in the segment table address-space-control-element */
@@ -513,6 +521,48 @@ static inline int pte_file(pte_t pte)
 #define __HAVE_ARCH_PTE_SAME
 #define pte_same(a,b)  (pte_val(a) == pte_val(b))
 
+static inline void rcp_lock(pte_t *ptep)
+{
+#ifdef CONFIG_PGSTE
+       unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
+       preempt_disable();
+       while (test_and_set_bit(RCP_PCL_BIT, pgste))
+               ;
+#endif
+}
+
+static inline void rcp_unlock(pte_t *ptep)
+{
+#ifdef CONFIG_PGSTE
+       unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
+       clear_bit(RCP_PCL_BIT, pgste);
+       preempt_enable();
+#endif
+}
+
+/* forward declaration for SetPageUptodate in page-flags.h*/
+static inline void page_clear_dirty(struct page *page);
+#include <linux/page-flags.h>
+
+static inline void ptep_rcp_copy(pte_t *ptep)
+{
+#ifdef CONFIG_PGSTE
+       struct page *page = virt_to_page(pte_val(*ptep));
+       unsigned int skey;
+       unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
+
+       skey = page_get_storage_key(page_to_phys(page));
+       if (skey & _PAGE_CHANGED)
+               set_bit_simple(RCP_GC_BIT, pgste);
+       if (skey & _PAGE_REFERENCED)
+               set_bit_simple(RCP_GR_BIT, pgste);
+       if (test_and_clear_bit_simple(RCP_HC_BIT, pgste))
+               SetPageDirty(page);
+       if (test_and_clear_bit_simple(RCP_HR_BIT, pgste))
+               SetPageReferenced(page);
+#endif
+}
+
 /*
  * query functions pte_write/pte_dirty/pte_young only work if
  * pte_present() is true. Undefined behaviour if not..
@@ -599,6 +649,8 @@ static inline void pmd_clear(pmd_t *pmd)
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
+       if (mm->context.pgstes)
+               ptep_rcp_copy(ptep);
        pte_val(*ptep) = _PAGE_TYPE_EMPTY;
        if (mm->context.noexec)
                pte_val(ptep[PTRS_PER_PTE]) = _PAGE_TYPE_EMPTY;
@@ -667,6 +719,24 @@ static inline pte_t pte_mkyoung(pte_t pte)
 static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
                                            unsigned long addr, pte_t *ptep)
 {
+#ifdef CONFIG_PGSTE
+       unsigned long physpage;
+       int young;
+       unsigned long *pgste;
+
+       if (!vma->vm_mm->context.pgstes)
+               return 0;
+       physpage = pte_val(*ptep) & PAGE_MASK;
+       pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
+
+       young = ((page_get_storage_key(physpage) & _PAGE_REFERENCED) != 0);
+       rcp_lock(ptep);
+       if (young)
+               set_bit_simple(RCP_GR_BIT, pgste);
+       young |= test_and_clear_bit_simple(RCP_HR_BIT, pgste);
+       rcp_unlock(ptep);
+       return young;
+#endif
        return 0;
 }
 
@@ -674,7 +744,13 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
 static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
                                         unsigned long address, pte_t *ptep)
 {
-       /* No need to flush TLB; bits are in storage key */
+       /* No need to flush TLB
+        * On s390 reference bits are in storage key and never in TLB
+        * With virtualization we handle the reference bit, without we
+        * we can simply return */
+#ifdef CONFIG_PGSTE
+       return ptep_test_and_clear_young(vma, address, ptep);
+#endif
        return 0;
 }
 
@@ -693,15 +769,25 @@ static inline void __ptep_ipte(unsigned long address, pte_t *ptep)
                        : "=m" (*ptep) : "m" (*ptep),
                          "a" (pto), "a" (address));
        }
-       pte_val(*ptep) = _PAGE_TYPE_EMPTY;
 }
 
 static inline void ptep_invalidate(struct mm_struct *mm,
                                   unsigned long address, pte_t *ptep)
 {
+       if (mm->context.pgstes) {
+               rcp_lock(ptep);
+               __ptep_ipte(address, ptep);
+               ptep_rcp_copy(ptep);
+               pte_val(*ptep) = _PAGE_TYPE_EMPTY;
+               rcp_unlock(ptep);
+               return;
+       }
        __ptep_ipte(address, ptep);
-       if (mm->context.noexec)
+       pte_val(*ptep) = _PAGE_TYPE_EMPTY;
+       if (mm->context.noexec) {
                __ptep_ipte(address, ptep + PTRS_PER_PTE);
+               pte_val(*(ptep + PTRS_PER_PTE)) = _PAGE_TYPE_EMPTY;
+       }
 }
 
 /*
@@ -966,6 +1052,7 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
 
 extern int add_shared_memory(unsigned long start, unsigned long size);
 extern int remove_shared_memory(unsigned long start, unsigned long size);
+extern int s390_enable_sie(void);
 
 /*
  * No page table caches to initialise
index a76a6b8fd887e259a62681053f058c850c3b54d4..aaf4b518b940870701e409f2d9816cc9fcc757f7 100644 (file)
@@ -62,6 +62,7 @@ extern unsigned long machine_flags;
 #define MACHINE_IS_VM          (machine_flags & 1)
 #define MACHINE_IS_P390                (machine_flags & 4)
 #define MACHINE_HAS_MVPG       (machine_flags & 16)
+#define MACHINE_IS_KVM         (machine_flags & 64)
 #define MACHINE_HAS_IDTE       (machine_flags & 128)
 #define MACHINE_HAS_DIAG9C     (machine_flags & 256)
 
index b6ba5a60dec217b4b7f4421db7cc8e402c2e15d4..d7d382f63ee53a5c6a59a7033169ba6bc366cb8f 100644 (file)
@@ -95,6 +95,7 @@ static inline unsigned long ffz(unsigned long word)
 #include <asm-generic/bitops/ext2-atomic.h>
 #include <asm-generic/bitops/minix.h>
 #include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 
 #endif /* __KERNEL__ */
index 982ce8992b91fcae6a2d9e790235b718d7cfa1b1..11f9d8146cdff0823500641bacde73d97c33151f 100644 (file)
@@ -34,6 +34,7 @@ extern void change_bit(unsigned long nr, volatile unsigned long *addr);
 #include <asm-generic/bitops/ffz.h>
 #include <asm-generic/bitops/__ffs.h>
 #include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 
 #ifdef __KERNEL__
index 9cbd9a668af814ca81a870e93edb3c70a2da1161..b4a46b7be7941fca2a7cd8636d9701bbf9ed7aa4 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _MACH_BIOS_EBDA_H
 #define _MACH_BIOS_EBDA_H
 
+#include <asm/io.h>
+
 /*
  * there is a real-mode segmented pointer pointing to the
  * 4K EBDA area at 0x40E.
index 1ae7b270a1efe8d1cc9abe8c4260d54d714ecc0f..b81a4d4d333787e4c9e8b69cb74fd190f09c4e69 100644 (file)
@@ -62,12 +62,9 @@ static inline void set_bit(int nr, volatile void *addr)
  */
 static inline void __set_bit(int nr, volatile void *addr)
 {
-       asm volatile("bts %1,%0"
-                    : ADDR
-                    : "Ir" (nr) : "memory");
+       asm volatile("bts %1,%0" : ADDR : "Ir" (nr) : "memory");
 }
 
-
 /**
  * clear_bit - Clears a bit in memory
  * @nr: Bit to clear
@@ -297,19 +294,145 @@ static inline int variable_test_bit(int nr, volatile const void *addr)
 static int test_bit(int nr, const volatile unsigned long *addr);
 #endif
 
-#define test_bit(nr,addr)                      \
-       (__builtin_constant_p(nr) ?             \
-        constant_test_bit((nr),(addr)) :       \
-        variable_test_bit((nr),(addr)))
+#define test_bit(nr, addr)                     \
+       (__builtin_constant_p((nr))             \
+        ? constant_test_bit((nr), (addr))      \
+        : variable_test_bit((nr), (addr)))
+
+/**
+ * __ffs - find first set bit in word
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static inline unsigned long __ffs(unsigned long word)
+{
+       asm("bsf %1,%0"
+               : "=r" (word)
+               : "rm" (word));
+       return word;
+}
+
+/**
+ * ffz - find first zero bit in word
+ * @word: The word to search
+ *
+ * Undefined if no zero exists, so code should check against ~0UL first.
+ */
+static inline unsigned long ffz(unsigned long word)
+{
+       asm("bsf %1,%0"
+               : "=r" (word)
+               : "r" (~word));
+       return word;
+}
+
+/*
+ * __fls: find last set bit in word
+ * @word: The word to search
+ *
+ * Undefined if no zero exists, so code should check against ~0UL first.
+ */
+static inline unsigned long __fls(unsigned long word)
+{
+       asm("bsr %1,%0"
+           : "=r" (word)
+           : "rm" (word));
+       return word;
+}
+
+#ifdef __KERNEL__
+/**
+ * ffs - find first set bit in word
+ * @x: the word to search
+ *
+ * This is defined the same way as the libc and compiler builtin ffs
+ * routines, therefore differs in spirit from the other bitops.
+ *
+ * ffs(value) returns 0 if value is 0 or the position of the first
+ * set bit if value is nonzero. The first (least significant) bit
+ * is at position 1.
+ */
+static inline int ffs(int x)
+{
+       int r;
+#ifdef CONFIG_X86_CMOV
+       asm("bsfl %1,%0\n\t"
+           "cmovzl %2,%0"
+           : "=r" (r) : "rm" (x), "r" (-1));
+#else
+       asm("bsfl %1,%0\n\t"
+           "jnz 1f\n\t"
+           "movl $-1,%0\n"
+           "1:" : "=r" (r) : "rm" (x));
+#endif
+       return r + 1;
+}
+
+/**
+ * fls - find last set bit in word
+ * @x: the word to search
+ *
+ * This is defined in a similar way as the libc and compiler builtin
+ * ffs, but returns the position of the most significant set bit.
+ *
+ * fls(value) returns 0 if value is 0 or the position of the last
+ * set bit if value is nonzero. The last (most significant) bit is
+ * at position 32.
+ */
+static inline int fls(int x)
+{
+       int r;
+#ifdef CONFIG_X86_CMOV
+       asm("bsrl %1,%0\n\t"
+           "cmovzl %2,%0"
+           : "=&r" (r) : "rm" (x), "rm" (-1));
+#else
+       asm("bsrl %1,%0\n\t"
+           "jnz 1f\n\t"
+           "movl $-1,%0\n"
+           "1:" : "=r" (r) : "rm" (x));
+#endif
+       return r + 1;
+}
+#endif /* __KERNEL__ */
 
 #undef BASE_ADDR
 #undef BIT_ADDR
 #undef ADDR
 
-#ifdef CONFIG_X86_32
-# include "bitops_32.h"
-#else
-# include "bitops_64.h"
-#endif
+static inline void set_bit_string(unsigned long *bitmap,
+               unsigned long i, int len)
+{
+       unsigned long end = i + len;
+       while (i < end) {
+               __set_bit(i, bitmap);
+               i++;
+       }
+}
+
+#ifdef __KERNEL__
+
+#include <asm-generic/bitops/sched.h>
+
+#define ARCH_HAS_FAST_MULTIPLIER 1
+
+#include <asm-generic/bitops/hweight.h>
+
+#endif /* __KERNEL__ */
+
+#include <asm-generic/bitops/fls64.h>
+
+#ifdef __KERNEL__
+
+#include <asm-generic/bitops/ext2-non-atomic.h>
+
+#define ext2_set_bit_atomic(lock, nr, addr)                    \
+       test_and_set_bit((nr), (unsigned long *)(addr))
+#define ext2_clear_bit_atomic(lock, nr, addr)                  \
+       test_and_clear_bit((nr), (unsigned long *)(addr))
+
+#include <asm-generic/bitops/minix.h>
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_X86_BITOPS_H */
diff --git a/include/asm-x86/bitops_32.h b/include/asm-x86/bitops_32.h
deleted file mode 100644 (file)
index 2513a81..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-#ifndef _I386_BITOPS_H
-#define _I386_BITOPS_H
-
-/*
- * Copyright 1992, Linus Torvalds.
- */
-
-/**
- * find_first_zero_bit - find the first zero bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit number of the first zero bit, not the number of the byte
- * containing a bit.
- */
-static inline int find_first_zero_bit(const unsigned long *addr, unsigned size)
-{
-       int d0, d1, d2;
-       int res;
-
-       if (!size)
-               return 0;
-       /* This looks at memory.
-        * Mark it volatile to tell gcc not to move it around
-        */
-       asm volatile("movl $-1,%%eax\n\t"
-                    "xorl %%edx,%%edx\n\t"
-                    "repe; scasl\n\t"
-                    "je 1f\n\t"
-                    "xorl -4(%%edi),%%eax\n\t"
-                    "subl $4,%%edi\n\t"
-                    "bsfl %%eax,%%edx\n"
-                    "1:\tsubl %%ebx,%%edi\n\t"
-                    "shll $3,%%edi\n\t"
-                    "addl %%edi,%%edx"
-                    : "=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
-                    : "1" ((size + 31) >> 5), "2" (addr),
-                      "b" (addr) : "memory");
-       return res;
-}
-
-/**
- * find_next_zero_bit - find the first zero bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bit number to start searching at
- * @size: The maximum size to search
- */
-int find_next_zero_bit(const unsigned long *addr, int size, int offset);
-
-/**
- * __ffs - find first bit in word.
- * @word: The word to search
- *
- * Undefined if no bit exists, so code should check against 0 first.
- */
-static inline unsigned long __ffs(unsigned long word)
-{
-       __asm__("bsfl %1,%0"
-               :"=r" (word)
-               :"rm" (word));
-       return word;
-}
-
-/**
- * find_first_bit - find the first set bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit number of the first set bit, not the number of the byte
- * containing a bit.
- */
-static inline unsigned find_first_bit(const unsigned long *addr, unsigned size)
-{
-       unsigned x = 0;
-
-       while (x < size) {
-               unsigned long val = *addr++;
-               if (val)
-                       return __ffs(val) + x;
-               x += sizeof(*addr) << 3;
-       }
-       return x;
-}
-
-/**
- * find_next_bit - find the first set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bit number to start searching at
- * @size: The maximum size to search
- */
-int find_next_bit(const unsigned long *addr, int size, int offset);
-
-/**
- * ffz - find first zero in word.
- * @word: The word to search
- *
- * Undefined if no zero exists, so code should check against ~0UL first.
- */
-static inline unsigned long ffz(unsigned long word)
-{
-       __asm__("bsfl %1,%0"
-               :"=r" (word)
-               :"r" (~word));
-       return word;
-}
-
-#ifdef __KERNEL__
-
-#include <asm-generic/bitops/sched.h>
-
-/**
- * ffs - find first bit set
- * @x: the word to search
- *
- * This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz() (man ffs).
- */
-static inline int ffs(int x)
-{
-       int r;
-
-       __asm__("bsfl %1,%0\n\t"
-               "jnz 1f\n\t"
-               "movl $-1,%0\n"
-               "1:" : "=r" (r) : "rm" (x));
-       return r+1;
-}
-
-/**
- * fls - find last bit set
- * @x: the word to search
- *
- * This is defined the same way as ffs().
- */
-static inline int fls(int x)
-{
-       int r;
-
-       __asm__("bsrl %1,%0\n\t"
-               "jnz 1f\n\t"
-               "movl $-1,%0\n"
-               "1:" : "=r" (r) : "rm" (x));
-       return r+1;
-}
-
-#include <asm-generic/bitops/hweight.h>
-
-#endif /* __KERNEL__ */
-
-#include <asm-generic/bitops/fls64.h>
-
-#ifdef __KERNEL__
-
-#include <asm-generic/bitops/ext2-non-atomic.h>
-
-#define ext2_set_bit_atomic(lock, nr, addr)                    \
-       test_and_set_bit((nr), (unsigned long *)(addr))
-#define ext2_clear_bit_atomic(lock, nr, addr)                  \
-       test_and_clear_bit((nr), (unsigned long *)(addr))
-
-#include <asm-generic/bitops/minix.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* _I386_BITOPS_H */
diff --git a/include/asm-x86/bitops_64.h b/include/asm-x86/bitops_64.h
deleted file mode 100644 (file)
index 365f820..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-#ifndef _X86_64_BITOPS_H
-#define _X86_64_BITOPS_H
-
-/*
- * Copyright 1992, Linus Torvalds.
- */
-
-extern long find_first_zero_bit(const unsigned long *addr, unsigned long size);
-extern long find_next_zero_bit(const unsigned long *addr, long size, long offset);
-extern long find_first_bit(const unsigned long *addr, unsigned long size);
-extern long find_next_bit(const unsigned long *addr, long size, long offset);
-
-/* return index of first bet set in val or max when no bit is set */
-static inline long __scanbit(unsigned long val, unsigned long max)
-{
-       asm("bsfq %1,%0 ; cmovz %2,%0" : "=&r" (val) : "r" (val), "r" (max));
-       return val;
-}
-
-#define find_next_bit(addr,size,off) \
-((__builtin_constant_p(size) && (size) <= BITS_PER_LONG ?        \
-  ((off) + (__scanbit((*(unsigned long *)addr) >> (off),(size)-(off)))) : \
-       find_next_bit(addr,size,off)))
-
-#define find_next_zero_bit(addr,size,off) \
-((__builtin_constant_p(size) && (size) <= BITS_PER_LONG ?        \
-  ((off)+(__scanbit(~(((*(unsigned long *)addr)) >> (off)),(size)-(off)))) : \
-       find_next_zero_bit(addr,size,off)))
-
-#define find_first_bit(addr, size)                                     \
-       ((__builtin_constant_p((size)) && (size) <= BITS_PER_LONG       \
-         ? (__scanbit(*(unsigned long *)(addr), (size)))               \
-         : find_first_bit((addr), (size))))
-
-#define find_first_zero_bit(addr, size)                                        \
-       ((__builtin_constant_p((size)) && (size) <= BITS_PER_LONG       \
-         ? (__scanbit(~*(unsigned long *)(addr), (size)))              \
-         : find_first_zero_bit((addr), (size))))
-
-static inline void set_bit_string(unsigned long *bitmap, unsigned long i,
-                                 int len)
-{
-       unsigned long end = i + len;
-       while (i < end) {
-               __set_bit(i, bitmap);
-               i++;
-       }
-}
-
-/**
- * ffz - find first zero in word.
- * @word: The word to search
- *
- * Undefined if no zero exists, so code should check against ~0UL first.
- */
-static inline unsigned long ffz(unsigned long word)
-{
-       __asm__("bsfq %1,%0"
-               :"=r" (word)
-               :"r" (~word));
-       return word;
-}
-
-/**
- * __ffs - find first bit in word.
- * @word: The word to search
- *
- * Undefined if no bit exists, so code should check against 0 first.
- */
-static inline unsigned long __ffs(unsigned long word)
-{
-       __asm__("bsfq %1,%0"
-               :"=r" (word)
-               :"rm" (word));
-       return word;
-}
-
-/*
- * __fls: find last bit set.
- * @word: The word to search
- *
- * Undefined if no zero exists, so code should check against ~0UL first.
- */
-static inline unsigned long __fls(unsigned long word)
-{
-       __asm__("bsrq %1,%0"
-               :"=r" (word)
-               :"rm" (word));
-       return word;
-}
-
-#ifdef __KERNEL__
-
-#include <asm-generic/bitops/sched.h>
-
-/**
- * ffs - find first bit set
- * @x: the word to search
- *
- * This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
-static inline int ffs(int x)
-{
-       int r;
-
-       __asm__("bsfl %1,%0\n\t"
-               "cmovzl %2,%0" 
-               : "=r" (r) : "rm" (x), "r" (-1));
-       return r+1;
-}
-
-/**
- * fls64 - find last bit set in 64 bit word
- * @x: the word to search
- *
- * This is defined the same way as fls.
- */
-static inline int fls64(__u64 x)
-{
-       if (x == 0)
-               return 0;
-       return __fls(x) + 1;
-}
-
-/**
- * fls - find last bit set
- * @x: the word to search
- *
- * This is defined the same way as ffs.
- */
-static inline int fls(int x)
-{
-       int r;
-
-       __asm__("bsrl %1,%0\n\t"
-               "cmovzl %2,%0"
-               : "=&r" (r) : "rm" (x), "rm" (-1));
-       return r+1;
-}
-
-#define ARCH_HAS_FAST_MULTIPLIER 1
-
-#include <asm-generic/bitops/hweight.h>
-
-#endif /* __KERNEL__ */
-
-#ifdef __KERNEL__
-
-#include <asm-generic/bitops/ext2-non-atomic.h>
-
-#define ext2_set_bit_atomic(lock, nr, addr)                    \
-       test_and_set_bit((nr), (unsigned long *)(addr))
-#define ext2_clear_bit_atomic(lock, nr, addr)                  \
-       test_and_clear_bit((nr), (unsigned long *)(addr))
-
-#include <asm-generic/bitops/minix.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* _X86_64_BITOPS_H */
index 51151356840fcd5e099c84bb4c7e1ab623d47e77..e8659909e5f69a93dc781402fc5cf5db9df95c75 100644 (file)
@@ -9,6 +9,17 @@
 #include <asm/ist.h>
 #include <video/edid.h>
 
+/* setup data types */
+#define SETUP_NONE                     0
+
+/* extensible setup data list node */
+struct setup_data {
+       u64 next;
+       u32 type;
+       u32 len;
+       u8 data[0];
+};
+
 struct setup_header {
        __u8    setup_sects;
        __u16   root_flags;
@@ -46,6 +57,9 @@ struct setup_header {
        __u32   cmdline_size;
        __u32   hardware_subarch;
        __u64   hardware_subarch_data;
+       __u32   payload_offset;
+       __u32   payload_length;
+       __u64   setup_data;
 } __attribute__((packed));
 
 struct sys_desc_table {
index f478c57eb06033b32d673b13021db1c516e5721e..71c4d685d30d894ad1d1700bdbde2ea468f3e8d3 100644 (file)
@@ -48,7 +48,8 @@ extern struct e820map e820;
 extern void update_e820(void);
 
 extern void reserve_early(unsigned long start, unsigned long end, char *name);
-extern void early_res_to_bootmem(void);
+extern void free_early(unsigned long start, unsigned long end);
+extern void early_res_to_bootmem(unsigned long start, unsigned long end);
 
 #endif/*!__ASSEMBLY__*/
 
index 382eb271a89203cc2439fe8a1fb4b38250725648..5bd206973dca3cf184b859a1c2031ce6d3501ff3 100644 (file)
@@ -1,5 +1,13 @@
+#ifndef _ASM_FIXMAP_H
+#define _ASM_FIXMAP_H
+
 #ifdef CONFIG_X86_32
 # include "fixmap_32.h"
 #else
 # include "fixmap_64.h"
 #endif
+
+#define clear_fixmap(idx)                      \
+       __set_fixmap(idx, 0, __pgprot(0))
+
+#endif
index eb1665125c443fac0cb1a474b2d7ae4d4c76f4de..4b96148e90c15587f715969f2ff4c6fd5a07d4d8 100644 (file)
@@ -10,8 +10,8 @@
  * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
  */
 
-#ifndef _ASM_FIXMAP_H
-#define _ASM_FIXMAP_H
+#ifndef _ASM_FIXMAP_32_H
+#define _ASM_FIXMAP_32_H
 
 
 /* used by vmalloc.c, vsyscall.lds.S.
@@ -121,9 +121,6 @@ extern void reserve_top_address(unsigned long reserve);
 #define set_fixmap_nocache(idx, phys)                  \
        __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
 
-#define clear_fixmap(idx)                      \
-       __set_fixmap(idx, 0, __pgprot(0))
-
 #define FIXADDR_TOP    ((unsigned long)__FIXADDR_TOP)
 
 #define __FIXADDR_SIZE (__end_of_permanent_fixed_addresses << PAGE_SHIFT)
index f3d76858c0e6f4b5c380736a1db9b79afcc4242f..355d26a75a821a87aa298ee52f79617015dc7a8e 100644 (file)
@@ -8,8 +8,8 @@
  * Copyright (C) 1998 Ingo Molnar
  */
 
-#ifndef _ASM_FIXMAP_H
-#define _ASM_FIXMAP_H
+#ifndef _ASM_FIXMAP_64_H
+#define _ASM_FIXMAP_64_H
 
 #include <linux/kernel.h>
 #include <asm/apicdef.h>
index 7b292d386713ee0466f882a8e637413ca0da826b..d5b11f60dbd073d9ae56efe67f38b3d03ba9ba5b 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef _ASM_X86_IO_H
+#define _ASM_X86_IO_H
+
 #define ARCH_HAS_IOREMAP_WC
 
 #ifdef CONFIG_X86_32
@@ -5,7 +8,12 @@
 #else
 # include "io_64.h"
 #endif
+
+extern void *xlate_dev_mem_ptr(unsigned long phys);
+extern void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
+
 extern int ioremap_change_attr(unsigned long vaddr, unsigned long size,
                                unsigned long prot_val);
 extern void __iomem *ioremap_wc(unsigned long offset, unsigned long size);
 
+#endif /* _ASM_X86_IO_H */
index 509045f5fda29ecc4b4216ff0e2d0825695f34d9..6e73467a4fb13783ba21a73108e238e8e4e35fe7 100644 (file)
 
 #include <linux/vmalloc.h>
 
-/*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * access
- */
-#define xlate_dev_mem_ptr(p)   __va(p)
-
 /*
  * Convert a virtual cached pointer to an uncached pointer
  */
index c2f5eef47b888568b0af823359b0a84a2fcce160..0930bedf9e4d0ca4636a50d766368106ddf4d3ab 100644 (file)
@@ -307,12 +307,6 @@ void memset_io(volatile void __iomem *a, int b, size_t c);
 extern int iommu_bio_merge;
 #define BIO_VMERGE_BOUNDARY iommu_bio_merge
 
-/*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * access
- */
-#define xlate_dev_mem_ptr(p)   __va(p)
-
 /*
  * Convert a virtual cached pointer to an uncached pointer
  */
index 0c9e17c73e05b9da8654199a184c003e5d957e45..d593e14f03411df3797562d4e01ed318b00efdc2 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __ASM_IO_APIC_H
 #define __ASM_IO_APIC_H
 
-#include <asm/types.h>
+#include <linux/types.h>
 #include <asm/mpspec.h>
 #include <asm/apicdef.h>
 
@@ -110,11 +110,13 @@ extern int nr_ioapic_registers[MAX_IO_APICS];
  * MP-BIOS irq configuration table structures:
  */
 
+#define MP_MAX_IOAPIC_PIN 127
+
 struct mp_ioapic_routing {
        int apic_id;
        int gsi_base;
        int gsi_end;
-       u32 pin_programmed[4];
+       DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
 };
 
 /* I/O APIC entries */
index 7a71120426a354155d377e3f7f952d92c4300862..80eefef2cc76cd3b54ba93856a8fc500f639d736 100644 (file)
@@ -188,4 +188,45 @@ struct kvm_cpuid2 {
        struct kvm_cpuid_entry2 entries[0];
 };
 
+/* for KVM_GET_PIT and KVM_SET_PIT */
+struct kvm_pit_channel_state {
+       __u32 count; /* can be 65536 */
+       __u16 latched_count;
+       __u8 count_latched;
+       __u8 status_latched;
+       __u8 status;
+       __u8 read_state;
+       __u8 write_state;
+       __u8 write_latch;
+       __u8 rw_mode;
+       __u8 mode;
+       __u8 bcd;
+       __u8 gate;
+       __s64 count_load_time;
+};
+
+struct kvm_pit_state {
+       struct kvm_pit_channel_state channels[3];
+};
+
+#define KVM_TRC_INJ_VIRQ         (KVM_TRC_HANDLER + 0x02)
+#define KVM_TRC_REDELIVER_EVT    (KVM_TRC_HANDLER + 0x03)
+#define KVM_TRC_PEND_INTR        (KVM_TRC_HANDLER + 0x04)
+#define KVM_TRC_IO_READ          (KVM_TRC_HANDLER + 0x05)
+#define KVM_TRC_IO_WRITE         (KVM_TRC_HANDLER + 0x06)
+#define KVM_TRC_CR_READ          (KVM_TRC_HANDLER + 0x07)
+#define KVM_TRC_CR_WRITE         (KVM_TRC_HANDLER + 0x08)
+#define KVM_TRC_DR_READ          (KVM_TRC_HANDLER + 0x09)
+#define KVM_TRC_DR_WRITE         (KVM_TRC_HANDLER + 0x0A)
+#define KVM_TRC_MSR_READ         (KVM_TRC_HANDLER + 0x0B)
+#define KVM_TRC_MSR_WRITE        (KVM_TRC_HANDLER + 0x0C)
+#define KVM_TRC_CPUID            (KVM_TRC_HANDLER + 0x0D)
+#define KVM_TRC_INTR             (KVM_TRC_HANDLER + 0x0E)
+#define KVM_TRC_NMI              (KVM_TRC_HANDLER + 0x0F)
+#define KVM_TRC_VMMCALL          (KVM_TRC_HANDLER + 0x10)
+#define KVM_TRC_HLT              (KVM_TRC_HANDLER + 0x11)
+#define KVM_TRC_CLTS             (KVM_TRC_HANDLER + 0x12)
+#define KVM_TRC_LMSW             (KVM_TRC_HANDLER + 0x13)
+#define KVM_TRC_APIC_ACCESS      (KVM_TRC_HANDLER + 0x14)
+
 #endif
index 68ee390b2844024eac9beb1444790870cc628483..9d963cd6533c5d7541b71dac204d3debf524f685 100644 (file)
 
 #include <asm/desc.h>
 
+#define KVM_MAX_VCPUS 16
+#define KVM_MEMORY_SLOTS 32
+/* memory slots that does not exposed to userspace */
+#define KVM_PRIVATE_MEM_SLOTS 4
+
+#define KVM_PIO_PAGE_OFFSET 1
+
 #define CR3_PAE_RESERVED_BITS ((X86_CR3_PWT | X86_CR3_PCD) - 1)
 #define CR3_NONPAE_RESERVED_BITS ((PAGE_SIZE-1) & ~(X86_CR3_PWT | X86_CR3_PCD))
 #define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS |   \
 #define INVALID_PAGE (~(hpa_t)0)
 #define UNMAPPED_GVA (~(gpa_t)0)
 
+/* shadow tables are PAE even on non-PAE hosts */
+#define KVM_HPAGE_SHIFT 21
+#define KVM_HPAGE_SIZE (1UL << KVM_HPAGE_SHIFT)
+#define KVM_HPAGE_MASK (~(KVM_HPAGE_SIZE - 1))
+
+#define KVM_PAGES_PER_HPAGE (KVM_HPAGE_SIZE / PAGE_SIZE)
+
 #define DE_VECTOR 0
 #define UD_VECTOR 6
 #define NM_VECTOR 7
@@ -48,6 +62,7 @@
 #define SS_VECTOR 12
 #define GP_VECTOR 13
 #define PF_VECTOR 14
+#define MC_VECTOR 18
 
 #define SELECTOR_TI_MASK (1 << 2)
 #define SELECTOR_RPL_MASK 0x03
@@ -58,7 +73,8 @@
 
 #define KVM_PERMILLE_MMU_PAGES 20
 #define KVM_MIN_ALLOC_MMU_PAGES 64
-#define KVM_NUM_MMU_PAGES 1024
+#define KVM_MMU_HASH_SHIFT 10
+#define KVM_NUM_MMU_PAGES (1 << KVM_MMU_HASH_SHIFT)
 #define KVM_MIN_FREE_MMU_PAGES 5
 #define KVM_REFILL_PAGES 25
 #define KVM_MAX_CPUID_ENTRIES 40
@@ -106,6 +122,12 @@ enum {
 
 #define KVM_NR_MEM_OBJS 40
 
+struct kvm_guest_debug {
+       int enabled;
+       unsigned long bp[4];
+       int singlestep;
+};
+
 /*
  * We don't want allocation failures within the mmu code, so we preallocate
  * enough memory for a single page fault in a cache.
@@ -140,6 +162,7 @@ union kvm_mmu_page_role {
                unsigned pad_for_nice_hex_output:6;
                unsigned metaphysical:1;
                unsigned access:3;
+               unsigned invalid:1;
        };
 };
 
@@ -204,11 +227,6 @@ struct kvm_vcpu_arch {
        u64 shadow_efer;
        u64 apic_base;
        struct kvm_lapic *apic;    /* kernel irqchip context */
-#define VCPU_MP_STATE_RUNNABLE          0
-#define VCPU_MP_STATE_UNINITIALIZED     1
-#define VCPU_MP_STATE_INIT_RECEIVED     2
-#define VCPU_MP_STATE_SIPI_RECEIVED     3
-#define VCPU_MP_STATE_HALTED            4
        int mp_state;
        int sipi_vector;
        u64 ia32_misc_enable_msr;
@@ -226,8 +244,9 @@ struct kvm_vcpu_arch {
        u64  *last_pte_updated;
 
        struct {
-               gfn_t gfn;          /* presumed gfn during guest pte update */
-               struct page *page;  /* page corresponding to that gfn */
+               gfn_t gfn;      /* presumed gfn during guest pte update */
+               pfn_t pfn;      /* pfn corresponding to that gfn */
+               int largepage;
        } update_pte;
 
        struct i387_fxsave_struct host_fx_image;
@@ -261,6 +280,11 @@ struct kvm_vcpu_arch {
        /* emulate context */
 
        struct x86_emulate_ctxt emulate_ctxt;
+
+       gpa_t time;
+       struct kvm_vcpu_time_info hv_clock;
+       unsigned int time_offset;
+       struct page *time_page;
 };
 
 struct kvm_mem_alias {
@@ -283,10 +307,13 @@ struct kvm_arch{
        struct list_head active_mmu_pages;
        struct kvm_pic *vpic;
        struct kvm_ioapic *vioapic;
+       struct kvm_pit *vpit;
 
        int round_robin_prev_vcpu;
        unsigned int tss_addr;
        struct page *apic_access_page;
+
+       gpa_t wall_clock;
 };
 
 struct kvm_vm_stat {
@@ -298,6 +325,7 @@ struct kvm_vm_stat {
        u32 mmu_recycled;
        u32 mmu_cache_miss;
        u32 remote_tlb_flush;
+       u32 lpages;
 };
 
 struct kvm_vcpu_stat {
@@ -320,6 +348,7 @@ struct kvm_vcpu_stat {
        u32 fpu_reload;
        u32 insn_emulation;
        u32 insn_emulation_fail;
+       u32 hypercalls;
 };
 
 struct descriptor_table {
@@ -355,6 +384,7 @@ struct kvm_x86_ops {
        u64 (*get_segment_base)(struct kvm_vcpu *vcpu, int seg);
        void (*get_segment)(struct kvm_vcpu *vcpu,
                            struct kvm_segment *var, int seg);
+       int (*get_cpl)(struct kvm_vcpu *vcpu);
        void (*set_segment)(struct kvm_vcpu *vcpu,
                            struct kvm_segment *var, int seg);
        void (*get_cs_db_l_bits)(struct kvm_vcpu *vcpu, int *db, int *l);
@@ -410,6 +440,15 @@ void kvm_mmu_zap_all(struct kvm *kvm);
 unsigned int kvm_mmu_calculate_mmu_pages(struct kvm *kvm);
 void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int kvm_nr_mmu_pages);
 
+int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3);
+
+int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
+                         const void *val, int bytes);
+int kvm_pv_mmu_op(struct kvm_vcpu *vcpu, unsigned long bytes,
+                 gpa_t addr, unsigned long *ret);
+
+extern bool tdp_enabled;
+
 enum emulation_result {
        EMULATE_DONE,       /* no further processing */
        EMULATE_DO_MMIO,      /* kvm_run filled with mmio request */
@@ -429,6 +468,7 @@ void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw,
 unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr);
 void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long value,
                     unsigned long *rflags);
+void kvm_enable_efer_bits(u64);
 int kvm_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *data);
 int kvm_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data);
 
@@ -448,12 +488,14 @@ int emulator_get_dr(struct x86_emulate_ctxt *ctxt, int dr,
 int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr,
                    unsigned long value);
 
-void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
-void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr0);
-void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr0);
-void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr0);
-unsigned long get_cr8(struct kvm_vcpu *vcpu);
-void lmsw(struct kvm_vcpu *vcpu, unsigned long msw);
+int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason);
+
+void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
+void kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3);
+void kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
+void kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8);
+unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu);
+void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw);
 void kvm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l);
 
 int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata);
@@ -491,6 +533,8 @@ int kvm_fix_hypercall(struct kvm_vcpu *vcpu);
 
 int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, u32 error_code);
 
+void kvm_enable_tdp(void);
+
 int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3);
 int complete_pio(struct kvm_vcpu *vcpu);
 
@@ -600,6 +644,7 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code)
 #define ASM_VMX_VMWRITE_RSP_RDX   ".byte 0x0f, 0x79, 0xd4"
 #define ASM_VMX_VMXOFF            ".byte 0x0f, 0x01, 0xc4"
 #define ASM_VMX_VMXON_RAX         ".byte 0xf3, 0x0f, 0xc7, 0x30"
+#define ASM_VMX_INVVPID                  ".byte 0x66, 0x0f, 0x38, 0x81, 0x08"
 
 #define MSR_IA32_TIME_STAMP_COUNTER            0x010
 
@@ -610,4 +655,30 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code)
 #define RMODE_TSS_SIZE                                                 \
        (TSS_BASE_SIZE + TSS_REDIRECTION_SIZE + TSS_IOPB_SIZE + 1)
 
+enum {
+       TASK_SWITCH_CALL = 0,
+       TASK_SWITCH_IRET = 1,
+       TASK_SWITCH_JMP = 2,
+       TASK_SWITCH_GATE = 3,
+};
+
+#define KVMTRACE_5D(evt, vcpu, d1, d2, d3, d4, d5, name) \
+       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
+                                               vcpu, 5, d1, d2, d3, d4, d5)
+#define KVMTRACE_4D(evt, vcpu, d1, d2, d3, d4, name) \
+       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
+                                               vcpu, 4, d1, d2, d3, d4, 0)
+#define KVMTRACE_3D(evt, vcpu, d1, d2, d3, name) \
+       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
+                                               vcpu, 3, d1, d2, d3, 0, 0)
+#define KVMTRACE_2D(evt, vcpu, d1, d2, name) \
+       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
+                                               vcpu, 2, d1, d2, 0, 0, 0)
+#define KVMTRACE_1D(evt, vcpu, d1, name) \
+       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
+                                               vcpu, 1, d1, 0, 0, 0, 0)
+#define KVMTRACE_0D(evt, vcpu, name) \
+       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
+                                               vcpu, 0, 0, 0, 0, 0, 0)
+
 #endif
index c6f3fd8d8c5350956b07764551c365f1f3b450b3..5098459420705ea53f41c2d05b0a91b688980334 100644 (file)
  * paravirtualization, the appropriate feature bit should be checked.
  */
 #define KVM_CPUID_FEATURES     0x40000001
+#define KVM_FEATURE_CLOCKSOURCE                0
+#define KVM_FEATURE_NOP_IO_DELAY       1
+#define KVM_FEATURE_MMU_OP             2
+
+#define MSR_KVM_WALL_CLOCK  0x11
+#define MSR_KVM_SYSTEM_TIME 0x12
+
+#define KVM_MAX_MMU_OP_BATCH           32
+
+/* Operations for KVM_HC_MMU_OP */
+#define KVM_MMU_OP_WRITE_PTE            1
+#define KVM_MMU_OP_FLUSH_TLB           2
+#define KVM_MMU_OP_RELEASE_PT          3
+
+/* Payload for KVM_HC_MMU_OP */
+struct kvm_mmu_op_header {
+       __u32 op;
+       __u32 pad;
+};
+
+struct kvm_mmu_op_write_pte {
+       struct kvm_mmu_op_header header;
+       __u64 pte_phys;
+       __u64 pte_val;
+};
+
+struct kvm_mmu_op_flush_tlb {
+       struct kvm_mmu_op_header header;
+};
+
+struct kvm_mmu_op_release_pt {
+       struct kvm_mmu_op_header header;
+       __u64 pt_phys;
+};
 
 #ifdef __KERNEL__
 #include <asm/processor.h>
 
+/* xen binary-compatible interface. See xen headers for details */
+struct kvm_vcpu_time_info {
+       uint32_t version;
+       uint32_t pad0;
+       uint64_t tsc_timestamp;
+       uint64_t system_time;
+       uint32_t tsc_to_system_mul;
+       int8_t   tsc_shift;
+       int8_t   pad[3];
+} __attribute__((__packed__)); /* 32 bytes */
+
+struct kvm_wall_clock {
+       uint32_t wc_version;
+       uint32_t wc_sec;
+       uint32_t wc_nsec;
+} __attribute__((__packed__));
+
+
+extern void kvmclock_init(void);
+
+
 /* This instruction is vmcall.  On non-VT architectures, it will generate a
  * trap that we will then rewrite to the appropriate instruction.
  */
index 3ff2c5bff93a6c0bd014f538ec41c85b1d31691f..56d0e1fa025895d1af57588e22a44820ec08a59e 100644 (file)
@@ -33,7 +33,7 @@ static inline void smpboot_restore_warm_reset_vector(void)
        *((volatile long *) phys_to_virt(0x467)) = 0;
 }
 
-static inline void smpboot_setup_io_apic(void)
+static inline void __init smpboot_setup_io_apic(void)
 {
        /*
         * Here we can be sure that there is an IO-APIC in the system. Let's
index 6724a4bc6b7aee2953bbf65493c35d87939a8063..b381f4a5a0bd90fc0e75268f5ee743b56ff1d3dd 100644 (file)
@@ -47,6 +47,7 @@
 #ifndef __ASSEMBLY__
 
 extern int page_is_ram(unsigned long pagenr);
+extern int devmem_is_allowed(unsigned long pagenr);
 
 extern unsigned long max_pfn_mapped;
 
index 3d419398499b4a6fe14de3eec92761f2e80ba19a..0f13b945e2400323cb65dfd6f8a7cc5b035c3319 100644 (file)
@@ -220,11 +220,13 @@ struct pv_mmu_ops {
                                 unsigned long va);
 
        /* Hooks for allocating/releasing pagetable pages */
-       void (*alloc_pt)(struct mm_struct *mm, u32 pfn);
-       void (*alloc_pd)(struct mm_struct *mm, u32 pfn);
-       void (*alloc_pd_clone)(u32 pfn, u32 clonepfn, u32 start, u32 count);
-       void (*release_pt)(u32 pfn);
-       void (*release_pd)(u32 pfn);
+       void (*alloc_pte)(struct mm_struct *mm, u32 pfn);
+       void (*alloc_pmd)(struct mm_struct *mm, u32 pfn);
+       void (*alloc_pmd_clone)(u32 pfn, u32 clonepfn, u32 start, u32 count);
+       void (*alloc_pud)(struct mm_struct *mm, u32 pfn);
+       void (*release_pte)(u32 pfn);
+       void (*release_pmd)(u32 pfn);
+       void (*release_pud)(u32 pfn);
 
        /* Pagetable manipulation functions */
        void (*set_pte)(pte_t *ptep, pte_t pteval);
@@ -910,28 +912,37 @@ static inline void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
        PVOP_VCALL3(pv_mmu_ops.flush_tlb_others, &cpumask, mm, va);
 }
 
-static inline void paravirt_alloc_pt(struct mm_struct *mm, unsigned pfn)
+static inline void paravirt_alloc_pte(struct mm_struct *mm, unsigned pfn)
 {
-       PVOP_VCALL2(pv_mmu_ops.alloc_pt, mm, pfn);
+       PVOP_VCALL2(pv_mmu_ops.alloc_pte, mm, pfn);
 }
-static inline void paravirt_release_pt(unsigned pfn)
+static inline void paravirt_release_pte(unsigned pfn)
 {
-       PVOP_VCALL1(pv_mmu_ops.release_pt, pfn);
+       PVOP_VCALL1(pv_mmu_ops.release_pte, pfn);
 }
 
-static inline void paravirt_alloc_pd(struct mm_struct *mm, unsigned pfn)
+static inline void paravirt_alloc_pmd(struct mm_struct *mm, unsigned pfn)
 {
-       PVOP_VCALL2(pv_mmu_ops.alloc_pd, mm, pfn);
+       PVOP_VCALL2(pv_mmu_ops.alloc_pmd, mm, pfn);
 }
 
-static inline void paravirt_alloc_pd_clone(unsigned pfn, unsigned clonepfn,
-                                          unsigned start, unsigned count)
+static inline void paravirt_alloc_pmd_clone(unsigned pfn, unsigned clonepfn,
+                                           unsigned start, unsigned count)
 {
-       PVOP_VCALL4(pv_mmu_ops.alloc_pd_clone, pfn, clonepfn, start, count);
+       PVOP_VCALL4(pv_mmu_ops.alloc_pmd_clone, pfn, clonepfn, start, count);
 }
-static inline void paravirt_release_pd(unsigned pfn)
+static inline void paravirt_release_pmd(unsigned pfn)
 {
-       PVOP_VCALL1(pv_mmu_ops.release_pd, pfn);
+       PVOP_VCALL1(pv_mmu_ops.release_pmd, pfn);
+}
+
+static inline void paravirt_alloc_pud(struct mm_struct *mm, unsigned pfn)
+{
+       PVOP_VCALL2(pv_mmu_ops.alloc_pud, mm, pfn);
+}
+static inline void paravirt_release_pud(unsigned pfn)
+{
+       PVOP_VCALL1(pv_mmu_ops.release_pud, pfn);
 }
 
 #ifdef CONFIG_HIGHPTE
index 5886eed05886d897a97f59200c5f33c3af37be95..91e4641f3f319de6072c63b436c17fb252c9e5b6 100644 (file)
@@ -1,5 +1,110 @@
-#ifdef CONFIG_X86_32
-# include "pgalloc_32.h"
+#ifndef _ASM_X86_PGALLOC_H
+#define _ASM_X86_PGALLOC_H
+
+#include <linux/threads.h>
+#include <linux/mm.h>          /* for struct page */
+#include <linux/pagemap.h>
+
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
 #else
-# include "pgalloc_64.h"
+static inline void paravirt_alloc_pte(struct mm_struct *mm, unsigned long pfn) {}
+static inline void paravirt_alloc_pmd(struct mm_struct *mm, unsigned long pfn) {}
+static inline void paravirt_alloc_pmd_clone(unsigned long pfn, unsigned long clonepfn,
+                                           unsigned long start, unsigned long count) {}
+static inline void paravirt_alloc_pud(struct mm_struct *mm, unsigned long pfn) {}
+static inline void paravirt_release_pte(unsigned long pfn) {}
+static inline void paravirt_release_pmd(unsigned long pfn) {}
+static inline void paravirt_release_pud(unsigned long pfn) {}
 #endif
+
+/*
+ * Allocate and free page tables.
+ */
+extern pgd_t *pgd_alloc(struct mm_struct *);
+extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+
+extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
+extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
+
+/* Should really implement gc for free page table pages. This could be
+   done with a reference count in struct page. */
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+       BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
+       free_page((unsigned long)pte);
+}
+
+static inline void pte_free(struct mm_struct *mm, struct page *pte)
+{
+       __free_page(pte);
+}
+
+extern void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
+
+static inline void pmd_populate_kernel(struct mm_struct *mm,
+                                      pmd_t *pmd, pte_t *pte)
+{
+       paravirt_alloc_pte(mm, __pa(pte) >> PAGE_SHIFT);
+       set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE));
+}
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
+                               struct page *pte)
+{
+       unsigned long pfn = page_to_pfn(pte);
+
+       paravirt_alloc_pte(mm, pfn);
+       set_pmd(pmd, __pmd(((pteval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE));
+}
+
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+#if PAGETABLE_LEVELS > 2
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+       return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+}
+
+static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+{
+       BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
+       free_page((unsigned long)pmd);
+}
+
+extern void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
+
+#ifdef CONFIG_X86_PAE
+extern void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd);
+#else  /* !CONFIG_X86_PAE */
+static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+{
+       paravirt_alloc_pmd(mm, __pa(pmd) >> PAGE_SHIFT);
+       set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd)));
+}
+#endif /* CONFIG_X86_PAE */
+
+#if PAGETABLE_LEVELS > 3
+static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
+{
+       paravirt_alloc_pud(mm, __pa(pud) >> PAGE_SHIFT);
+       set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud)));
+}
+
+static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+       return (pud_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+}
+
+static inline void pud_free(struct mm_struct *mm, pud_t *pud)
+{
+       BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
+       free_page((unsigned long)pud);
+}
+
+extern void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud);
+#endif /* PAGETABLE_LEVELS > 3 */
+#endif /* PAGETABLE_LEVELS > 2 */
+
+#endif /* _ASM_X86_PGALLOC_H */
diff --git a/include/asm-x86/pgalloc_32.h b/include/asm-x86/pgalloc_32.h
deleted file mode 100644 (file)
index 6bea6e5..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-#ifndef _I386_PGALLOC_H
-#define _I386_PGALLOC_H
-
-#include <linux/threads.h>
-#include <linux/mm.h>          /* for struct page */
-#include <linux/pagemap.h>
-#include <asm/tlb.h>
-#include <asm-generic/tlb.h>
-
-#ifdef CONFIG_PARAVIRT
-#include <asm/paravirt.h>
-#else
-#define paravirt_alloc_pt(mm, pfn) do { } while (0)
-#define paravirt_alloc_pd(mm, pfn) do { } while (0)
-#define paravirt_alloc_pd_clone(pfn, clonepfn, start, count) do { } while (0)
-#define paravirt_release_pt(pfn) do { } while (0)
-#define paravirt_release_pd(pfn) do { } while (0)
-#endif
-
-static inline void pmd_populate_kernel(struct mm_struct *mm,
-                                      pmd_t *pmd, pte_t *pte)
-{
-       paravirt_alloc_pt(mm, __pa(pte) >> PAGE_SHIFT);
-       set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE));
-}
-
-static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
-{
-       unsigned long pfn = page_to_pfn(pte);
-
-       paravirt_alloc_pt(mm, pfn);
-       set_pmd(pmd, __pmd(((pteval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE));
-}
-#define pmd_pgtable(pmd) pmd_page(pmd)
-
-/*
- * Allocate and free page tables.
- */
-extern pgd_t *pgd_alloc(struct mm_struct *);
-extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
-
-extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
-extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
-
-static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
-{
-       free_page((unsigned long)pte);
-}
-
-static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
-{
-       pgtable_page_dtor(pte);
-       __free_page(pte);
-}
-
-
-extern void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
-
-#ifdef CONFIG_X86_PAE
-/*
- * In the PAE case we free the pmds as part of the pgd.
- */
-static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
-{
-       return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
-}
-
-static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
-{
-       BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
-       free_page((unsigned long)pmd);
-}
-
-extern void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
-
-static inline void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
-{
-       paravirt_alloc_pd(mm, __pa(pmd) >> PAGE_SHIFT);
-
-       /* Note: almost everything apart from _PAGE_PRESENT is
-          reserved at the pmd (PDPT) level. */
-       set_pud(pudp, __pud(__pa(pmd) | _PAGE_PRESENT));
-
-       /*
-        * According to Intel App note "TLBs, Paging-Structure Caches,
-        * and Their Invalidation", April 2007, document 317080-001,
-        * section 8.1: in PAE mode we explicitly have to flush the
-        * TLB via cr3 if the top-level pgd is changed...
-        */
-       if (mm == current->active_mm)
-               write_cr3(read_cr3());
-}
-#endif /* CONFIG_X86_PAE */
-
-#endif /* _I386_PGALLOC_H */
diff --git a/include/asm-x86/pgalloc_64.h b/include/asm-x86/pgalloc_64.h
deleted file mode 100644 (file)
index 8d67223..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-#ifndef _X86_64_PGALLOC_H
-#define _X86_64_PGALLOC_H
-
-#include <asm/pda.h>
-#include <linux/threads.h>
-#include <linux/mm.h>
-
-#define pmd_populate_kernel(mm, pmd, pte) \
-               set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte)))
-#define pud_populate(mm, pud, pmd) \
-               set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd)))
-#define pgd_populate(mm, pgd, pud) \
-               set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud)))
-
-#define pmd_pgtable(pmd) pmd_page(pmd)
-
-static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
-{
-       set_pmd(pmd, __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT)));
-}
-
-static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
-{
-       BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
-       free_page((unsigned long)pmd);
-}
-
-static inline pmd_t *pmd_alloc_one (struct mm_struct *mm, unsigned long addr)
-{
-       return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
-}
-
-static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
-{
-       return (pud_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
-}
-
-static inline void pud_free(struct mm_struct *mm, pud_t *pud)
-{
-       BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
-       free_page((unsigned long)pud);
-}
-
-static inline void pgd_list_add(pgd_t *pgd)
-{
-       struct page *page = virt_to_page(pgd);
-       unsigned long flags;
-
-       spin_lock_irqsave(&pgd_lock, flags);
-       list_add(&page->lru, &pgd_list);
-       spin_unlock_irqrestore(&pgd_lock, flags);
-}
-
-static inline void pgd_list_del(pgd_t *pgd)
-{
-       struct page *page = virt_to_page(pgd);
-       unsigned long flags;
-
-       spin_lock_irqsave(&pgd_lock, flags);
-       list_del(&page->lru);
-       spin_unlock_irqrestore(&pgd_lock, flags);
-}
-
-static inline pgd_t *pgd_alloc(struct mm_struct *mm)
-{
-       unsigned boundary;
-       pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
-       if (!pgd)
-               return NULL;
-       pgd_list_add(pgd);
-       /*
-        * Copy kernel pointers in from init.
-        * Could keep a freelist or slab cache of those because the kernel
-        * part never changes.
-        */
-       boundary = pgd_index(__PAGE_OFFSET);
-       memset(pgd, 0, boundary * sizeof(pgd_t));
-       memcpy(pgd + boundary,
-              init_level4_pgt + boundary,
-              (PTRS_PER_PGD - boundary) * sizeof(pgd_t));
-       return pgd;
-}
-
-static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
-{
-       BUG_ON((unsigned long)pgd & (PAGE_SIZE-1));
-       pgd_list_del(pgd);
-       free_page((unsigned long)pgd);
-}
-
-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
-{
-       return (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
-}
-
-static inline pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
-{
-       struct page *page;
-       void *p;
-
-       p = (void *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
-       if (!p)
-               return NULL;
-       page = virt_to_page(p);
-       pgtable_page_ctor(page);
-       return page;
-}
-
-/* Should really implement gc for free page table pages. This could be
-   done with a reference count in struct page. */
-
-static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
-{
-       BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
-       free_page((unsigned long)pte); 
-}
-
-static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
-{
-       pgtable_page_dtor(pte);
-       __free_page(pte);
-} 
-
-#define __pte_free_tlb(tlb,pte)                                \
-do {                                                   \
-       pgtable_page_dtor((pte));                               \
-       tlb_remove_page((tlb), (pte));                  \
-} while (0)
-
-#define __pmd_free_tlb(tlb,x)   tlb_remove_page((tlb),virt_to_page(x))
-#define __pud_free_tlb(tlb,x)   tlb_remove_page((tlb),virt_to_page(x))
-
-#endif /* _X86_64_PGALLOC_H */
index f1d9f4a03f6fafc0dfe8de3634196f571608d6e4..a496d6335d3baa644f80bd0c9e293ce5b9fc480c 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_X86_PGTABLE_H
 #define _ASM_X86_PGTABLE_H
 
-#define USER_PTRS_PER_PGD      ((TASK_SIZE-1)/PGDIR_SIZE+1)
 #define FIRST_USER_ADDRESS     0
 
 #define _PAGE_BIT_PRESENT      0       /* is present */
@@ -289,6 +288,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 
 #define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask)
 
+#ifndef __ASSEMBLY__
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+struct file;
+pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+                              unsigned long size, pgprot_t vma_prot);
+int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
+                              unsigned long size, pgprot_t *vma_prot);
+#endif
+
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
 #else  /* !CONFIG_PARAVIRT */
@@ -330,6 +338,9 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 # include "pgtable_64.h"
 #endif
 
+#define KERNEL_PGD_BOUNDARY    pgd_index(PAGE_OFFSET)
+#define KERNEL_PGD_PTRS                (PTRS_PER_PGD - KERNEL_PGD_BOUNDARY)
+
 #ifndef __ASSEMBLY__
 
 enum {
@@ -389,37 +400,17 @@ static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr,
  * bit at the same time.
  */
 #define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
-#define ptep_set_access_flags(vma, address, ptep, entry, dirty)                \
-({                                                                     \
-       int __changed = !pte_same(*(ptep), entry);                      \
-       if (__changed && dirty) {                                       \
-               *ptep = entry;                                          \
-               pte_update_defer((vma)->vm_mm, (address), (ptep));      \
-               flush_tlb_page(vma, address);                           \
-       }                                                               \
-       __changed;                                                      \
-})
+extern int ptep_set_access_flags(struct vm_area_struct *vma,
+                                unsigned long address, pte_t *ptep,
+                                pte_t entry, int dirty);
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define ptep_test_and_clear_young(vma, addr, ptep) ({                  \
-       int __ret = 0;                                                  \
-       if (pte_young(*(ptep)))                                         \
-               __ret = test_and_clear_bit(_PAGE_BIT_ACCESSED,          \
-                                          &(ptep)->pte);               \
-       if (__ret)                                                      \
-               pte_update((vma)->vm_mm, addr, ptep);                   \
-       __ret;                                                          \
-})
+extern int ptep_test_and_clear_young(struct vm_area_struct *vma,
+                                    unsigned long addr, pte_t *ptep);
 
 #define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
-#define ptep_clear_flush_young(vma, address, ptep)                     \
-({                                                                     \
-       int __young;                                                    \
-       __young = ptep_test_and_clear_young((vma), (address), (ptep));  \
-       if (__young)                                                    \
-               flush_tlb_page(vma, address);                           \
-       __young;                                                        \
-})
+extern int ptep_clear_flush_young(struct vm_area_struct *vma,
+                                 unsigned long address, pte_t *ptep);
 
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
@@ -456,6 +447,22 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm,
        pte_update(mm, addr, ptep);
 }
 
+/*
+ * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
+ *
+ *  dst - pointer to pgd range anwhere on a pgd page
+ *  src - ""
+ *  count - the number of pgds to copy.
+ *
+ * dst and src can be on the same page, but the range must not overlap,
+ * and must not cross a page boundary.
+ */
+static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
+{
+       memcpy(dst, src, count * sizeof(pgd_t));
+}
+
+
 #include <asm-generic/pgtable.h>
 #endif /* __ASSEMBLY__ */
 
index c4a6436744582e35676c06de5833402bc4de30d3..577ab79c4c27b8ebaa84542806dfe4d3f217553f 100644 (file)
@@ -48,9 +48,6 @@ void paging_init(void);
 #define PGDIR_SIZE     (1UL << PGDIR_SHIFT)
 #define PGDIR_MASK     (~(PGDIR_SIZE - 1))
 
-#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
-#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
-
 /* Just any arbitrary offset to the start of the vmalloc VM area: the
  * current 8MB value just means that there will be a 8MB "hole" after the
  * physical memory until the kernel virtual memory starts.  That means that
@@ -108,21 +105,6 @@ extern int pmd_bad(pmd_t pmd);
 # include <asm/pgtable-2level.h>
 #endif
 
-/*
- * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
- *
- *  dst - pointer to pgd range anwhere on a pgd page
- *  src - ""
- *  count - the number of pgds to copy.
- *
- * dst and src can be on the same page, but the range must not overlap,
- * and must not cross a page boundary.
- */
-static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
-{
-       memcpy(dst, src, count * sizeof(pgd_t));
-}
-
 /*
  * Macro to mark a page protection value as "uncacheable".
  * On processors which do not support it, this is a no-op.
@@ -216,16 +198,16 @@ do {                                              \
  */
 #define update_mmu_cache(vma, address, pte) do { } while (0)
 
-void native_pagetable_setup_start(pgd_t *base);
-void native_pagetable_setup_done(pgd_t *base);
+extern void native_pagetable_setup_start(pgd_t *base);
+extern void native_pagetable_setup_done(pgd_t *base);
 
 #ifndef CONFIG_PARAVIRT
-static inline void paravirt_pagetable_setup_start(pgd_t *base)
+static inline void __init paravirt_pagetable_setup_start(pgd_t *base)
 {
        native_pagetable_setup_start(base);
 }
 
-static inline void paravirt_pagetable_setup_done(pgd_t *base)
+static inline void __init paravirt_pagetable_setup_done(pgd_t *base)
 {
        native_pagetable_setup_done(base);
 }
index 9fd87d0b6477d209177790c169558b87599934a9..a3bbf8766c1d62790d2f999bba1edac5dab7fa64 100644 (file)
@@ -24,7 +24,7 @@ extern void paging_init(void);
 
 #endif /* !__ASSEMBLY__ */
 
-#define SHARED_KERNEL_PMD      1
+#define SHARED_KERNEL_PMD      0
 
 /*
  * PGDIR_SHIFT determines what a top-level page table entry can map
index fe312a5ba20478da9bf5afc91edf4b526bbe0ce5..bb7133dc155d4bebb9094693a8b823d4ae127e19 100644 (file)
@@ -1,5 +1,11 @@
 #ifdef __KERNEL__
-# if defined(CONFIG_X86_32) || defined(__i386__)
+# ifdef CONFIG_X86_32
+#  include "posix_types_32.h"
+# else
+#  include "posix_types_64.h"
+# endif
+#else
+# ifdef __i386__
 #  include "posix_types_32.h"
 # else
 #  include "posix_types_64.h"
index e6bf92ddeb21ded7de69cff3f37120df56520291..2e7974ec77eca6e94b2ee503d02580a87db717a2 100644 (file)
@@ -118,7 +118,6 @@ struct cpuinfo_x86 {
 #define X86_VENDOR_CYRIX       1
 #define X86_VENDOR_AMD         2
 #define X86_VENDOR_UMC         3
-#define X86_VENDOR_NEXGEN      4
 #define X86_VENDOR_CENTAUR     5
 #define X86_VENDOR_TRANSMETA   7
 #define X86_VENDOR_NSC         8
@@ -723,6 +722,7 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
 
 static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
 {
+       trace_hardirqs_on();
        /* "mwait %eax, %ecx;" */
        asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
                     :: "a" (eax), "c" (ecx));
index 24ec061566c541e4ba237e385a67b54f8092dc39..9f922b0b95d6d3961275c9cac804acf22cbb8ef6 100644 (file)
@@ -231,6 +231,8 @@ extern int do_get_thread_area(struct task_struct *p, int idx,
 extern int do_set_thread_area(struct task_struct *p, int idx,
                              struct user_desc __user *info, int can_allocate);
 
+#define __ARCH_WANT_COMPAT_SYS_PTRACE
+
 #endif /* __KERNEL__ */
 
 #endif /* !__ASSEMBLY__ */
index 6b5233b4f84b945d713cf047c0ea591ea77469d7..e63741f19392e24d587b3383c18e6de2da1dab18 100644 (file)
@@ -15,5 +15,7 @@ struct machine_ops {
 extern struct machine_ops machine_ops;
 
 void machine_real_restart(unsigned char *code, int length);
+void native_machine_crash_shutdown(struct pt_regs *regs);
+void native_machine_shutdown(void);
 
 #endif /* _ASM_REBOOT_H */
index 3451c576e6afc1f26a6bbad5401fec0bf75c85db..c9448bd8968f3696f800d240078e3b0510e101b7 100644 (file)
@@ -60,15 +60,4 @@ enum {
        ALT_CALGARY     = 5,    /* Second Planar Calgary      */
 };
 
-/*
- * there is a real-mode segmented pointer pointing to the
- * 4K EBDA area at 0x40E.
- */
-static inline unsigned long get_bios_ebda(void)
-{
-       unsigned long address = *(unsigned short *)phys_to_virt(0x40EUL);
-       address <<= 4;
-       return address;
-}
-
 #endif /* __ASM_RIO_H */
index 62ebdec394b96866d59f2d74e843721e9af052cf..1ebaa5cd31128eb40a7ca2c918aa17d7d8d8f244 100644 (file)
@@ -199,7 +199,6 @@ static inline int hard_smp_processor_id(void)
 #ifdef CONFIG_HOTPLUG_CPU
 extern void cpu_exit_clear(void);
 extern void cpu_uninit(void);
-extern void remove_siblinginfo(int cpu);
 #endif
 
 extern void smp_alloc_memory(void);
index 0434bd8349a7456f27f8ca95c18b472e07c1ba8e..d2d8eb5b55f532365f9277b5f776109626f7ed4b 100644 (file)
@@ -18,7 +18,6 @@ extern unsigned int cpu_khz;
 extern unsigned int tsc_khz;
 
 extern void disable_TSC(void);
-extern void enable_TSC(void);
 
 static inline cycles_t get_cycles(void)
 {
index effc7ad8e12f66bc28d68b4b54134fcf11143c1f..2a58ed3e51d8265627e185d5d8be3783c5ea9bf4 100644 (file)
@@ -1,5 +1,11 @@
 #ifdef __KERNEL__
-# if defined(CONFIG_X86_32) || defined(__i386__)
+# ifdef CONFIG_X86_32
+#  include "unistd_32.h"
+# else
+#  include "unistd_64.h"
+# endif
+#else
+# ifdef __i386__
 #  include "unistd_32.h"
 # else
 #  include "unistd_64.h"
diff --git a/include/asm-x86/xen/events.h b/include/asm-x86/xen/events.h
new file mode 100644 (file)
index 0000000..596312a
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __XEN_EVENTS_H
+#define __XEN_EVENTS_H
+
+enum ipi_vector {
+       XEN_RESCHEDULE_VECTOR,
+       XEN_CALL_FUNCTION_VECTOR,
+
+       XEN_NR_IPIS,
+};
+
+static inline int xen_irqs_disabled(struct pt_regs *regs)
+{
+       return raw_irqs_disabled_flags(regs->flags);
+}
+
+static inline void xen_do_IRQ(int irq, struct pt_regs *regs)
+{
+       regs->orig_ax = ~irq;
+       do_IRQ(regs);
+}
+
+#endif /* __XEN_EVENTS_H */
diff --git a/include/asm-x86/xen/grant_table.h b/include/asm-x86/xen/grant_table.h
new file mode 100644 (file)
index 0000000..2444d45
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __XEN_GRANT_TABLE_H
+#define __XEN_GRANT_TABLE_H
+
+#define xen_alloc_vm_area(size)        alloc_vm_area(size)
+#define xen_free_vm_area(area) free_vm_area(area)
+
+#endif /* __XEN_GRANT_TABLE_H */
index bc0ee7d961ca8d55ac98ebcfb9607a3be920603b..c2ccd997ed3537f00ff3ea78195a845d3dd27d0c 100644 (file)
@@ -163,6 +163,12 @@ HYPERVISOR_set_callbacks(unsigned long event_selector,
                           failsafe_selector, failsafe_address);
 }
 
+static inline int
+HYPERVISOR_callback_op(int cmd, void *arg)
+{
+       return _hypercall2(int, callback_op, cmd, arg);
+}
+
 static inline int
 HYPERVISOR_fpu_taskswitch(int set)
 {
index 165c3968e1380df0d5b3a06ad774486c10364c46..6227000a1e840780512b31e1e246bf7cd14ee716 100644 (file)
 #define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name)
 #define GUEST_HANDLE(name)        __guest_handle_ ## name
 
+#ifdef __XEN__
+#if defined(__i386__)
+#define set_xen_guest_handle(hnd, val)                 \
+       do {                                            \
+               if (sizeof(hnd) == 8)                   \
+                       *(uint64_t *)&(hnd) = 0;        \
+               (hnd).p = val;                          \
+       } while (0)
+#elif defined(__x86_64__)
+#define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0)
+#endif
+#else
+#if defined(__i386__)
+#define set_xen_guest_handle(hnd, val)                 \
+       do {                                            \
+               if (sizeof(hnd) == 8)                   \
+                       *(uint64_t *)&(hnd) = 0;        \
+               (hnd) = val;                            \
+       } while (0)
+#elif defined(__x86_64__)
+#define set_xen_guest_handle(hnd, val) do { (hnd) = val; } while (0)
+#endif
+#endif
+
 #ifndef __ASSEMBLY__
 /* Guest handles for primitive C types. */
 __DEFINE_GUEST_HANDLE(uchar, unsigned char);
@@ -171,6 +195,10 @@ struct arch_vcpu_info {
     unsigned long pad[5]; /* sizeof(struct vcpu_info) == 64 */
 };
 
+struct xen_callback {
+       unsigned long cs;
+       unsigned long eip;
+};
 #endif /* !__ASSEMBLY__ */
 
 /*
diff --git a/include/asm-x86/xen/page.h b/include/asm-x86/xen/page.h
new file mode 100644 (file)
index 0000000..0179930
--- /dev/null
@@ -0,0 +1,168 @@
+#ifndef __XEN_PAGE_H
+#define __XEN_PAGE_H
+
+#include <linux/pfn.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+#include <xen/features.h>
+
+/* Xen machine address */
+typedef struct xmaddr {
+       phys_addr_t maddr;
+} xmaddr_t;
+
+/* Xen pseudo-physical address */
+typedef struct xpaddr {
+       phys_addr_t paddr;
+} xpaddr_t;
+
+#define XMADDR(x)      ((xmaddr_t) { .maddr = (x) })
+#define XPADDR(x)      ((xpaddr_t) { .paddr = (x) })
+
+/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
+#define INVALID_P2M_ENTRY      (~0UL)
+#define FOREIGN_FRAME_BIT      (1UL<<31)
+#define FOREIGN_FRAME(m)       ((m) | FOREIGN_FRAME_BIT)
+
+extern unsigned long *phys_to_machine_mapping;
+
+static inline unsigned long pfn_to_mfn(unsigned long pfn)
+{
+       if (xen_feature(XENFEAT_auto_translated_physmap))
+               return pfn;
+
+       return phys_to_machine_mapping[(unsigned int)(pfn)] &
+               ~FOREIGN_FRAME_BIT;
+}
+
+static inline int phys_to_machine_mapping_valid(unsigned long pfn)
+{
+       if (xen_feature(XENFEAT_auto_translated_physmap))
+               return 1;
+
+       return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
+}
+
+static inline unsigned long mfn_to_pfn(unsigned long mfn)
+{
+       unsigned long pfn;
+
+       if (xen_feature(XENFEAT_auto_translated_physmap))
+               return mfn;
+
+#if 0
+       if (unlikely((mfn >> machine_to_phys_order) != 0))
+               return max_mapnr;
+#endif
+
+       pfn = 0;
+       /*
+        * The array access can fail (e.g., device space beyond end of RAM).
+        * In such cases it doesn't matter what we return (we return garbage),
+        * but we must handle the fault without crashing!
+        */
+       __get_user(pfn, &machine_to_phys_mapping[mfn]);
+
+       return pfn;
+}
+
+static inline xmaddr_t phys_to_machine(xpaddr_t phys)
+{
+       unsigned offset = phys.paddr & ~PAGE_MASK;
+       return XMADDR(PFN_PHYS((u64)pfn_to_mfn(PFN_DOWN(phys.paddr))) | offset);
+}
+
+static inline xpaddr_t machine_to_phys(xmaddr_t machine)
+{
+       unsigned offset = machine.maddr & ~PAGE_MASK;
+       return XPADDR(PFN_PHYS((u64)mfn_to_pfn(PFN_DOWN(machine.maddr))) | offset);
+}
+
+/*
+ * We detect special mappings in one of two ways:
+ *  1. If the MFN is an I/O page then Xen will set the m2p entry
+ *     to be outside our maximum possible pseudophys range.
+ *  2. If the MFN belongs to a different domain then we will certainly
+ *     not have MFN in our p2m table. Conversely, if the page is ours,
+ *     then we'll have p2m(m2p(MFN))==MFN.
+ * If we detect a special mapping then it doesn't have a 'struct page'.
+ * We force !pfn_valid() by returning an out-of-range pointer.
+ *
+ * NB. These checks require that, for any MFN that is not in our reservation,
+ * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
+ * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
+ * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
+ *
+ * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
+ *      use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
+ *      require. In all the cases we care about, the FOREIGN_FRAME bit is
+ *      masked (e.g., pfn_to_mfn()) so behaviour there is correct.
+ */
+static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
+{
+       extern unsigned long max_mapnr;
+       unsigned long pfn = mfn_to_pfn(mfn);
+       if ((pfn < max_mapnr)
+           && !xen_feature(XENFEAT_auto_translated_physmap)
+           && (phys_to_machine_mapping[pfn] != mfn))
+               return max_mapnr; /* force !pfn_valid() */
+       return pfn;
+}
+
+static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+{
+       if (xen_feature(XENFEAT_auto_translated_physmap)) {
+               BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+               return;
+       }
+       phys_to_machine_mapping[pfn] = mfn;
+}
+
+/* VIRT <-> MACHINE conversion */
+#define virt_to_machine(v)     (phys_to_machine(XPADDR(__pa(v))))
+#define virt_to_mfn(v)         (pfn_to_mfn(PFN_DOWN(__pa(v))))
+#define mfn_to_virt(m)         (__va(mfn_to_pfn(m) << PAGE_SHIFT))
+
+static inline unsigned long pte_mfn(pte_t pte)
+{
+       return (pte.pte & ~_PAGE_NX) >> PAGE_SHIFT;
+}
+
+static inline pte_t mfn_pte(unsigned long page_nr, pgprot_t pgprot)
+{
+       pte_t pte;
+
+       pte.pte = ((phys_addr_t)page_nr << PAGE_SHIFT) |
+               (pgprot_val(pgprot) & __supported_pte_mask);
+
+       return pte;
+}
+
+static inline pteval_t pte_val_ma(pte_t pte)
+{
+       return pte.pte;
+}
+
+static inline pte_t __pte_ma(pteval_t x)
+{
+       return (pte_t) { .pte = x };
+}
+
+#ifdef CONFIG_X86_PAE
+#define pmd_val_ma(v) ((v).pmd)
+#define pud_val_ma(v) ((v).pgd.pgd)
+#define __pmd_ma(x)    ((pmd_t) { (x) } )
+#else  /* !X86_PAE */
+#define pmd_val_ma(v)  ((v).pud.pgd.pgd)
+#endif /* CONFIG_X86_PAE */
+
+#define pgd_val_ma(x)  ((x).pgd)
+
+
+xmaddr_t arbitrary_virt_to_machine(unsigned long address);
+void make_lowmem_page_readonly(void *vaddr);
+void make_lowmem_page_readwrite(void *vaddr);
+
+#endif /* __XEN_PAGE_H */
index cbb5ccb27de3e0a377566d2b9459a2af5ba66ef0..bda6f04791d43e421efec9c5ced07bdd407f3eb4 100644 (file)
@@ -210,7 +210,6 @@ unifdef-y += hayesesp.h
 unifdef-y += hdlcdrv.h
 unifdef-y += hdlc.h
 unifdef-y += hdreg.h
-unifdef-y += hdsmart.h
 unifdef-y += hid.h
 unifdef-y += hiddev.h
 unifdef-y += hidraw.h
index 40d54731de7e0b9fb6b44ebf7db983ea58fc1ac2..48bde600a2dbcf652715d0c97b4da756ceffad3d 100644 (file)
@@ -112,4 +112,144 @@ static inline unsigned fls_long(unsigned long l)
        return fls64(l);
 }
 
+#ifdef __KERNEL__
+#ifdef CONFIG_GENERIC_FIND_FIRST_BIT
+extern unsigned long __find_first_bit(const unsigned long *addr,
+               unsigned long size);
+
+/**
+ * find_first_bit - find the first set bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit number of the first set bit.
+ */
+static __always_inline unsigned long
+find_first_bit(const unsigned long *addr, unsigned long size)
+{
+       /* Avoid a function call if the bitmap size is a constant */
+       /* and not bigger than BITS_PER_LONG. */
+
+       /* insert a sentinel so that __ffs returns size if there */
+       /* are no set bits in the bitmap */
+       if (__builtin_constant_p(size) && (size < BITS_PER_LONG))
+               return __ffs((*addr) | (1ul << size));
+
+       /* the result of __ffs(0) is undefined, so it needs to be */
+       /* handled separately */
+       if (__builtin_constant_p(size) && (size == BITS_PER_LONG))
+               return ((*addr) == 0) ? BITS_PER_LONG : __ffs(*addr);
+
+       /* size is not constant or too big */
+       return __find_first_bit(addr, size);
+}
+
+extern unsigned long __find_first_zero_bit(const unsigned long *addr,
+               unsigned long size);
+
+/**
+ * find_first_zero_bit - find the first cleared bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit number of the first cleared bit.
+ */
+static __always_inline unsigned long
+find_first_zero_bit(const unsigned long *addr, unsigned long size)
+{
+       /* Avoid a function call if the bitmap size is a constant */
+       /* and not bigger than BITS_PER_LONG. */
+
+       /* insert a sentinel so that __ffs returns size if there */
+       /* are no set bits in the bitmap */
+       if (__builtin_constant_p(size) && (size < BITS_PER_LONG)) {
+               return __ffs(~(*addr) | (1ul << size));
+       }
+
+       /* the result of __ffs(0) is undefined, so it needs to be */
+       /* handled separately */
+       if (__builtin_constant_p(size) && (size == BITS_PER_LONG))
+               return (~(*addr) == 0) ? BITS_PER_LONG : __ffs(~(*addr));
+
+       /* size is not constant or too big */
+       return __find_first_zero_bit(addr, size);
+}
+#endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
+
+#ifdef CONFIG_GENERIC_FIND_NEXT_BIT
+extern unsigned long __find_next_bit(const unsigned long *addr,
+               unsigned long size, unsigned long offset);
+
+/**
+ * find_next_bit - find the next set bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The bitmap size in bits
+ */
+static __always_inline unsigned long
+find_next_bit(const unsigned long *addr, unsigned long size,
+               unsigned long offset)
+{
+       unsigned long value;
+
+       /* Avoid a function call if the bitmap size is a constant */
+       /* and not bigger than BITS_PER_LONG. */
+
+       /* insert a sentinel so that __ffs returns size if there */
+       /* are no set bits in the bitmap */
+       if (__builtin_constant_p(size) && (size < BITS_PER_LONG)) {
+               value = (*addr) & ((~0ul) << offset);
+               value |= (1ul << size);
+               return __ffs(value);
+       }
+
+       /* the result of __ffs(0) is undefined, so it needs to be */
+       /* handled separately */
+       if (__builtin_constant_p(size) && (size == BITS_PER_LONG)) {
+               value = (*addr) & ((~0ul) << offset);
+               return (value == 0) ? BITS_PER_LONG : __ffs(value);
+       }
+
+       /* size is not constant or too big */
+       return __find_next_bit(addr, size, offset);
+}
+
+extern unsigned long __find_next_zero_bit(const unsigned long *addr,
+               unsigned long size, unsigned long offset);
+
+/**
+ * find_next_zero_bit - find the next cleared bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The bitmap size in bits
+ */
+static __always_inline unsigned long
+find_next_zero_bit(const unsigned long *addr, unsigned long size,
+               unsigned long offset)
+{
+       unsigned long value;
+
+       /* Avoid a function call if the bitmap size is a constant */
+       /* and not bigger than BITS_PER_LONG. */
+
+       /* insert a sentinel so that __ffs returns size if there */
+       /* are no set bits in the bitmap */
+       if (__builtin_constant_p(size) && (size < BITS_PER_LONG)) {
+               value = (~(*addr)) & ((~0ul) << offset);
+               value |= (1ul << size);
+               return __ffs(value);
+       }
+
+       /* the result of __ffs(0) is undefined, so it needs to be */
+       /* handled separately */
+       if (__builtin_constant_p(size) && (size == BITS_PER_LONG)) {
+               value = (~(*addr)) & ((~0ul) << offset);
+               return (value == 0) ? BITS_PER_LONG : __ffs(value);
+       }
+
+       /* size is not constant or too big */
+       return __find_next_zero_bit(addr, size, offset);
+}
+#endif /* CONFIG_GENERIC_FIND_NEXT_BIT */
+#endif /* __KERNEL__ */
 #endif
index e8406c55c6d31885a3adddfba69a40378c961c19..cf0303a6061195de840a22d97ff24a7b41d4d49e 100644 (file)
@@ -56,19 +56,25 @@ struct sg_io_v4 {
 #if defined(CONFIG_BLK_DEV_BSG)
 struct bsg_class_device {
        struct device *class_dev;
-       struct device *dev;
+       struct device *parent;
        int minor;
        struct request_queue *queue;
+       struct kref ref;
+       void (*release)(struct device *);
 };
 
-extern int bsg_register_queue(struct request_queue *, struct device *, const char *);
+extern int bsg_register_queue(struct request_queue *q,
+                             struct device *parent, const char *name,
+                             void (*release)(struct device *));
 extern void bsg_unregister_queue(struct request_queue *);
 #else
-static inline int bsg_register_queue(struct request_queue * rq, struct device *dev, const char *name)
+static inline int bsg_register_queue(struct request_queue *q,
+                                    struct device *parent, const char *name,
+                                    void (*release)(struct device *))
 {
        return 0;
 }
-static inline void bsg_unregister_queue(struct request_queue *rq)
+static inline void bsg_unregister_queue(struct request_queue *q)
 {
 }
 #endif
index fe23792f05c1077149718fd783458e8d4d12c5db..b2fd7547b58deaa5e90b0fa5b384c0581da19d58 100644 (file)
 #define __must_be_array(a) \
   BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&a[0])))
 
-#define inline         inline          __attribute__((always_inline))
-#define __inline__     __inline__      __attribute__((always_inline))
-#define __inline       __inline        __attribute__((always_inline))
+/*
+ * Force always-inline if the user requests it so via the .config:
+ */
+#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
+    !defined(CONFIG_OPTIMIZE_INLINING) && (__GNUC__ >= 4)
+# define inline                inline          __attribute__((always_inline))
+# define __inline__    __inline__      __attribute__((always_inline))
+# define __inline      __inline        __attribute__((always_inline))
+#endif
+
 #define __deprecated                   __attribute__((deprecated))
 #define __packed                       __attribute__((packed))
 #define __weak                         __attribute__((weak))
index cb784579956bb35a3f11abde8178ce6ba2da1e44..ad3b787479a49ef54daff54e12f505b2833fd731 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001 Sistina Software (UK) Limited.
- * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
  *
  * This file is released under the LGPL.
  */
@@ -10,6 +10,8 @@
 
 #ifdef __KERNEL__
 
+#include <linux/bio.h>
+
 struct dm_target;
 struct dm_table;
 struct dm_dev;
@@ -250,11 +252,97 @@ void dm_table_event(struct dm_table *t);
  */
 int dm_swap_table(struct mapped_device *md, struct dm_table *t);
 
+/*-----------------------------------------------------------------
+ * Macros.
+ *---------------------------------------------------------------*/
+#define DM_NAME "device-mapper"
+
+#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_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) ? \
+                         0 : scnprintf(result + sz, maxlen - sz, x))
+
+#define SECTOR_SHIFT 9
+
+/*
+ * Definitions of return values from target end_io function.
+ */
+#define DM_ENDIO_INCOMPLETE    1
+#define DM_ENDIO_REQUEUE       2
+
+/*
+ * Definitions of return values from target map function.
+ */
+#define DM_MAPIO_SUBMITTED     0
+#define DM_MAPIO_REMAPPED      1
+#define DM_MAPIO_REQUEUE       DM_ENDIO_REQUEUE
+
+/*
+ * Ceiling(n / sz)
+ */
+#define dm_div_up(n, sz) (((n) + (sz) - 1) / (sz))
+
+#define dm_sector_div_up(n, sz) ( \
+{ \
+       sector_t _r = ((n) + (sz) - 1); \
+       sector_div(_r, (sz)); \
+       _r; \
+} \
+)
+
 /*
- * Prepare a table for a device that will error all I/O.
- * To make it active, call dm_suspend(), dm_swap_table() then dm_resume().
+ * ceiling(n / size) * size
  */
-int dm_create_error_table(struct dm_table **result, struct mapped_device *md);
+#define dm_round_up(n, sz) (dm_div_up((n), (sz)) * (sz))
+
+static inline sector_t to_sector(unsigned long n)
+{
+       return (n >> SECTOR_SHIFT);
+}
+
+static inline unsigned long to_bytes(sector_t n)
+{
+       return (n << SECTOR_SHIFT);
+}
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_DEVICE_MAPPER_H */
similarity index 53%
rename from drivers/md/dm-log.h
rename to include/linux/dm-dirty-log.h
index 3fae87eb59631bcaf77c82b0924e363716643b0c..600c5fb2daad4c231b53a4654316469895af9b0c 100644 (file)
@@ -1,52 +1,56 @@
 /*
  * Copyright (C) 2003 Sistina Software
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * Device-Mapper dirty region log.
  *
  * This file is released under the LGPL.
  */
 
-#ifndef DM_DIRTY_LOG
-#define DM_DIRTY_LOG
+#ifndef _LINUX_DM_DIRTY_LOG
+#define _LINUX_DM_DIRTY_LOG
+
+#ifdef __KERNEL__
 
-#include "dm.h"
+#include <linux/types.h>
+#include <linux/device-mapper.h>
 
 typedef sector_t region_t;
 
-struct dirty_log_type;
+struct dm_dirty_log_type;
 
-struct dirty_log {
-       struct dirty_log_type *type;
+struct dm_dirty_log {
+       struct dm_dirty_log_type *type;
        void *context;
 };
 
-struct dirty_log_type {
-       struct list_head list;
+struct dm_dirty_log_type {
        const char *name;
        struct module *module;
-       unsigned int use_count;
 
-       int (*ctr)(struct dirty_log *log, struct dm_target *ti,
-                  unsigned int argc, char **argv);
-       void (*dtr)(struct dirty_log *log);
+       int (*ctr)(struct dm_dirty_log *log, struct dm_target *ti,
+                  unsigned argc, char **argv);
+       void (*dtr)(struct dm_dirty_log *log);
 
        /*
         * There are times when we don't want the log to touch
         * the disk.
         */
-       int (*presuspend)(struct dirty_log *log);
-       int (*postsuspend)(struct dirty_log *log);
-       int (*resume)(struct dirty_log *log);
+       int (*presuspend)(struct dm_dirty_log *log);
+       int (*postsuspend)(struct dm_dirty_log *log);
+       int (*resume)(struct dm_dirty_log *log);
 
        /*
         * Retrieves the smallest size of region that the log can
         * deal with.
         */
-       uint32_t (*get_region_size)(struct dirty_log *log);
+       uint32_t (*get_region_size)(struct dm_dirty_log *log);
 
-        /*
+       /*
         * A predicate to say whether a region is clean or not.
         * May block.
         */
-       int (*is_clean)(struct dirty_log *log, region_t region);
+       int (*is_clean)(struct dm_dirty_log *log, region_t region);
 
        /*
         *  Returns: 0, 1, -EWOULDBLOCK, < 0
@@ -59,13 +63,14 @@ struct dirty_log_type {
         * passed to a daemon to deal with, since a daemon is
         * allowed to block.
         */
-       int (*in_sync)(struct dirty_log *log, region_t region, int can_block);
+       int (*in_sync)(struct dm_dirty_log *log, region_t region,
+                      int can_block);
 
        /*
         * Flush the current log state (eg, to disk).  This
         * function may block.
         */
-       int (*flush)(struct dirty_log *log);
+       int (*flush)(struct dm_dirty_log *log);
 
        /*
         * Mark an area as clean or dirty.  These functions may
@@ -73,8 +78,8 @@ struct dirty_log_type {
         * be extremely rare (eg, allocating another chunk of
         * memory for some reason).
         */
-       void (*mark_region)(struct dirty_log *log, region_t region);
-       void (*clear_region)(struct dirty_log *log, region_t region);
+       void (*mark_region)(struct dm_dirty_log *log, region_t region);
+       void (*clear_region)(struct dm_dirty_log *log, region_t region);
 
        /*
         * Returns: <0 (error), 0 (no region), 1 (region)
@@ -88,44 +93,39 @@ struct dirty_log_type {
         * tells you if an area is synchronised, the other
         * assigns recovery work.
        */
-       int (*get_resync_work)(struct dirty_log *log, region_t *region);
+       int (*get_resync_work)(struct dm_dirty_log *log, region_t *region);
 
        /*
         * This notifies the log that the resync status of a region
         * has changed.  It also clears the region from the recovering
         * list (if present).
         */
-       void (*set_region_sync)(struct dirty_log *log,
+       void (*set_region_sync)(struct dm_dirty_log *log,
                                region_t region, int in_sync);
 
-        /*
+       /*
         * Returns the number of regions that are in sync.
-         */
-        region_t (*get_sync_count)(struct dirty_log *log);
+        */
+       region_t (*get_sync_count)(struct dm_dirty_log *log);
 
        /*
         * Support function for mirror status requests.
         */
-       int (*status)(struct dirty_log *log, status_type_t status_type,
-                     char *result, unsigned int maxlen);
+       int (*status)(struct dm_dirty_log *log, status_type_t status_type,
+                     char *result, unsigned maxlen);
 };
 
-int dm_register_dirty_log_type(struct dirty_log_type *type);
-int dm_unregister_dirty_log_type(struct dirty_log_type *type);
-
+int dm_dirty_log_type_register(struct dm_dirty_log_type *type);
+int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type);
 
 /*
  * Make sure you use these two functions, rather than calling
  * type->constructor/destructor() directly.
  */
-struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *ti,
-                                     unsigned int argc, char **argv);
-void dm_destroy_dirty_log(struct dirty_log *log);
-
-/*
- * init/exit functions.
- */
-int dm_dirty_log_init(void);
-void dm_dirty_log_exit(void);
+struct dm_dirty_log *dm_dirty_log_create(const char *type_name,
+                                        struct dm_target *ti,
+                                        unsigned argc, char **argv);
+void dm_dirty_log_destroy(struct dm_dirty_log *log);
 
-#endif
+#endif /* __KERNEL__ */
+#endif /* _LINUX_DM_DIRTY_LOG_H */
similarity index 84%
rename from drivers/md/dm-io.h
rename to include/linux/dm-io.h
index f647e2cceaa673f8098fce058832a3cc55ce23c4..b6bf17ee2f619601964d33d9c3e7cbf323f79317 100644 (file)
@@ -1,15 +1,20 @@
 /*
  * Copyright (C) 2003 Sistina Software
+ * Copyright (C) 2004 - 2008 Red Hat, Inc. All rights reserved.
+ *
+ * Device-Mapper low-level I/O.
  *
  * This file is released under the GPL.
  */
 
-#ifndef _DM_IO_H
-#define _DM_IO_H
+#ifndef _LINUX_DM_IO_H
+#define _LINUX_DM_IO_H
+
+#ifdef __KERNEL__
 
-#include "dm.h"
+#include <linux/types.h>
 
-struct io_region {
+struct dm_io_region {
        struct block_device *bdev;
        sector_t sector;
        sector_t count;         /* If this is zero the region is ignored. */
@@ -74,6 +79,7 @@ void dm_io_client_destroy(struct dm_io_client *client);
  * error occurred doing io to the corresponding region.
  */
 int dm_io(struct dm_io_request *io_req, unsigned num_regions,
-         struct io_region *region, unsigned long *sync_error_bits);
+         struct dm_io_region *region, unsigned long *sync_error_bits);
 
-#endif
+#endif /* __KERNEL__ */
+#endif /* _LINUX_DM_IO_H */
diff --git a/include/linux/dm-kcopyd.h b/include/linux/dm-kcopyd.h
new file mode 100644 (file)
index 0000000..5db2163
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2001 - 2003 Sistina Software
+ * Copyright (C) 2004 - 2008 Red Hat, Inc. All rights reserved.
+ *
+ * kcopyd provides a simple interface for copying an area of one
+ * block-device to one or more other block-devices, either synchronous
+ * or with an asynchronous completion notification.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_KCOPYD_H
+#define _LINUX_DM_KCOPYD_H
+
+#ifdef __KERNEL__
+
+#include <linux/dm-io.h>
+
+/* FIXME: make this configurable */
+#define DM_KCOPYD_MAX_REGIONS 8
+
+#define DM_KCOPYD_IGNORE_ERROR 1
+
+/*
+ * To use kcopyd you must first create a dm_kcopyd_client object.
+ */
+struct dm_kcopyd_client;
+int dm_kcopyd_client_create(unsigned num_pages,
+                           struct dm_kcopyd_client **result);
+void dm_kcopyd_client_destroy(struct dm_kcopyd_client *kc);
+
+/*
+ * Submit a copy job to kcopyd.  This is built on top of the
+ * previous three fns.
+ *
+ * read_err is a boolean,
+ * write_err is a bitset, with 1 bit for each destination region
+ */
+typedef void (*dm_kcopyd_notify_fn)(int read_err, unsigned long write_err,
+                                   void *context);
+
+int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
+                  unsigned num_dests, struct dm_io_region *dests,
+                  unsigned flags, dm_kcopyd_notify_fn fn, void *context);
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_DM_KCOPYD_H */
index 653477021e4c545b9f4dcc983587ceb26eb11eac..69baf5a4f0a582cfeb061af5735e4a2d70e701e6 100644 (file)
@@ -117,7 +117,8 @@ struct task_struct;
 
 struct files_struct *get_files_struct(struct task_struct *);
 void put_files_struct(struct files_struct *fs);
-void reset_files_struct(struct task_struct *, struct files_struct *);
+void reset_files_struct(struct files_struct *);
+int unshare_files(struct files_struct **);
 
 extern struct kmem_cache *files_cachep;
 
index cc2be2cf7d4158108965ce5f9394595c68c651e0..d6d7c52055c69c633a8251181b278037aa7be166 100644 (file)
@@ -973,6 +973,7 @@ extern int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
 /* fs/locks.c */
 extern void locks_init_lock(struct file_lock *);
 extern void locks_copy_lock(struct file_lock *, struct file_lock *);
+extern void __locks_copy_lock(struct file_lock *, const struct file_lock *);
 extern void locks_remove_posix(struct file *, fl_owner_t);
 extern void locks_remove_flock(struct file *);
 extern void posix_test_lock(struct file *, struct file_lock *);
@@ -1308,7 +1309,7 @@ struct super_operations {
        int (*statfs) (struct dentry *, struct kstatfs *);
        int (*remount_fs) (struct super_block *, int *, char *);
        void (*clear_inode) (struct inode *);
-       void (*umount_begin) (struct vfsmount *, int);
+       void (*umount_begin) (struct super_block *);
 
        int (*show_options)(struct seq_file *, struct vfsmount *);
        int (*show_stats)(struct seq_file *, struct vfsmount *);
@@ -2033,9 +2034,6 @@ static inline ino_t parent_ino(struct dentry *dentry)
        return res;
 }
 
-/* kernel/fork.c */
-extern int unshare_files(void);
-
 /* Transaction based IO helpers */
 
 /*
diff --git a/include/linux/hdsmart.h b/include/linux/hdsmart.h
deleted file mode 100644 (file)
index 4f4faf9..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * linux/include/linux/hdsmart.h
- *
- * Copyright (C) 1999-2000     Michael Cornwell <cornwell@acm.org>
- * Copyright (C) 2000          Andre Hedrick <andre@linux-ide.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.
- *
- * You should have received a copy of the GNU General Public License
- * (for example /usr/src/linux/COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _LINUX_HDSMART_H
-#define _LINUX_HDSMART_H
-
-#ifndef __KERNEL__
-#define OFFLINE_FULL_SCAN              0
-#define SHORT_SELF_TEST                        1
-#define EXTEND_SELF_TEST               2
-#define SHORT_CAPTIVE_SELF_TEST                129
-#define EXTEND_CAPTIVE_SELF_TEST       130
-
-/* smart_attribute is the vendor specific in SFF-8035 spec */
-typedef struct ata_smart_attribute_s {
-       unsigned char                   id;
-       unsigned short                  status_flag;
-       unsigned char                   normalized;
-       unsigned char                   worse_normal;
-       unsigned char                   raw[6];
-       unsigned char                   reserv;
-} __attribute__ ((packed)) ata_smart_attribute_t;
-
-/* smart_values is format of the read drive Atrribute command */
-typedef struct ata_smart_values_s {
-       unsigned short                  revnumber;
-       ata_smart_attribute_t           vendor_attributes [30];
-        unsigned char                  offline_data_collection_status;
-        unsigned char                  self_test_exec_status;
-       unsigned short                  total_time_to_complete_off_line;
-       unsigned char                   vendor_specific_366;
-       unsigned char                   offline_data_collection_capability;
-       unsigned short                  smart_capability;
-       unsigned char                   errorlog_capability;
-       unsigned char                   vendor_specific_371;
-       unsigned char                   short_test_completion_time;
-       unsigned char                   extend_test_completion_time;
-       unsigned char                   reserved_374_385 [12];
-       unsigned char                   vendor_specific_386_509 [125];
-       unsigned char                   chksum;
-} __attribute__ ((packed)) ata_smart_values_t;
-
-/* Smart Threshold data structures */
-/* Vendor attribute of SMART Threshold */
-typedef struct ata_smart_threshold_entry_s {
-       unsigned char                   id;
-       unsigned char                   normalized_threshold;
-       unsigned char                   reserved[10];
-} __attribute__ ((packed)) ata_smart_threshold_entry_t;
-
-/* Format of Read SMART THreshold Command */
-typedef struct ata_smart_thresholds_s {
-       unsigned short                  revnumber;
-       ata_smart_threshold_entry_t     thres_entries[30];
-       unsigned char                   reserved[149];
-       unsigned char                   chksum;
-} __attribute__ ((packed)) ata_smart_thresholds_t;
-
-typedef struct ata_smart_errorlog_command_struct_s {
-       unsigned char                   devicecontrolreg;
-       unsigned char                   featuresreg;
-       unsigned char                   sector_count;
-       unsigned char                   sector_number;
-       unsigned char                   cylinder_low;
-       unsigned char                   cylinder_high;
-       unsigned char                   drive_head;
-       unsigned char                   commandreg;
-       unsigned int                    timestamp;
-} __attribute__ ((packed)) ata_smart_errorlog_command_struct_t;
-
-typedef struct ata_smart_errorlog_error_struct_s {
-       unsigned char                   error_condition;
-       unsigned char                   extended_error[14];
-       unsigned char                   state;
-       unsigned short                  timestamp;
-} __attribute__ ((packed)) ata_smart_errorlog_error_struct_t;
-
-typedef struct ata_smart_errorlog_struct_s {
-       ata_smart_errorlog_command_struct_t     commands[6];
-       ata_smart_errorlog_error_struct_t       error_struct;
-} __attribute__ ((packed)) ata_smart_errorlog_struct_t;
-
-typedef struct ata_smart_errorlog_s {
-       unsigned char                   revnumber;
-       unsigned char                   error_log_pointer;
-       ata_smart_errorlog_struct_t     errorlog_struct[5];
-       unsigned short                  ata_error_count;
-       unsigned short                  non_fatal_count;
-       unsigned short                  drive_timeout_count;
-       unsigned char                   reserved[53];
-       unsigned char                   chksum;
-} __attribute__ ((packed)) ata_smart_errorlog_t;
-
-typedef struct ata_smart_selftestlog_struct_s {
-       unsigned char                   selftestnumber;
-       unsigned char                   selfteststatus;
-       unsigned short                  timestamp;
-       unsigned char                   selftestfailurecheckpoint;
-       unsigned int                    lbafirstfailure;
-       unsigned char                   vendorspecific[15];
-} __attribute__ ((packed)) ata_smart_selftestlog_struct_t;
-
-typedef struct ata_smart_selftestlog_s {
-       unsigned short                  revnumber;
-       ata_smart_selftestlog_struct_t  selftest_struct[21];
-       unsigned char                   vendorspecific[2];
-       unsigned char                   mostrecenttest;
-       unsigned char                   resevered[2];
-       unsigned char                   chksum;
-} __attribute__ ((packed)) ata_smart_selftestlog_t;
-#endif /* __KERNEL__ */
-
-#endif /* _LINUX_HDSMART_H */
index 5f3e82ae901a94a54a7e99602dca5f06052191d4..32fd77bb4436977295ea6a6224088adaae20d6aa 100644 (file)
@@ -47,13 +47,6 @@ typedef unsigned char        byte;   /* used everywhere */
 #define ERROR_RESET    3       /* Reset controller every 4th retry */
 #define ERROR_RECAL    1       /* Recalibrate every 2nd retry */
 
-/*
- * Tune flags
- */
-#define IDE_TUNE_NOAUTO                2
-#define IDE_TUNE_AUTO          1
-#define IDE_TUNE_DEFAULT       0
-
 /*
  * state flags
  */
@@ -68,23 +61,30 @@ typedef unsigned char       byte;   /* used everywhere */
  */
 #define IDE_NR_PORTS           (10)
 
-#define IDE_DATA_OFFSET                (0)
-#define IDE_ERROR_OFFSET       (1)
-#define IDE_NSECTOR_OFFSET     (2)
-#define IDE_SECTOR_OFFSET      (3)
-#define IDE_LCYL_OFFSET                (4)
-#define IDE_HCYL_OFFSET                (5)
-#define IDE_SELECT_OFFSET      (6)
-#define IDE_STATUS_OFFSET      (7)
-#define IDE_CONTROL_OFFSET     (8)
-#define IDE_IRQ_OFFSET         (9)
-
-#define IDE_FEATURE_OFFSET     IDE_ERROR_OFFSET
-#define IDE_COMMAND_OFFSET     IDE_STATUS_OFFSET
-#define IDE_ALTSTATUS_OFFSET   IDE_CONTROL_OFFSET
-#define IDE_IREASON_OFFSET     IDE_NSECTOR_OFFSET
-#define IDE_BCOUNTL_OFFSET     IDE_LCYL_OFFSET
-#define IDE_BCOUNTH_OFFSET     IDE_HCYL_OFFSET
+struct ide_io_ports {
+       unsigned long   data_addr;
+
+       union {
+               unsigned long error_addr;       /*   read:  error */
+               unsigned long feature_addr;     /*  write: feature */
+       };
+
+       unsigned long   nsect_addr;
+       unsigned long   lbal_addr;
+       unsigned long   lbam_addr;
+       unsigned long   lbah_addr;
+
+       unsigned long   device_addr;
+
+       union {
+               unsigned long status_addr;      /* Â read: status Â */
+               unsigned long command_addr;     /* write: command */
+       };
+
+       unsigned long   ctl_addr;
+
+       unsigned long   irq_addr;
+};
 
 #define OK_STAT(stat,good,bad) (((stat)&((good)|(bad)))==(good))
 #define BAD_R_STAT             (BUSY_STAT   | ERR_STAT)
@@ -163,14 +163,17 @@ typedef u8 hwif_chipset_t;
  * Structure to hold all information about the location of this port
  */
 typedef struct hw_regs_s {
-       unsigned long   io_ports[IDE_NR_PORTS]; /* task file registers */
+       union {
+               struct ide_io_ports     io_ports;
+               unsigned long           io_ports_array[IDE_NR_PORTS];
+       };
+
        int             irq;                    /* our irq number */
        ide_ack_intr_t  *ack_intr;              /* acknowledge interrupt */
        hwif_chipset_t  chipset;
        struct device   *dev;
 } hw_regs_t;
 
-struct hwif_s * ide_find_port(unsigned long);
 void ide_init_port_data(struct hwif_s *, unsigned int);
 void ide_init_port_hw(struct hwif_s *, hw_regs_t *);
 
@@ -180,10 +183,10 @@ static inline void ide_std_init_ports(hw_regs_t *hw,
 {
        unsigned int i;
 
-       for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
-               hw->io_ports[i] = io_addr++;
+       for (i = 0; i <= 7; i++)
+               hw->io_ports_array[i] = io_addr++;
 
-       hw->io_ports[IDE_CONTROL_OFFSET] = ctl_addr;
+       hw->io_ports.ctl_addr = ctl_addr;
 }
 
 #include <asm/ide.h>
@@ -329,7 +332,6 @@ typedef struct ide_drive_s {
        unsigned atapi_overlap  : 1;    /* ATAPI overlap (not supported) */
        unsigned doorlocking    : 1;    /* for removable only: door lock/unlock works */
        unsigned nodma          : 1;    /* disallow DMA */
-       unsigned autotune       : 2;    /* 0=default, 1=autotune, 2=noautotune */
        unsigned remap_0_to_1   : 1;    /* 0=noremap, 1=remap 0->1 (for EZDrive) */
        unsigned blocked        : 1;    /* 1=powermanagment told us not to do anything, so sleep nicely */
        unsigned vdma           : 1;    /* 1=doing PIO over DMA 0=doing normal DMA */
@@ -388,6 +390,43 @@ typedef struct ide_drive_s {
 
 struct ide_port_info;
 
+struct ide_port_ops {
+       /* host specific initialization of devices on a port */
+       void    (*port_init_devs)(struct hwif_s *);
+       /* routine to program host for PIO mode */
+       void    (*set_pio_mode)(ide_drive_t *, const u8);
+       /* routine to program host for DMA mode */
+       void    (*set_dma_mode)(ide_drive_t *, const u8);
+       /* tweaks hardware to select drive */
+       void    (*selectproc)(ide_drive_t *);
+       /* chipset polling based on hba specifics */
+       int     (*reset_poll)(ide_drive_t *);
+       /* chipset specific changes to default for device-hba resets */
+       void    (*pre_reset)(ide_drive_t *);
+       /* routine to reset controller after a disk reset */
+       void    (*resetproc)(ide_drive_t *);
+       /* special host masking for drive selection */
+       void    (*maskproc)(ide_drive_t *, int);
+       /* check host's drive quirk list */
+       void    (*quirkproc)(ide_drive_t *);
+
+       u8      (*mdma_filter)(ide_drive_t *);
+       u8      (*udma_filter)(ide_drive_t *);
+
+       u8      (*cable_detect)(struct hwif_s *);
+};
+
+struct ide_dma_ops {
+       void    (*dma_host_set)(struct ide_drive_s *, int);
+       int     (*dma_setup)(struct ide_drive_s *);
+       void    (*dma_exec_cmd)(struct ide_drive_s *, u8);
+       void    (*dma_start)(struct ide_drive_s *);
+       int     (*dma_end)(struct ide_drive_s *);
+       int     (*dma_test_irq)(struct ide_drive_s *);
+       void    (*dma_lost_irq)(struct ide_drive_s *);
+       void    (*dma_timeout)(struct ide_drive_s *);
+};
+
 typedef struct hwif_s {
        struct hwif_s *next;            /* for linked-list in ide_hwgroup_t */
        struct hwif_s *mate;            /* other hwif from same PCI chip */
@@ -396,8 +435,8 @@ typedef struct hwif_s {
 
        char name[6];                   /* name of interface, eg. "ide0" */
 
-               /* task file registers for pata and sata */
-       unsigned long   io_ports[IDE_NR_PORTS];
+       struct ide_io_ports     io_ports;
+
        unsigned long   sata_scr[SATA_NR_PORTS];
 
        ide_drive_t     drives[MAX_DRIVES];     /* drive info */
@@ -421,38 +460,12 @@ typedef struct hwif_s {
 
        struct device *dev;
 
-       const struct ide_port_info *cds;        /* chipset device struct */
-
        ide_ack_intr_t *ack_intr;
 
        void (*rw_disk)(ide_drive_t *, struct request *);
 
-#if 0
-       ide_hwif_ops_t  *hwifops;
-#else
-       /* host specific initialization of devices on a port */
-       void    (*port_init_devs)(struct hwif_s *);
-       /* routine to program host for PIO mode */
-       void    (*set_pio_mode)(ide_drive_t *, const u8);
-       /* routine to program host for DMA mode */
-       void    (*set_dma_mode)(ide_drive_t *, const u8);
-       /* tweaks hardware to select drive */
-       void    (*selectproc)(ide_drive_t *);
-       /* chipset polling based on hba specifics */
-       int     (*reset_poll)(ide_drive_t *);
-       /* chipset specific changes to default for device-hba resets */
-       void    (*pre_reset)(ide_drive_t *);
-       /* routine to reset controller after a disk reset */
-       void    (*resetproc)(ide_drive_t *);
-       /* special host masking for drive selection */
-       void    (*maskproc)(ide_drive_t *, int);
-       /* check host's drive quirk list */
-       void    (*quirkproc)(ide_drive_t *);
-#endif
-       u8 (*mdma_filter)(ide_drive_t *);
-       u8 (*udma_filter)(ide_drive_t *);
-
-       u8 (*cable_detect)(struct hwif_s *);
+       const struct ide_port_ops       *port_ops;
+       const struct ide_dma_ops        *dma_ops;
 
        void (*ata_input_data)(ide_drive_t *, void *, u32);
        void (*ata_output_data)(ide_drive_t *, void *, u32);
@@ -460,15 +473,7 @@ typedef struct hwif_s {
        void (*atapi_input_bytes)(ide_drive_t *, void *, u32);
        void (*atapi_output_bytes)(ide_drive_t *, void *, u32);
 
-       void (*dma_host_set)(ide_drive_t *, int);
-       int (*dma_setup)(ide_drive_t *);
-       void (*dma_exec_cmd)(ide_drive_t *, u8);
-       void (*dma_start)(ide_drive_t *);
-       int (*ide_dma_end)(ide_drive_t *drive);
-       int (*ide_dma_test_irq)(ide_drive_t *drive);
        void (*ide_dma_clear_irq)(ide_drive_t *drive);
-       void (*dma_lost_irq)(ide_drive_t *drive);
-       void (*dma_timeout)(ide_drive_t *drive);
 
        void (*OUTB)(u8 addr, unsigned long port);
        void (*OUTBSYNC)(ide_drive_t *drive, u8 addr, unsigned long port);
@@ -515,14 +520,11 @@ typedef struct hwif_s {
        unsigned long   extra_base;     /* extra addr for dma ports */
        unsigned        extra_ports;    /* number of extra dma ports */
 
-       unsigned        noprobe    : 1; /* don't probe for this interface */
        unsigned        present    : 1; /* this interface exists */
        unsigned        serialized : 1; /* serialized all channel operation */
        unsigned        sharing_irq: 1; /* 1 = sharing irq with another hwif */
-       unsigned        reset      : 1; /* reset after probe */
        unsigned        sg_mapped  : 1; /* sg_table and sg_nents are ready */
        unsigned        mmio       : 1; /* host uses MMIO */
-       unsigned        straight8  : 1; /* Alan's straight 8 check */
 
        struct device           gendev;
        struct device           *portdev;
@@ -703,10 +705,6 @@ void ide_add_generic_settings(ide_drive_t *);
 read_proc_t proc_ide_read_capacity;
 read_proc_t proc_ide_read_geometry;
 
-#ifdef CONFIG_BLK_DEV_IDEPCI
-void ide_pci_create_host_proc(const char *, get_info_t *);
-#endif
-
 /*
  * Standard exit stuff:
  */
@@ -807,8 +805,21 @@ int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsig
 #ifndef _IDE_C
 extern ide_hwif_t      ide_hwifs[];            /* master data repository */
 #endif
+extern int ide_noacpi;
+extern int ide_acpigtf;
+extern int ide_acpionboot;
 extern int noautodma;
 
+extern int ide_vlb_clk;
+extern int ide_pci_clk;
+
+ide_hwif_t *ide_find_port_slot(const struct ide_port_info *);
+
+static inline ide_hwif_t *ide_find_port(void)
+{
+       return ide_find_port_slot(NULL);
+}
+
 extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs);
 int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
                             int uptodate, int nr_sectors);
@@ -1004,10 +1015,15 @@ void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, int, u8
 void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
-void ide_hwif_setup_dma(ide_hwif_t *, const struct ide_port_info *);
+int ide_pci_set_master(struct pci_dev *, const char *);
+unsigned long ide_pci_dma_base(ide_hwif_t *, const struct ide_port_info *);
+int ide_hwif_setup_dma(ide_hwif_t *, const struct ide_port_info *);
 #else
-static inline void ide_hwif_setup_dma(ide_hwif_t *hwif,
-                                     const struct ide_port_info *d) { }
+static inline int ide_hwif_setup_dma(ide_hwif_t *hwif,
+                                    const struct ide_port_info *d)
+{
+       return -EINVAL;
+}
 #endif
 
 extern void default_hwif_iops(ide_hwif_t *);
@@ -1027,8 +1043,8 @@ enum {
        IDE_HFLAG_SINGLE                = (1 << 1),
        /* don't use legacy PIO blacklist */
        IDE_HFLAG_PIO_NO_BLACKLIST      = (1 << 2),
-       /* don't use conservative PIO "downgrade" */
-       IDE_HFLAG_PIO_NO_DOWNGRADE      = (1 << 3),
+       /* set for the second port of QD65xx */
+       IDE_HFLAG_QD_2ND_PORT           = (1 << 3),
        /* use PIO8/9 for prefetch off/on */
        IDE_HFLAG_ABUSE_PREFETCH        = (1 << 4),
        /* use PIO6/7 for fast-devsel off/on */
@@ -1050,14 +1066,12 @@ enum {
        IDE_HFLAG_VDMA                  = (1 << 11),
        /* ATAPI DMA is unsupported */
        IDE_HFLAG_NO_ATAPI_DMA          = (1 << 12),
-       /* set if host is a "bootable" controller */
-       IDE_HFLAG_BOOTABLE              = (1 << 13),
+       /* set if host is a "non-bootable" controller */
+       IDE_HFLAG_NON_BOOTABLE          = (1 << 13),
        /* host doesn't support DMA */
        IDE_HFLAG_NO_DMA                = (1 << 14),
        /* check if host is PCI IDE device before allowing DMA */
        IDE_HFLAG_NO_AUTODMA            = (1 << 15),
-       /* don't autotune PIO */
-       IDE_HFLAG_NO_AUTOTUNE           = (1 << 16),
        /* host is CS5510/CS5520 */
        IDE_HFLAG_CS5520                = IDE_HFLAG_VDMA,
        /* no LBA48 */
@@ -1079,8 +1093,8 @@ enum {
        /* unmask IRQs */
        IDE_HFLAG_UNMASK_IRQS           = (1 << 25),
        IDE_HFLAG_ABUSE_SET_DMA_MODE    = (1 << 26),
-       /* host is CY82C693 */
-       IDE_HFLAG_CY82C693              = (1 << 27),
+       /* serialize ports if DMA is possible (for sl82c105) */
+       IDE_HFLAG_SERIALIZE_DMA         = (1 << 27),
        /* force host out of "simplex" mode */
        IDE_HFLAG_CLEAR_SIMPLEX         = (1 << 28),
        /* DSC overlap is unsupported */
@@ -1092,9 +1106,9 @@ enum {
 };
 
 #ifdef CONFIG_BLK_DEV_OFFBOARD
-# define IDE_HFLAG_OFF_BOARD   IDE_HFLAG_BOOTABLE
-#else
 # define IDE_HFLAG_OFF_BOARD   0
+#else
+# define IDE_HFLAG_OFF_BOARD   IDE_HFLAG_NON_BOOTABLE
 #endif
 
 struct ide_port_info {
@@ -1102,10 +1116,14 @@ struct ide_port_info {
        unsigned int            (*init_chipset)(struct pci_dev *, const char *);
        void                    (*init_iops)(ide_hwif_t *);
        void                    (*init_hwif)(ide_hwif_t *);
-       void                    (*init_dma)(ide_hwif_t *, unsigned long);
+       int                     (*init_dma)(ide_hwif_t *,
+                                           const struct ide_port_info *);
+
+       const struct ide_port_ops       *port_ops;
+       const struct ide_dma_ops        *dma_ops;
+
        ide_pci_enablebit_t     enablebits[2];
        hwif_chipset_t          chipset;
-       u8                      extra;
        u32                     host_flags;
        u8                      pio_mask;
        u8                      swdma_mask;
@@ -1152,13 +1170,16 @@ void ide_destroy_dmatable(ide_drive_t *);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_SFF
 extern int ide_build_dmatable(ide_drive_t *, struct request *);
-extern int ide_release_dma(ide_hwif_t *);
-extern void ide_setup_dma(ide_hwif_t *, unsigned long);
+int ide_allocate_dma_engine(ide_hwif_t *);
+void ide_release_dma_engine(ide_hwif_t *);
+void ide_setup_dma(ide_hwif_t *, unsigned long);
 
 void ide_dma_host_set(ide_drive_t *, int);
 extern int ide_dma_setup(ide_drive_t *);
+void ide_dma_exec_cmd(ide_drive_t *, u8);
 extern void ide_dma_start(ide_drive_t *);
 extern int __ide_dma_end(ide_drive_t *);
+int ide_dma_test_irq(ide_drive_t *);
 extern void ide_dma_lost_irq(ide_drive_t *);
 extern void ide_dma_timeout(ide_drive_t *);
 #endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
@@ -1176,7 +1197,7 @@ static inline void ide_check_dma_crc(ide_drive_t *drive) { ; }
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
 #ifndef CONFIG_BLK_DEV_IDEDMA_SFF
-static inline void ide_release_dma(ide_hwif_t *drive) {;}
+static inline void ide_release_dma_engine(ide_hwif_t *hwif) { ; }
 #endif
 
 #ifdef CONFIG_BLK_DEV_IDEACPI
@@ -1196,17 +1217,18 @@ static inline void ide_acpi_set_state(ide_hwif_t *hwif, int on) {}
 #endif
 
 void ide_remove_port_from_hwgroup(ide_hwif_t *);
-extern int ide_hwif_request_regions(ide_hwif_t *hwif);
-extern void ide_hwif_release_regions(ide_hwif_t* hwif);
-void ide_unregister(unsigned int);
+void ide_unregister(ide_hwif_t *);
 
 void ide_register_region(struct gendisk *);
 void ide_unregister_region(struct gendisk *);
 
 void ide_undecoded_slave(ide_drive_t *);
 
+void ide_port_apply_params(ide_hwif_t *);
+
 int ide_device_add_all(u8 *idx, const struct ide_port_info *);
 int ide_device_add(u8 idx[4], const struct ide_port_info *);
+int ide_legacy_device_add(const struct ide_port_info *, unsigned long);
 void ide_port_unregister_devices(ide_hwif_t *);
 void ide_port_scan(ide_hwif_t *);
 
@@ -1315,29 +1337,28 @@ static inline void ide_set_irq(ide_drive_t *drive, int on)
 {
        ide_hwif_t *hwif = drive->hwif;
 
-       hwif->OUTB(drive->ctl | (on ? 0 : 2),
-                  hwif->io_ports[IDE_CONTROL_OFFSET]);
+       hwif->OUTB(drive->ctl | (on ? 0 : 2), hwif->io_ports.ctl_addr);
 }
 
 static inline u8 ide_read_status(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
 
-       return hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+       return hwif->INB(hwif->io_ports.status_addr);
 }
 
 static inline u8 ide_read_altstatus(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
 
-       return hwif->INB(hwif->io_ports[IDE_CONTROL_OFFSET]);
+       return hwif->INB(hwif->io_ports.ctl_addr);
 }
 
 static inline u8 ide_read_error(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
 
-       return hwif->INB(hwif->io_ports[IDE_ERROR_OFFSET]);
+       return hwif->INB(hwif->io_ports.error_addr);
 }
 
 /*
@@ -1350,7 +1371,7 @@ static inline void ide_atapi_discard_data(ide_drive_t *drive, unsigned bcount)
 
        /* FIXME: use ->atapi_input_bytes */
        while (bcount--)
-               (void)hwif->INB(hwif->io_ports[IDE_DATA_OFFSET]);
+               (void)hwif->INB(hwif->io_ports.data_addr);
 }
 
 static inline void ide_atapi_write_zeros(ide_drive_t *drive, unsigned bcount)
@@ -1359,7 +1380,7 @@ static inline void ide_atapi_write_zeros(ide_drive_t *drive, unsigned bcount)
 
        /* FIXME: use ->atapi_output_bytes */
        while (bcount--)
-               hwif->OUTB(0, hwif->io_ports[IDE_DATA_OFFSET]);
+               hwif->OUTB(0, hwif->io_ports.data_addr);
 }
 
 #endif /* _IDE_H */
index cae2c35d1206593bc6a3154e44ae47ef1db6fb75..28a094fcfe201f0a05a344011f338cf7c3c7dc72 100644 (file)
@@ -1025,10 +1025,6 @@ struct ff_effect {
  * @node: used to place the device onto input_dev_list
  */
 struct input_dev {
-       /* private: */
-       void *private;  /* do not use */
-       /* public: */
-
        const char *name;
        const char *phys;
        const char *uniq;
@@ -1238,12 +1234,12 @@ static inline void input_put_device(struct input_dev *dev)
 
 static inline void *input_get_drvdata(struct input_dev *dev)
 {
-       return dev->private;
+       return dev_get_drvdata(&dev->dev);
 }
 
 static inline void input_set_drvdata(struct input_dev *dev, void *data)
 {
-       dev->private = data;
+       dev_set_drvdata(&dev->dev, data);
 }
 
 int __must_check input_register_device(struct input_dev *);
index 65c2d70853e96557dc13c3f8e0a2e1420b4ccbf0..a3c984d780f0144422da0e0e9a4a754dc208510f 100644 (file)
@@ -33,6 +33,7 @@ struct keyboard_notifier_param {
        struct vc_data *vc;     /* VC on which the keyboard press was done */
        int down;               /* Pressure of the key? */
        int shift;              /* Current shift mask */
+       int ledstate;           /* Current led state */
        unsigned int value;     /* keycode, unicode value or keysym */
 };
 
index c1ec04fd000d42d27d310ce79c92944f09d63c5f..a281afeddfbb0e2a4b9dd8747cc7afdffb271b2e 100644 (file)
@@ -8,11 +8,18 @@
  */
 
 #include <asm/types.h>
+#include <linux/compiler.h>
 #include <linux/ioctl.h>
 #include <asm/kvm.h>
 
 #define KVM_API_VERSION 12
 
+/* for KVM_TRACE_ENABLE */
+struct kvm_user_trace_setup {
+       __u32 buf_size; /* sub_buffer size of each per-cpu */
+       __u32 buf_nr; /* the number of sub_buffers of each per-cpu */
+};
+
 /* for KVM_CREATE_MEMORY_REGION */
 struct kvm_memory_region {
        __u32 slot;
@@ -73,6 +80,9 @@ struct kvm_irqchip {
 #define KVM_EXIT_INTR             10
 #define KVM_EXIT_SET_TPR          11
 #define KVM_EXIT_TPR_ACCESS       12
+#define KVM_EXIT_S390_SIEIC       13
+#define KVM_EXIT_S390_RESET       14
+#define KVM_EXIT_DCR              15
 
 /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
 struct kvm_run {
@@ -137,6 +147,27 @@ struct kvm_run {
                        __u32 is_write;
                        __u32 pad;
                } tpr_access;
+               /* KVM_EXIT_S390_SIEIC */
+               struct {
+                       __u8 icptcode;
+                       __u64 mask; /* psw upper half */
+                       __u64 addr; /* psw lower half */
+                       __u16 ipa;
+                       __u32 ipb;
+               } s390_sieic;
+               /* KVM_EXIT_S390_RESET */
+#define KVM_S390_RESET_POR       1
+#define KVM_S390_RESET_CLEAR     2
+#define KVM_S390_RESET_SUBSYSTEM 4
+#define KVM_S390_RESET_CPU_INIT  8
+#define KVM_S390_RESET_IPL       16
+               __u64 s390_reset_flags;
+               /* KVM_EXIT_DCR */
+               struct {
+                       __u32 dcrn;
+                       __u32 data;
+                       __u8  is_write;
+               } dcr;
                /* Fix the size of the union. */
                char padding[256];
        };
@@ -204,6 +235,74 @@ struct kvm_vapic_addr {
        __u64 vapic_addr;
 };
 
+/* for KVM_SET_MPSTATE */
+
+#define KVM_MP_STATE_RUNNABLE          0
+#define KVM_MP_STATE_UNINITIALIZED     1
+#define KVM_MP_STATE_INIT_RECEIVED     2
+#define KVM_MP_STATE_HALTED            3
+#define KVM_MP_STATE_SIPI_RECEIVED     4
+
+struct kvm_mp_state {
+       __u32 mp_state;
+};
+
+struct kvm_s390_psw {
+       __u64 mask;
+       __u64 addr;
+};
+
+/* valid values for type in kvm_s390_interrupt */
+#define KVM_S390_SIGP_STOP             0xfffe0000u
+#define KVM_S390_PROGRAM_INT           0xfffe0001u
+#define KVM_S390_SIGP_SET_PREFIX       0xfffe0002u
+#define KVM_S390_RESTART               0xfffe0003u
+#define KVM_S390_INT_VIRTIO            0xffff2603u
+#define KVM_S390_INT_SERVICE           0xffff2401u
+#define KVM_S390_INT_EMERGENCY         0xffff1201u
+
+struct kvm_s390_interrupt {
+       __u32 type;
+       __u32 parm;
+       __u64 parm64;
+};
+
+#define KVM_TRC_SHIFT           16
+/*
+ * kvm trace categories
+ */
+#define KVM_TRC_ENTRYEXIT       (1 << KVM_TRC_SHIFT)
+#define KVM_TRC_HANDLER         (1 << (KVM_TRC_SHIFT + 1)) /* only 12 bits */
+
+/*
+ * kvm trace action
+ */
+#define KVM_TRC_VMENTRY         (KVM_TRC_ENTRYEXIT + 0x01)
+#define KVM_TRC_VMEXIT          (KVM_TRC_ENTRYEXIT + 0x02)
+#define KVM_TRC_PAGE_FAULT      (KVM_TRC_HANDLER + 0x01)
+
+#define KVM_TRC_HEAD_SIZE       12
+#define KVM_TRC_CYCLE_SIZE      8
+#define KVM_TRC_EXTRA_MAX       7
+
+/* This structure represents a single trace buffer record. */
+struct kvm_trace_rec {
+       __u32 event:28;
+       __u32 extra_u32:3;
+       __u32 cycle_in:1;
+       __u32 pid;
+       __u32 vcpu_id;
+       union {
+               struct {
+                       __u32 cycle_lo, cycle_hi;
+                       __u32 extra_u32[KVM_TRC_EXTRA_MAX];
+               } cycle;
+               struct {
+                       __u32 extra_u32[KVM_TRC_EXTRA_MAX];
+               } nocycle;
+       } u;
+};
+
 #define KVMIO 0xAE
 
 /*
@@ -212,6 +311,8 @@ struct kvm_vapic_addr {
 #define KVM_GET_API_VERSION       _IO(KVMIO,   0x00)
 #define KVM_CREATE_VM             _IO(KVMIO,   0x01) /* returns a VM fd */
 #define KVM_GET_MSR_INDEX_LIST    _IOWR(KVMIO, 0x02, struct kvm_msr_list)
+
+#define KVM_S390_ENABLE_SIE       _IO(KVMIO,   0x06)
 /*
  * Check if a kvm extension is available.  Argument is extension number,
  * return is 1 (yes) or 0 (no, sorry).
@@ -222,7 +323,12 @@ struct kvm_vapic_addr {
  */
 #define KVM_GET_VCPU_MMAP_SIZE    _IO(KVMIO,   0x04) /* in bytes */
 #define KVM_GET_SUPPORTED_CPUID   _IOWR(KVMIO, 0x05, struct kvm_cpuid2)
-
+/*
+ * ioctls for kvm trace
+ */
+#define KVM_TRACE_ENABLE          _IOW(KVMIO, 0x06, struct kvm_user_trace_setup)
+#define KVM_TRACE_PAUSE           _IO(KVMIO,  0x07)
+#define KVM_TRACE_DISABLE         _IO(KVMIO,  0x08)
 /*
  * Extension capability list.
  */
@@ -233,6 +339,13 @@ struct kvm_vapic_addr {
 #define KVM_CAP_SET_TSS_ADDR 4
 #define KVM_CAP_VAPIC 6
 #define KVM_CAP_EXT_CPUID 7
+#define KVM_CAP_CLOCKSOURCE 8
+#define KVM_CAP_NR_VCPUS 9       /* returns max vcpus per vm */
+#define KVM_CAP_NR_MEMSLOTS 10   /* returns max memory slots per vm */
+#define KVM_CAP_PIT 11
+#define KVM_CAP_NOP_IO_DELAY 12
+#define KVM_CAP_PV_MMU 13
+#define KVM_CAP_MP_STATE 14
 
 /*
  * ioctls for VM fds
@@ -255,6 +368,9 @@ struct kvm_vapic_addr {
 #define KVM_IRQ_LINE             _IOW(KVMIO, 0x61, struct kvm_irq_level)
 #define KVM_GET_IRQCHIP                  _IOWR(KVMIO, 0x62, struct kvm_irqchip)
 #define KVM_SET_IRQCHIP                  _IOR(KVMIO,  0x63, struct kvm_irqchip)
+#define KVM_CREATE_PIT           _IO(KVMIO,  0x64)
+#define KVM_GET_PIT              _IOWR(KVMIO, 0x65, struct kvm_pit_state)
+#define KVM_SET_PIT              _IOR(KVMIO,  0x66, struct kvm_pit_state)
 
 /*
  * ioctls for vcpu fds
@@ -281,5 +397,17 @@ struct kvm_vapic_addr {
 #define KVM_TPR_ACCESS_REPORTING  _IOWR(KVMIO,  0x92, struct kvm_tpr_access_ctl)
 /* Available with KVM_CAP_VAPIC */
 #define KVM_SET_VAPIC_ADDR        _IOW(KVMIO,  0x93, struct kvm_vapic_addr)
+/* valid for virtual machine (for floating interrupt)_and_ vcpu */
+#define KVM_S390_INTERRUPT        _IOW(KVMIO,  0x94, struct kvm_s390_interrupt)
+/* store status for s390 */
+#define KVM_S390_STORE_STATUS_NOADDR    (-1ul)
+#define KVM_S390_STORE_STATUS_PREFIXED  (-2ul)
+#define KVM_S390_STORE_STATUS    _IOW(KVMIO,  0x95, unsigned long)
+/* initial ipl psw for s390 */
+#define KVM_S390_SET_INITIAL_PSW  _IOW(KVMIO,  0x96, struct kvm_s390_psw)
+/* initial reset for s390 */
+#define KVM_S390_INITIAL_RESET    _IO(KVMIO,  0x97)
+#define KVM_GET_MP_STATE          _IOR(KVMIO,  0x98, struct kvm_mp_state)
+#define KVM_SET_MP_STATE          _IOW(KVMIO,  0x99, struct kvm_mp_state)
 
 #endif
index 928b0d59e9ba07d64686975f5db6022ad608ef8d..398978972b7a639cb6cf0b14b974971db0addd76 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/preempt.h>
+#include <linux/marker.h>
 #include <asm/signal.h>
 
 #include <linux/kvm.h>
 
 #include <asm/kvm_host.h>
 
-#define KVM_MAX_VCPUS 4
-#define KVM_MEMORY_SLOTS 8
-/* memory slots that does not exposed to userspace */
-#define KVM_PRIVATE_MEM_SLOTS 4
-
-#define KVM_PIO_PAGE_OFFSET 1
-
 /*
  * vcpu->requests bit members
  */
 #define KVM_REQ_TLB_FLUSH          0
 #define KVM_REQ_MIGRATE_TIMER      1
 #define KVM_REQ_REPORT_TPR_ACCESS  2
+#define KVM_REQ_MMU_RELOAD         3
+#define KVM_REQ_TRIPLE_FAULT       4
 
 struct kvm_vcpu;
 extern struct kmem_cache *kvm_vcpu_cache;
 
-struct kvm_guest_debug {
-       int enabled;
-       unsigned long bp[4];
-       int singlestep;
-};
-
 /*
  * It would be nice to use something smarter than a linear search, TBD...
  * Thankfully we dont expect many devices to register (famous last words :),
@@ -67,7 +57,9 @@ void kvm_io_bus_register_dev(struct kvm_io_bus *bus,
 
 struct kvm_vcpu {
        struct kvm *kvm;
+#ifdef CONFIG_PREEMPT_NOTIFIERS
        struct preempt_notifier preempt_notifier;
+#endif
        int vcpu_id;
        struct mutex mutex;
        int   cpu;
@@ -100,6 +92,10 @@ struct kvm_memory_slot {
        unsigned long flags;
        unsigned long *rmap;
        unsigned long *dirty_bitmap;
+       struct {
+               unsigned long rmap_pde;
+               int write_count;
+       } *lpage_info;
        unsigned long userspace_addr;
        int user_alloc;
 };
@@ -114,11 +110,11 @@ struct kvm {
                                        KVM_PRIVATE_MEM_SLOTS];
        struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
        struct list_head vm_list;
-       struct file *filp;
        struct kvm_io_bus mmio_bus;
        struct kvm_io_bus pio_bus;
        struct kvm_vm_stat stat;
        struct kvm_arch arch;
+       atomic_t users_count;
 };
 
 /* The guest did something we don't support. */
@@ -145,14 +141,19 @@ int kvm_init(void *opaque, unsigned int vcpu_size,
                  struct module *module);
 void kvm_exit(void);
 
+void kvm_get_kvm(struct kvm *kvm);
+void kvm_put_kvm(struct kvm *kvm);
+
 #define HPA_MSB ((sizeof(hpa_t) * 8) - 1)
 #define HPA_ERR_MASK ((hpa_t)1 << HPA_MSB)
 static inline int is_error_hpa(hpa_t hpa) { return hpa >> HPA_MSB; }
 struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva);
 
 extern struct page *bad_page;
+extern pfn_t bad_pfn;
 
 int is_error_page(struct page *page);
+int is_error_pfn(pfn_t pfn);
 int kvm_is_error_hva(unsigned long addr);
 int kvm_set_memory_region(struct kvm *kvm,
                          struct kvm_userspace_memory_region *mem,
@@ -166,8 +167,19 @@ int kvm_arch_set_memory_region(struct kvm *kvm,
                                int user_alloc);
 gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn);
 struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn);
+unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn);
 void kvm_release_page_clean(struct page *page);
 void kvm_release_page_dirty(struct page *page);
+void kvm_set_page_dirty(struct page *page);
+void kvm_set_page_accessed(struct page *page);
+
+pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn);
+void kvm_release_pfn_dirty(pfn_t);
+void kvm_release_pfn_clean(pfn_t pfn);
+void kvm_set_pfn_dirty(pfn_t pfn);
+void kvm_set_pfn_accessed(pfn_t pfn);
+void kvm_get_pfn(pfn_t pfn);
+
 int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset,
                        int len);
 int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data,
@@ -188,6 +200,7 @@ void kvm_resched(struct kvm_vcpu *vcpu);
 void kvm_load_guest_fpu(struct kvm_vcpu *vcpu);
 void kvm_put_guest_fpu(struct kvm_vcpu *vcpu);
 void kvm_flush_remote_tlbs(struct kvm *kvm);
+void kvm_reload_remote_mmus(struct kvm *kvm);
 
 long kvm_arch_dev_ioctl(struct file *filp,
                        unsigned int ioctl, unsigned long arg);
@@ -223,6 +236,10 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
                                  struct kvm_sregs *sregs);
 int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
                                  struct kvm_sregs *sregs);
+int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
+                                   struct kvm_mp_state *mp_state);
+int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
+                                   struct kvm_mp_state *mp_state);
 int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
                                    struct kvm_debug_guest *dbg);
 int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run);
@@ -255,6 +272,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm);
 
 int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
 int kvm_cpu_has_interrupt(struct kvm_vcpu *v);
+int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu);
 void kvm_vcpu_kick(struct kvm_vcpu *vcpu);
 
 static inline void kvm_guest_enter(void)
@@ -296,5 +314,18 @@ struct kvm_stats_debugfs_item {
        struct dentry *dentry;
 };
 extern struct kvm_stats_debugfs_item debugfs_entries[];
+extern struct dentry *kvm_debugfs_dir;
+
+#ifdef CONFIG_KVM_TRACE
+int kvm_trace_ioctl(unsigned int ioctl, unsigned long arg);
+void kvm_trace_cleanup(void);
+#else
+static inline
+int kvm_trace_ioctl(unsigned int ioctl, unsigned long arg)
+{
+       return -EINVAL;
+}
+#define kvm_trace_cleanup() ((void)0)
+#endif
 
 #endif
index 5497aac0d2f829d4efe3df98f8c34496d947243f..3ddce03766caf5796f84f71bd7462f117c9a064a 100644 (file)
 
 /* Return values for hypercalls */
 #define KVM_ENOSYS             1000
+#define KVM_EFAULT             EFAULT
+#define KVM_E2BIG              E2BIG
 
-#define KVM_HC_VAPIC_POLL_IRQ            1
+#define KVM_HC_VAPIC_POLL_IRQ          1
+#define KVM_HC_MMU_OP                  2
 
 /*
  * hypercalls use architecture specific
 #include <asm/kvm_para.h>
 
 #ifdef __KERNEL__
+#ifdef CONFIG_KVM_GUEST
+void __init kvm_guest_init(void);
+#else
+#define kvm_guest_init() do { } while (0)
+#endif
+
 static inline int kvm_para_has_feature(unsigned int feature)
 {
        if (kvm_arch_para_features() & (1UL << feature))
index 1c4e46decb226658a5d35b36444bf21f6a39fd6d..9b6f395c9625e13237abd15a9cb41150a34f48d0 100644 (file)
@@ -38,6 +38,8 @@ typedef unsigned long  hva_t;
 typedef u64            hpa_t;
 typedef unsigned long  hfn_t;
 
+typedef hfn_t pfn_t;
+
 struct kvm_pio_request {
        unsigned long count;
        int cur_count;
index b07e3d400bd6b6ad91d2465a76285fc80b6b444d..519df72e939d30a4355747aa4cea1140b5c3bef9 100644 (file)
@@ -35,8 +35,11 @@ struct led_classdev {
 #define LED_SUSPENDED          (1 << 0)
 
        /* Set LED brightness level */
+       /* Must not sleep, use a workqueue if needed */
        void            (*brightness_set)(struct led_classdev *led_cdev,
                                          enum led_brightness brightness);
+       /* Get LED brightness level */
+       enum led_brightness (*brightness_get)(struct led_classdev *led_cdev);
 
        /* Activate hardware accelerated blink */
        int             (*blink_set)(struct led_classdev *led_cdev,
@@ -126,6 +129,9 @@ struct gpio_led {
 struct gpio_led_platform_data {
        int             num_leds;
        struct gpio_led *leds;
+       int             (*gpio_blink_set)(unsigned gpio,
+                                       unsigned long *delay_on,
+                                       unsigned long *delay_off);
 };
 
 
index 07ed56f7a767bfda737db92a1b21318cb2a4f033..395a523d8c30c157985a48789016efea659c1196 100644 (file)
@@ -847,7 +847,6 @@ static inline int ata_port_is_dummy(struct ata_port *ap)
        return ap->ops == &ata_dummy_port_ops;
 }
 
-extern void sata_print_link_status(struct ata_link *link);
 extern void ata_port_probe(struct ata_port *);
 extern int sata_set_spd(struct ata_link *link);
 extern int ata_std_prereset(struct ata_link *link, unsigned long deadline);
index 94649a8da01403975c0c24e657f8062b9ec5dc80..102d928f7206b4bce0e242c8779b2de01117e8d5 100644 (file)
@@ -194,7 +194,7 @@ void                  nsm_release(struct nsm_handle *);
  * This is used in garbage collection and resource reclaim
  * A return value != 0 means destroy the lock/block/share
  */
-typedef int      (*nlm_host_match_fn_t)(struct nlm_host *cur, struct nlm_host *ref);
+typedef int      (*nlm_host_match_fn_t)(void *cur, struct nlm_host *ref);
 
 /*
  * Server-side lock handling
@@ -220,6 +220,12 @@ void                 nlmsvc_mark_resources(void);
 void             nlmsvc_free_host_resources(struct nlm_host *);
 void             nlmsvc_invalidate_all(void);
 
+/*
+ * Cluster failover support
+ */
+int           nlmsvc_unlock_all_by_sb(struct super_block *sb);
+int           nlmsvc_unlock_all_by_ip(__be32 server_addr);
+
 static inline struct inode *nlmsvc_file_inode(struct nlm_file *file)
 {
        return file->f_file->f_path.dentry->d_inode;
index ff7df1a2222fea4d5d5056280a0fba76eb84aab9..9fa1a8002ce206f27d5bd45ea916063fa6d6c9ad 100644 (file)
@@ -208,6 +208,38 @@ struct mlx4_mtt {
        int                     page_shift;
 };
 
+enum {
+       MLX4_DB_PER_PAGE = PAGE_SIZE / 4
+};
+
+struct mlx4_db_pgdir {
+       struct list_head        list;
+       DECLARE_BITMAP(order0, MLX4_DB_PER_PAGE);
+       DECLARE_BITMAP(order1, MLX4_DB_PER_PAGE / 2);
+       unsigned long          *bits[2];
+       __be32                 *db_page;
+       dma_addr_t              db_dma;
+};
+
+struct mlx4_ib_user_db_page;
+
+struct mlx4_db {
+       __be32                  *db;
+       union {
+               struct mlx4_db_pgdir            *pgdir;
+               struct mlx4_ib_user_db_page     *user_page;
+       }                       u;
+       dma_addr_t              dma;
+       int                     index;
+       int                     order;
+};
+
+struct mlx4_hwq_resources {
+       struct mlx4_db          db;
+       struct mlx4_mtt         mtt;
+       struct mlx4_buf         buf;
+};
+
 struct mlx4_mr {
        struct mlx4_mtt         mtt;
        u64                     iova;
@@ -341,6 +373,14 @@ int mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
 int mlx4_buf_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
                       struct mlx4_buf *buf);
 
+int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, int order);
+void mlx4_db_free(struct mlx4_dev *dev, struct mlx4_db *db);
+
+int mlx4_alloc_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres,
+                      int size, int max_direct);
+void mlx4_free_hwq_res(struct mlx4_dev *mdev, struct mlx4_hwq_resources *wqres,
+                      int size);
+
 int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
                  struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq);
 void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq);
index a5e43febee4fa550a6a4a9d145ed0c893acd76f8..7f128b266faa39044cc85e4f7175aed51664fe16 100644 (file)
@@ -296,6 +296,10 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
 int mlx4_qp_query(struct mlx4_dev *dev, struct mlx4_qp *qp,
                  struct mlx4_qp_context *context);
 
+int mlx4_qp_to_ready(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
+                    struct mlx4_qp_context *context,
+                    struct mlx4_qp *qp, enum mlx4_qp_state *qp_state);
+
 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 b695875d63e308bcc9086e5889c0040438f0a363..286d315216053502ce5ab9bb16b51c118cdf9d84 100644 (file)
@@ -1229,6 +1229,7 @@ void vmemmap_verify(pte_t *, int, unsigned long, unsigned long);
 int vmemmap_populate_basepages(struct page *start_page,
                                                unsigned long pages, int node);
 int vmemmap_populate(struct page *start_page, unsigned long pages, int node);
+void vmemmap_populate_print_last(void);
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MM_H */
index 6977780e548f96809a2c5df708490f7bae81bff0..85fd041d44ad30ca9fea26eef7dfafb164d611f2 100644 (file)
@@ -57,6 +57,11 @@ extern char inftlmountrev[];
 void INFTL_dumptables(struct INFTLrecord *s);
 void INFTL_dumpVUchains(struct INFTLrecord *s);
 
+int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+                  size_t *retlen, uint8_t *buf);
+int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+                   size_t *retlen, uint8_t *buf);
+
 #endif /* __KERNEL__ */
 
 #endif /* __MTD_INFTL_H__ */
index bcf2fb3fa4a786300ca2a3d23e470bd25843faa2..001eec50cac6d12c12e3362ef1ca9687400357b8 100644 (file)
@@ -43,6 +43,11 @@ struct NFTLrecord {
 int NFTL_mount(struct NFTLrecord *s);
 int NFTL_formatblock(struct NFTLrecord *s, int block);
 
+int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+                 size_t *retlen, uint8_t *buf);
+int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+                  size_t *retlen, uint8_t *buf);
+
 #ifndef NFTL_MAJOR
 #define NFTL_MAJOR 93
 #endif
index fd0a260e070b483b7be93288d088367949366b47..9aa2a9149b583991c75054ffd15b583b8e540f3e 100644 (file)
@@ -187,4 +187,7 @@ struct onenand_manufacturers {
         char *name;
 };
 
+int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
+                        struct mtd_oob_ops *ops);
+
 #endif /* __LINUX_MTD_ONENAND_H */
index 9667863bd7e3c95496bf0cd0b47e1e589b5ed9ca..0e37ad07bce2bb4895d9913350958d80016b83d5 100644 (file)
@@ -21,8 +21,9 @@
 #define PLATRAM_RW (1)
 
 struct platdata_mtd_ram {
-       char                    *mapname;
-       char                   **probes;
+       const char              *mapname;
+       const char              **map_probes;
+       const char              **probes;
        struct mtd_partition    *partitions;
        int                      nr_partitions;
        int                      bankwidth;
index 21ee440dd3e768eb2bbb1e72f3a33d54c31b69da..41d30c9c9de6e4b33045d232239f0366d2349916 100644 (file)
@@ -329,7 +329,7 @@ extern struct timeval       nfssvc_boot;
 (FATTR4_WORD0_SIZE              | FATTR4_WORD0_ACL                                         )
 #define NFSD_WRITEABLE_ATTRS_WORD1                                                          \
 (FATTR4_WORD1_MODE              | FATTR4_WORD1_OWNER         | FATTR4_WORD1_OWNER_GROUP     \
- | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_METADATA | FATTR4_WORD1_TIME_MODIFY_SET)
+ | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET)
 
 #endif /* CONFIG_NFSD_V4 */
 
index 779cbcd65f62d50ae56b897deff6adca44496cad..02df20f085fe9e89637affb8cb880d2a1f153628 100644 (file)
@@ -379,6 +379,18 @@ struct phy_driver {
 };
 #define to_phy_driver(d) container_of(d, struct phy_driver, driver)
 
+#define PHY_ANY_ID "MATCH ANY PHY"
+#define PHY_ANY_UID 0xffffffff
+
+/* A Structure for boards to register fixups with the PHY Lib */
+struct phy_fixup {
+       struct list_head list;
+       char bus_id[BUS_ID_SIZE];
+       u32 phy_uid;
+       u32 phy_uid_mask;
+       int (*run)(struct phy_device *phydev);
+};
+
 int phy_read(struct phy_device *phydev, u16 regnum);
 int phy_write(struct phy_device *phydev, u16 regnum, u16 val);
 int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id);
@@ -386,8 +398,8 @@ struct phy_device* get_phy_device(struct mii_bus *bus, int addr);
 int phy_clear_interrupt(struct phy_device *phydev);
 int phy_config_interrupt(struct phy_device *phydev, u32 interrupts);
 struct phy_device * phy_attach(struct net_device *dev,
-               const char *phy_id, u32 flags, phy_interface_t interface);
-struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
+               const char *bus_id, u32 flags, phy_interface_t interface);
+struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
                void (*handler)(struct net_device *), u32 flags,
                phy_interface_t interface);
 void phy_disconnect(struct phy_device *phydev);
@@ -427,5 +439,13 @@ void phy_print_status(struct phy_device *phydev);
 struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id);
 void phy_device_free(struct phy_device *phydev);
 
+int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
+               int (*run)(struct phy_device *));
+int phy_register_fixup_for_id(const char *bus_id,
+               int (*run)(struct phy_device *));
+int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
+               int (*run)(struct phy_device *));
+int phy_scan_fixups(struct phy_device *phydev);
+
 extern struct bus_type mdio_bus_type;
 #endif /* __PHY_H */
index 311380e5fe8915a1d85f6999f524bcd4330f0141..9a4f3e63e3bf0a88833d779a0b214aa997419c6e 100644 (file)
@@ -1798,6 +1798,8 @@ extern void mmput(struct mm_struct *);
 extern struct mm_struct *get_task_mm(struct task_struct *task);
 /* Remove the current tasks stale references to the old mm_struct */
 extern void mm_release(struct task_struct *, struct mm_struct *);
+/* Allocate a new mm structure and copy contents from tsk->mm */
+extern struct mm_struct *dup_mm(struct task_struct *tsk);
 
 extern int  copy_thread(int, unsigned long, unsigned long, unsigned long, struct task_struct *, struct pt_regs *);
 extern void flush_thread(void);
@@ -1926,6 +1928,8 @@ static inline unsigned long *end_of_stack(struct task_struct *p)
 
 #endif
 
+extern void thread_info_cache_init(void);
+
 /* set thread flags in other task's structures
  * - see asm/thread_info.h for TIF_xxxx flags available
  */
index 26e4925bc35bb5f76d28aa55119b4a2c2501091d..632205ccc25dabdd50debabc06914161bc2358ca 100644 (file)
@@ -85,23 +85,29 @@ static inline int write_tryseqlock(seqlock_t *sl)
 /* Start of read calculation -- fetch last complete writer token */
 static __always_inline unsigned read_seqbegin(const seqlock_t *sl)
 {
-       unsigned ret = sl->sequence;
+       unsigned ret;
+
+repeat:
+       ret = sl->sequence;
        smp_rmb();
+       if (unlikely(ret & 1)) {
+               cpu_relax();
+               goto repeat;
+       }
+
        return ret;
 }
 
-/* Test if reader processed invalid data.
- * If initial values is odd, 
- *     then writer had already started when section was entered
- * If sequence value changed
- *     then writer changed data while in section
- *    
- * Using xor saves one conditional branch.
+/*
+ * Test if reader processed invalid data.
+ *
+ * If sequence value changed then writer changed data while in section.
  */
-static __always_inline int read_seqretry(const seqlock_t *sl, unsigned iv)
+static __always_inline int read_seqretry(const seqlock_t *sl, unsigned start)
 {
        smp_rmb();
-       return (iv & 1) | (sl->sequence ^ iv);
+
+       return (sl->sequence != start);
 }
 
 
@@ -122,20 +128,26 @@ typedef struct seqcount {
 /* Start of read using pointer to a sequence counter only.  */
 static inline unsigned read_seqcount_begin(const seqcount_t *s)
 {
-       unsigned ret = s->sequence;
+       unsigned ret;
+
+repeat:
+       ret = s->sequence;
        smp_rmb();
+       if (unlikely(ret & 1)) {
+               cpu_relax();
+               goto repeat;
+       }
        return ret;
 }
 
-/* Test if reader processed invalid data.
- * Equivalent to: iv is odd or sequence number has changed.
- *                (iv & 1) || (*s != iv)
- * Using xor saves one conditional branch.
+/*
+ * Test if reader processed invalid data because sequence number has changed.
  */
-static inline int read_seqcount_retry(const seqcount_t *s, unsigned iv)
+static inline int read_seqcount_retry(const seqcount_t *s, unsigned start)
 {
        smp_rmb();
-       return (iv & 1) | (s->sequence ^ iv);
+
+       return s->sequence != start;
 }
 
 
index 9f38250146744a605736879d1ba23fe969a07ad0..95674d97dabda27a1cdcb361546844b2b993da26 100644 (file)
@@ -211,5 +211,6 @@ static inline void serio_unpin_driver(struct serio *serio)
 #define SERIO_TOUCHWIN 0x33
 #define SERIO_TAOSEVM  0x34
 #define SERIO_FUJITSU  0x35
+#define SERIO_ZHENHUA  0x36
 
 #endif
index 334d3141162966a4daacc7233d4bdf843b4d4e6a..daf744017a31c86bfaacf0a98ad1ebfdd27a4595 100644 (file)
@@ -14,7 +14,8 @@ enum ads7846_filter {
 struct ads7846_platform_data {
        u16     model;                  /* 7843, 7845, 7846. */
        u16     vref_delay_usecs;       /* 0 for external vref; etc */
-       int     keep_vref_on:1;         /* set to keep vref on for differential
+       u16     vref_mv;                /* external vref value, milliVolts */
+       bool    keep_vref_on;           /* set to keep vref on for differential
                                         * measurements as well */
 
        /* Settling time of the analog signals; a function of Vcc and the
index 03378e3515b3fd073b23bf517057fa4708d5bf43..add3c5a40827f7824169159a140884da38291d17 100644 (file)
@@ -32,7 +32,7 @@ struct attribute {
 
 struct attribute_group {
        const char              *name;
-       int                     (*is_visible)(struct kobject *,
+       mode_t                  (*is_visible)(struct kobject *,
                                              struct attribute *, int);
        struct attribute        **attrs;
 };
@@ -105,6 +105,8 @@ void sysfs_remove_link(struct kobject *kobj, const char *name);
 
 int __must_check sysfs_create_group(struct kobject *kobj,
                                    const struct attribute_group *grp);
+int sysfs_update_group(struct kobject *kobj,
+                      const struct attribute_group *grp);
 void sysfs_remove_group(struct kobject *kobj,
                        const struct attribute_group *grp);
 int sysfs_add_file_to_group(struct kobject *kobj,
index 583e0481dfa028cfe137156d74dd342dc5a03f9c..c08689ea9b4bb6027cadb5ffa33b1ea3a3e43c8a 100644 (file)
@@ -23,6 +23,7 @@
 
 struct usb_device;
 struct usb_driver;
+struct wusb_dev;
 
 /*-------------------------------------------------------------------------*/
 
@@ -341,103 +342,146 @@ struct usb_bus {
 
 struct usb_tt;
 
-/*
+/**
  * struct usb_device - kernel's representation of a USB device
- *
- * FIXME: Write the kerneldoc!
- *
+ * @devnum: device number; address on a USB bus
+ * @devpath: device ID string for use in messages (e.g., /port/...)
+ * @state: device state: configured, not attached, etc.
+ * @speed: device speed: high/full/low (or error)
+ * @tt: Transaction Translator info; used with low/full speed dev, highspeed hub
+ * @ttport: device port on that tt hub
+ * @toggle: one bit for each endpoint, with ([0] = IN, [1] = OUT) endpoints
+ * @parent: our hub, unless we're the root
+ * @bus: bus we're part of
+ * @ep0: endpoint 0 data (default control pipe)
+ * @dev: generic device interface
+ * @descriptor: USB device descriptor
+ * @config: all of the device's configs
+ * @actconfig: the active configuration
+ * @ep_in: array of IN endpoints
+ * @ep_out: array of OUT endpoints
+ * @rawdescriptors: raw descriptors for each config
+ * @bus_mA: Current available from the bus
+ * @portnum: parent port number (origin 1)
+ * @level: number of USB hub ancestors
+ * @can_submit: URBs may be submitted
+ * @discon_suspended: disconnected while suspended
+ * @persist_enabled:  USB_PERSIST enabled for this device
+ * @have_langid: whether string_langid is valid
+ * @authorized: policy has said we can use it;
+ *     (user space) policy determines if we authorize this device to be
+ *     used or not. By default, wired USB devices are authorized.
+ *     WUSB devices are not, until we authorize them from user space.
+ *     FIXME -- complete doc
+ * @authenticated: Crypto authentication passed
+ * @wusb: device is Wireless USB
+ * @string_langid: language ID for strings
+ * @product: iProduct string, if present (static)
+ * @manufacturer: iManufacturer string, if present (static)
+ * @serial: iSerialNumber string, if present (static)
+ * @filelist: usbfs files that are open to this device
+ * @usb_classdev: USB class device that was created for usbfs device
+ *     access from userspace
+ * @usbfs_dentry: usbfs dentry entry for the device
+ * @maxchild: number of ports if hub
+ * @children: child devices - USB devices that are attached to this hub
+ * @pm_usage_cnt: usage counter for autosuspend
+ * @quirks: quirks of the whole device
+ * @urbnum: number of URBs submitted for the whole device
+ * @active_duration: total time device is not suspended
+ * @autosuspend: for delayed autosuspends
+ * @pm_mutex: protects PM operations
+ * @last_busy: time of last use
+ * @autosuspend_delay: in jiffies
+ * @connect_time: time device was first connected
+ * @auto_pm: autosuspend/resume in progress
+ * @do_remote_wakeup:  remote wakeup should be enabled
+ * @reset_resume: needs reset instead of resume
+ * @autosuspend_disabled: autosuspend disabled by the user
+ * @autoresume_disabled: autoresume disabled by the user
+ * @skip_sys_resume: skip the next system resume
+ *
+ * Notes:
  * Usbcore drivers should not set usbdev->state directly.  Instead use
  * usb_set_device_state().
- *
- * @authorized: (user space) policy determines if we authorize this
- *              device to be used or not. By default, wired USB
- *              devices are authorized. WUSB devices are not, until we
- *              authorize them from user space. FIXME -- complete doc
  */
 struct usb_device {
-       int             devnum;         /* Address on USB bus */
-       char            devpath [16];   /* Use in messages: /port/port/... */
-       enum usb_device_state   state;  /* configured, not attached, etc */
-       enum usb_device_speed   speed;  /* high/full/low (or error) */
+       int             devnum;
+       char            devpath [16];
+       enum usb_device_state   state;
+       enum usb_device_speed   speed;
 
-       struct usb_tt   *tt;            /* low/full speed dev, highspeed hub */
-       int             ttport;         /* device port on that tt hub */
+       struct usb_tt   *tt;
+       int             ttport;
 
-       unsigned int toggle[2];         /* one bit for each endpoint
-                                        * ([0] = IN, [1] = OUT) */
+       unsigned int toggle[2];
 
-       struct usb_device *parent;      /* our hub, unless we're the root */
-       struct usb_bus *bus;            /* Bus we're part of */
+       struct usb_device *parent;
+       struct usb_bus *bus;
        struct usb_host_endpoint ep0;
 
-       struct device dev;              /* Generic device interface */
+       struct device dev;
 
-       struct usb_device_descriptor descriptor;/* Descriptor */
-       struct usb_host_config *config; /* All of the configs */
+       struct usb_device_descriptor descriptor;
+       struct usb_host_config *config;
 
-       struct usb_host_config *actconfig;/* the active configuration */
+       struct usb_host_config *actconfig;
        struct usb_host_endpoint *ep_in[16];
        struct usb_host_endpoint *ep_out[16];
 
-       char **rawdescriptors;          /* Raw descriptors for each config */
+       char **rawdescriptors;
 
-       unsigned short bus_mA;          /* Current available from the bus */
-       u8 portnum;                     /* Parent port number (origin 1) */
-       u8 level;                       /* Number of USB hub ancestors */
+       unsigned short bus_mA;
+       u8 portnum;
+       u8 level;
 
-       unsigned can_submit:1;          /* URBs may be submitted */
-       unsigned discon_suspended:1;    /* Disconnected while suspended */
-       unsigned have_langid:1;         /* whether string_langid is valid */
-       unsigned authorized:1;          /* Policy has said we can use it */
-       unsigned wusb:1;                /* Device is Wireless USB */
-       int string_langid;              /* language ID for strings */
+       unsigned can_submit:1;
+       unsigned discon_suspended:1;
+       unsigned persist_enabled:1;
+       unsigned have_langid:1;
+       unsigned authorized:1;
+       unsigned authenticated:1;
+       unsigned wusb:1;
+       int string_langid;
 
        /* static strings from the device */
-       char *product;                  /* iProduct string, if present */
-       char *manufacturer;             /* iManufacturer string, if present */
-       char *serial;                   /* iSerialNumber string, if present */
+       char *product;
+       char *manufacturer;
+       char *serial;
 
        struct list_head filelist;
 #ifdef CONFIG_USB_DEVICE_CLASS
        struct device *usb_classdev;
 #endif
 #ifdef CONFIG_USB_DEVICEFS
-       struct dentry *usbfs_dentry;    /* usbfs dentry entry for the device */
+       struct dentry *usbfs_dentry;
 #endif
-       /*
-        * Child devices - these can be either new devices
-        * (if this is a hub device), or different instances
-        * of this same device.
-        *
-        * Each instance needs its own set of data structures.
-        */
 
-       int maxchild;                   /* Number of ports if hub */
+       int maxchild;
        struct usb_device *children[USB_MAXCHILDREN];
 
-       int pm_usage_cnt;               /* usage counter for autosuspend */
-       u32 quirks;                     /* quirks of the whole device */
-       atomic_t urbnum;                /* number of URBs submitted for
-                                          the whole device */
+       int pm_usage_cnt;
+       u32 quirks;
+       atomic_t urbnum;
 
-       unsigned long active_duration;  /* total time device is not suspended */
+       unsigned long active_duration;
 
 #ifdef CONFIG_PM
-       struct delayed_work autosuspend; /* for delayed autosuspends */
-       struct mutex pm_mutex;          /* protects PM operations */
-
-       unsigned long last_busy;        /* time of last use */
-       int autosuspend_delay;          /* in jiffies */
-       unsigned long connect_time;     /* time device was first connected */
-
-       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 */
-       unsigned skip_sys_resume:1;     /* skip the next system resume */
+       struct delayed_work autosuspend;
+       struct mutex pm_mutex;
+
+       unsigned long last_busy;
+       int autosuspend_delay;
+       unsigned long connect_time;
+
+       unsigned auto_pm:1;
+       unsigned do_remote_wakeup:1;
+       unsigned reset_resume:1;
+       unsigned autosuspend_disabled:1;
+       unsigned autoresume_disabled:1;
+       unsigned skip_sys_resume:1;
 #endif
+       struct wusb_dev *wusb_dev;
 };
 #define        to_usb_device(d) container_of(d, struct usb_device, dev)
 
@@ -898,10 +942,11 @@ struct usbdrv_wrap {
  *     and should normally be the same as the module name.
  * @probe: Called to see if the driver is willing to manage a particular
  *     interface on a device.  If it is, probe returns zero and uses
- *     dev_set_drvdata() to associate driver-specific data with the
+ *     usb_set_intfdata() to associate driver-specific data with the
  *     interface.  It may also use usb_set_interface() to specify the
  *     appropriate altsetting.  If unwilling to manage the interface,
- *     return a negative errno value.
+ *     return -ENODEV, if genuine IO errors occured, an appropriate
+ *     negative errno value.
  * @disconnect: Called when the interface is no longer accessible, usually
  *     because its device has been (or is being) disconnected or the
  *     driver module is being unloaded.
@@ -916,10 +961,7 @@ struct usbdrv_wrap {
  * @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, 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.
+ *     has been reset
  * @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.
@@ -1411,6 +1453,7 @@ 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_unlink_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,
@@ -1661,13 +1704,12 @@ extern void usb_unregister_notify(struct notifier_block *nb);
 #define dbg(format, arg...) do {} while (0)
 #endif
 
-#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
-       __FILE__ , ## arg)
-#define info(format, arg...) printk(KERN_INFO "%s: " format "\n" , \
-       __FILE__ , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n" , \
-       __FILE__ , ## arg)
-
+#define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \
+       format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO KBUILD_MODNAME ": " \
+       format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING KBUILD_MODNAME ": " \
+       format "\n" , ## arg)
 
 #endif  /* __KERNEL__ */
 
index 2dfeef16b221d4605f2090de430e4f196c9d8712..8cb025fef6346a63270cd55a8de69b3b93a49006 100644 (file)
@@ -50,4 +50,4 @@ struct usb_ac_header_descriptor_##n {                         \
        __u8  baInterfaceNr[n];                                 \
 } __attribute__ ((packed))
 
-#endif
+#endif /* __LINUX_USB_AUDIO_H */
index 94ee4ecf0564972750e2fba836cd70990d01101a..71e52f2f6a38686ff45e7a7f489e24a395dfbeb1 100644 (file)
@@ -6,6 +6,9 @@
  * firmware based USB peripherals.
  */
 
+#ifndef __LINUX_USB_CDC_H
+#define __LINUX_USB_CDC_H
+
 #define USB_CDC_SUBCLASS_ACM                   0x02
 #define USB_CDC_SUBCLASS_ETHERNET              0x06
 #define USB_CDC_SUBCLASS_WHCM                  0x08
@@ -221,3 +224,4 @@ struct usb_cdc_notification {
        __le16  wLength;
 } __attribute__ ((packed));
 
+#endif /* __LINUX_USB_CDC_H */
index 6169438ec5a2357c6341e1ae31f3cfc2cbac1ad2..7e0d3084f76c8411aa5dad0b09772f840020b50a 100644 (file)
@@ -66,8 +66,8 @@
 #define USB_RECIP_ENDPOINT             0x02
 #define USB_RECIP_OTHER                        0x03
 /* From Wireless USB 1.0 */
-#define USB_RECIP_PORT                         0x04
-#define USB_RECIP_RPIPE                0x05
+#define USB_RECIP_PORT                 0x04
+#define USB_RECIP_RPIPE                0x05
 
 /*
  * Standard requests, for the bRequest field of a SETUP packet.
 #define USB_REQ_LOOPBACK_DATA_READ     0x16
 #define USB_REQ_SET_INTERFACE_DS       0x17
 
+/* The Link Power Mangement (LPM) ECN defines USB_REQ_TEST_AND_SET command,
+ * used by hubs to put ports into a new L1 suspend state, except that it
+ * forgot to define its number ...
+ */
+
 /*
  * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and
  * are read as a bit array returned by USB_REQ_GET_STATUS.  (So there
- * are at most sixteen features of each type.)
+ * are at most sixteen features of each type.)  Hubs may also support a
+ * new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend.
  */
 #define USB_DEVICE_SELF_POWERED                0       /* (read only) */
 #define USB_DEVICE_REMOTE_WAKEUP       1       /* dev may initiate wakeup */
@@ -180,6 +186,7 @@ struct usb_ctrlrequest {
 #define USB_DT_WIRELESS_ENDPOINT_COMP  0x11
 #define USB_DT_WIRE_ADAPTER            0x21
 #define USB_DT_RPIPE                   0x22
+#define USB_DT_CS_RADIO_CONTROL                0x23
 
 /* Conventional codes for class-specific descriptors.  The convention is
  * defined in the USB "Common Class" Spec (3.11).  Individual class specs
@@ -574,7 +581,9 @@ enum usb_device_state {
        /* NOTE:  there are actually four different SUSPENDED
         * states, returning to POWERED, DEFAULT, ADDRESS, or
         * CONFIGURED respectively when SOF tokens flow again.
+        * At this level there's no difference between L1 and L2
+        * suspend states.  (L2 being original USB 1.1 suspend.)
         */
 };
 
-#endif /* __LINUX_USB_CH9_H */
+#endif /* __LINUX_USB_CH9_H */
index 0c5ea1e3eb980fb11b276ca0377e593b25f362bd..6178fde50f7404d7639440b8445fa0043f6b1b1b 100644 (file)
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#ifndef __LINUX_USB_G_PRINTER_H
+#define __LINUX_USB_G_PRINTER_H
 
 #define PRINTER_NOT_ERROR      0x08
 #define PRINTER_SELECTED       0x10
@@ -29,3 +31,5 @@
  */
 #define GADGET_GET_PRINTER_STATUS      _IOR('g', 0x21, unsigned char)
 #define GADGET_SET_PRINTER_STATUS      _IOWR('g', 0x22, unsigned char)
+
+#endif /* __LINUX_USB_G_PRINTER_H */
index f3295296b4353a5305ca3ee947d80b7ac3e0932b..d8128f7102c92858bc01d71c7544882849318ae7 100644 (file)
@@ -846,4 +846,4 @@ extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *,
 
 extern void usb_ep_autoconfig_reset(struct usb_gadget *) __devinit;
 
-#endif /* __LINUX_USB_GADGET_H */
+#endif /* __LINUX_USB_GADGET_H */
index c291ab1af747a37953f7866fe6479dcef16a7877..ea45f265ec05221bc18b0ad687a15e721f53ed44 100644 (file)
@@ -1,11 +1,3 @@
-#ifndef __LINUX_USB_GADGETFS_H
-#define __LINUX_USB_GADGETFS_H
-
-#include <asm/types.h>
-#include <asm/ioctl.h>
-
-#include <linux/usb/ch9.h>
-
 /*
  * Filesystem based user-mode API to USB Gadget controller hardware
  *
  * then performing data transfers by reading or writing.
  */
 
+#ifndef __LINUX_USB_GADGETFS_H
+#define __LINUX_USB_GADGETFS_H
+
+#include <asm/types.h>
+#include <asm/ioctl.h>
+
+#include <linux/usb/ch9.h>
+
 /*
  * Events are delivered on the ep0 file descriptor, when the user mode driver
  * reads from this file descriptor after writing the descriptors.  Don't
index 716e0cc1604314b147bfe1b517b82930503e98f1..0e010b220e85b3f9ea861f2ab009809d17014910 100644 (file)
@@ -1,6 +1,3 @@
-#ifndef __USB_INPUT_H
-#define __USB_INPUT_H
-
 /*
  * Copyright (C) 2005 Dmitry Torokhov
  *
@@ -9,6 +6,9 @@
  * the Free Software Foundation.
  */
 
+#ifndef __LINUX_USB_INPUT_H
+#define __LINUX_USB_INPUT_H
+
 #include <linux/usb.h>
 #include <linux/input.h>
 #include <asm/byteorder.h>
@@ -22,4 +22,4 @@ usb_to_input_id(const struct usb_device *dev, struct input_id *id)
        id->version = le16_to_cpu(dev->descriptor.bcdDevice);
 }
 
-#endif
+#endif /* __LINUX_USB_INPUT_H */
index de6f380e17a2bfac42059c40b41c69d3102222f9..4fd6513d564c7ccb1362d73a1aa45ba4ee05baaf 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _IOWARRIOR_H_
-#define _IOWARRIOR_H_
+#ifndef __LINUX_USB_IOWARRIOR_H
+#define __LINUX_USB_IOWARRIOR_H
 
 #define CODEMERCS_MAGIC_NUMBER 0xC0    /* like COde Mercenaries */
 
@@ -39,4 +39,4 @@ struct iowarrior_info {
 */
 #define IOW_GETINFO _IOR(CODEMERCS_MAGIC_NUMBER, 3, struct iowarrior_info)
 
-#endif  /* _IOWARRIOR_H_ */
+#endif /* __LINUX_USB_IOWARRIOR_H */
index 67d2826f34fe7795cc8bb37bf3ea4fa6ab7c1307..96ca114e88d0e1b843f1816c55c1bba310ee93ad 100644 (file)
@@ -1,9 +1,11 @@
-
 /*
  * Board initialization code should put one of these into dev->platform_data
  * and place the isp116x onto platform_bus.
  */
 
+#ifndef __LINUX_USB_ISP116X_H
+#define __LINUX_USB_ISP116X_H
+
 struct isp116x_platform_data {
        /* Enable internal resistors on downstream ports */
        unsigned sel15Kres:1;
@@ -27,3 +29,5 @@ struct isp116x_platform_data {
         */
        void (*delay) (struct device *dev, int delay);
 };
+
+#endif /* __LINUX_USB_ISP116X_H */
index 80624c562921e0fe2dc620ccbaad6e16f70eb7cb..1d10408656617b0657b8cba188ee6893681e688c 100644 (file)
@@ -109,4 +109,4 @@ struct usb_ms_endpoint_descriptor_##n {                             \
        __u8  baAssocJackID[n];                                 \
 } __attribute__ ((packed))
 
-#endif
+#endif /* __LINUX_USB_MIDI_H */
index ec897cb844ab5cd9a8dbda9be1b66a37cf8235c2..96ca549a778d62a22897451539efab0189303db0 100644 (file)
@@ -1,11 +1,7 @@
 /*
  * NetChip 2280 high/full speed USB device controller.
  * Unlike many such controllers, this one talks PCI.
- */
-#ifndef __LINUX_USB_NET2280_H
-#define __LINUX_USB_NET2280_H
-
-/*
+ *
  * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
  * Copyright (C) 2003 David Brownell
  *
@@ -24,6 +20,9 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#ifndef __LINUX_USB_NET2280_H
+#define __LINUX_USB_NET2280_H
+
 /*-------------------------------------------------------------------------*/
 
 /* NET2280 MEMORY MAPPED REGISTERS
index e007074ebe41f6b9648f62177cfa588b7bc13fcb..1db25d152ad86a351483f680251af8081de6fc0d 100644 (file)
@@ -1,11 +1,13 @@
 /* USB OTG (On The Go) defines */
-
 /*
+ *
  * These APIs may be used between USB controllers.  USB device drivers
  * (for either host or peripheral roles) don't use these calls; they
  * continue to use just usb_device and usb_gadget.
  */
 
+#ifndef __LINUX_USB_OTG_H
+#define __LINUX_USB_OTG_H
 
 /* OTG defines lots of enumeration states before device reset */
 enum usb_otg_state {
@@ -129,3 +131,5 @@ otg_start_srp(struct otg_transceiver *otg)
 
 /* for OTG controller drivers (and maybe other stuff) */
 extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num);
+
+#endif /* __LINUX_USB_OTG_H */
index 1f999ec8d08c520c431d626e3bf5372e890c51a3..7f6c603db654d077f4cd8ee8351c97e8f9957815 100644 (file)
@@ -4,6 +4,9 @@
  * belong here.
  */
 
+#ifndef __LINUX_USB_QUIRKS_H
+#define __LINUX_USB_QUIRKS_H
+
 /* string descriptors must not be fetched using a 255-byte read */
 #define USB_QUIRK_STRING_FETCH_255     0x00000001
 
@@ -12,3 +15,5 @@
 
 /* device can't handle Set-Interface requests */
 #define USB_QUIRK_NO_SET_INTF          0x00000004
+
+#endif /* __LINUX_USB_QUIRKS_H */
index edc1d4a0e272459a8c411c80c9d4855ec4a0163a..29d6458ecb8d88127af75d053cc286cba2e12d08 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-
-#ifndef        __RNDIS_HOST_H
-#define        __RNDIS_HOST_H
-
+#ifndef        __LINUX_USB_RNDIS_HOST_H
+#define        __LINUX_USB_RNDIS_HOST_H
 
 /*
  * CONTROL uses CDC "encapsulated commands" with funky notifications.
@@ -270,5 +268,4 @@ extern int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb);
 extern struct sk_buff *
 rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags);
 
-#endif /* __RNDIS_HOST_H */
-
+#endif /* __LINUX_USB_RNDIS_HOST_H */
index 21b4a1c6f5851f9c92998694afd0171602af880b..8f891cbaf9abd497f990e5ae68eabb8d2ae99971 100644 (file)
@@ -10,7 +10,6 @@
  *
  */
 
-
 #ifndef __LINUX_USB_SERIAL_H
 #define __LINUX_USB_SERIAL_H
 
@@ -146,8 +145,6 @@ struct usb_serial {
 };
 #define to_usb_serial(d) container_of(d, struct usb_serial, kref)
 
-#define NUM_DONT_CARE  99
-
 /* get and set the serial private data pointer helper functions */
 static inline void *usb_get_serial_data(struct usb_serial *serial)
 {
@@ -165,18 +162,6 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
  *     used in the syslog messages when a device is inserted or removed.
  * @id_table: pointer to a list of usb_device_id structures that define all
  *     of the devices this structure can support.
- * @num_interrupt_in: If a device doesn't have this many interrupt-in
- *     endpoints, it won't be sent to the driver's attach() method.
- *     (But it might still be sent to the probe() method.)
- * @num_interrupt_out: If a device doesn't have this many interrupt-out
- *     endpoints, it won't be sent to the driver's attach() method.
- *     (But it might still be sent to the probe() method.)
- * @num_bulk_in: If a device doesn't have this many bulk-in
- *     endpoints, it won't be sent to the driver's attach() method.
- *     (But it might still be sent to the probe() method.)
- * @num_bulk_out: If a device doesn't have this many bulk-out
- *     endpoints, it won't be sent to the driver's attach() method.
- *     (But it might still be sent to the probe() method.)
  * @num_ports: the number of different ports this device will have.
  * @calc_num_ports: pointer to a function to determine how many ports this
  *     device has dynamically.  It will be called after the probe()
@@ -212,10 +197,6 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
 struct usb_serial_driver {
        const char *description;
        const struct usb_device_id *id_table;
-       char    num_interrupt_in;
-       char    num_interrupt_out;
-       char    num_bulk_in;
-       char    num_bulk_out;
        char    num_ports;
 
        struct list_head        driver_list;
@@ -340,5 +321,5 @@ static inline void usb_serial_debug_data(int debug,
 
 
 
-#endif /* ifdef __LINUX_USB_SERIAL_H */
+#endif /* __LINUX_USB_SERIAL_H */
 
index 877373da410dcd0520cae0babe731188351fc637..3afe4d16fcef186d2c9f8b415b6c3c8b87c3ca2c 100644 (file)
@@ -1,9 +1,11 @@
-
 /*
  * board initialization should put one of these into dev->platform_data
  * and place the sl811hs onto platform_bus named "sl811-hcd".
  */
 
+#ifndef __LINUX_USB_SL811_H
+#define __LINUX_USB_SL811_H
+
 struct sl811_platform_data {
        unsigned        can_wakeup:1;
 
@@ -24,3 +26,4 @@ struct sl811_platform_data {
        /* void         (*clock_enable)(struct device *dev, int is_on); */
 };
 
+#endif /* __LINUX_USB_SL811_H */
index e0501da3dd115024b9b31b8d1f0d0bd139b3f19d..ba09fe88addaebc9d6ee07e5ef70baecae08d313 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-
-#ifndef        __USBNET_H
-#define        __USBNET_H
-
+#ifndef        __LINUX_USB_USBNET_H
+#define        __LINUX_USB_USBNET_H
 
 /* interface from usbnet core to each USB networking link we handle */
 struct usbnet {
@@ -211,4 +209,4 @@ extern int usbnet_nway_reset(struct net_device *net);
        printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net->name , ## arg); \
 
 
-#endif /* __USBNET_H */
+#endif /* __LINUX_USB_USBNET_H */
index 0a40dfa44c9f9a640524f03cecd2ef5261b1f78d..d9a3bbe38e6b78b0aad1d1e90e5d98cc77d82003 100644 (file)
@@ -85,6 +85,7 @@ enum { US_DO_ALL_FLAGS };
 #define US_SC_LOCKABLE 0x07            /* Password-protected */
 
 #define US_SC_ISD200    0xf0           /* ISD200 ATA */
+#define US_SC_CYP_ATACB 0xf1           /* Cypress ATACB */
 #define US_SC_DEVICE   0xff            /* Use device's value */
 
 /* Protocols */
index 17cb108b7db038558ef4e49337503c1217d8592a..3118ede2c67b3f35c18b7ea326c63220c0cdc4f1 100644 (file)
@@ -77,8 +77,11 @@ struct usbdevfs_connectinfo {
        unsigned char slow;
 };
 
-#define USBDEVFS_URB_SHORT_NOT_OK          1
-#define USBDEVFS_URB_ISO_ASAP              2
+#define USBDEVFS_URB_SHORT_NOT_OK      0x01
+#define USBDEVFS_URB_ISO_ASAP          0x02
+#define USBDEVFS_URB_NO_FSBR           0x20
+#define USBDEVFS_URB_ZERO_PACKET       0x40
+#define USBDEVFS_URB_NO_INTERRUPT      0x80
 
 #define USBDEVFS_URB_TYPE_ISO             0
 #define USBDEVFS_URB_TYPE_INTERRUPT       1
diff --git a/include/linux/wm97xx.h b/include/linux/wm97xx.h
new file mode 100644 (file)
index 0000000..4d13732
--- /dev/null
@@ -0,0 +1,314 @@
+
+/*
+ * Register bits and API for Wolfson WM97xx series of codecs
+ */
+
+#ifndef _LINUX_WM97XX_H
+#define _LINUX_WM97XX_H
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <sound/initval.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/input.h>       /* Input device layer */
+#include <linux/platform_device.h>
+
+/*
+ * WM97xx AC97 Touchscreen registers
+ */
+#define AC97_WM97XX_DIGITISER1         0x76
+#define AC97_WM97XX_DIGITISER2         0x78
+#define AC97_WM97XX_DIGITISER_RD       0x7a
+#define AC97_WM9713_DIG1               0x74
+#define AC97_WM9713_DIG2               AC97_WM97XX_DIGITISER1
+#define AC97_WM9713_DIG3               AC97_WM97XX_DIGITISER2
+
+/*
+ * WM97xx register bits
+ */
+#define WM97XX_POLL            0x8000  /* initiate a polling measurement */
+#define WM97XX_ADCSEL_X                0x1000  /* x coord measurement */
+#define WM97XX_ADCSEL_Y                0x2000  /* y coord measurement */
+#define WM97XX_ADCSEL_PRES     0x3000  /* pressure measurement */
+#define WM97XX_ADCSEL_MASK     0x7000
+#define WM97XX_COO             0x0800  /* enable coordinate mode */
+#define WM97XX_CTC             0x0400  /* enable continuous mode */
+#define WM97XX_CM_RATE_93      0x0000  /* 93.75Hz continuous rate */
+#define WM97XX_CM_RATE_187     0x0100  /* 187.5Hz continuous rate */
+#define WM97XX_CM_RATE_375     0x0200  /* 375Hz continuous rate */
+#define WM97XX_CM_RATE_750     0x0300  /* 750Hz continuous rate */
+#define WM97XX_CM_RATE_8K      0x00f0  /* 8kHz continuous rate */
+#define WM97XX_CM_RATE_12K     0x01f0  /* 12kHz continuous rate */
+#define WM97XX_CM_RATE_24K     0x02f0  /* 24kHz continuous rate */
+#define WM97XX_CM_RATE_48K     0x03f0  /* 48kHz continuous rate */
+#define WM97XX_CM_RATE_MASK    0x03f0
+#define WM97XX_RATE(i)         (((i & 3) << 8) | ((i & 4) ? 0xf0 : 0))
+#define WM97XX_DELAY(i)                ((i << 4) & 0x00f0)     /* sample delay times */
+#define WM97XX_DELAY_MASK      0x00f0
+#define WM97XX_SLEN            0x0008  /* slot read back enable */
+#define WM97XX_SLT(i)          ((i - 5) & 0x7) /* panel slot (5-11) */
+#define WM97XX_SLT_MASK                0x0007
+#define WM97XX_PRP_DETW                0x4000  /* detect on, digitise off, wake */
+#define WM97XX_PRP_DET         0x8000  /* detect on, digitise off, no wake */
+#define WM97XX_PRP_DET_DIG     0xc000  /* setect on, digitise on */
+#define WM97XX_RPR             0x2000  /* wake up on pen down */
+#define WM97XX_PEN_DOWN                0x8000  /* pen is down */
+#define WM97XX_ADCSRC_MASK     0x7000  /* ADC source mask */
+
+#define WM97XX_AUX_ID1         0x8001
+#define WM97XX_AUX_ID2         0x8002
+#define WM97XX_AUX_ID3         0x8003
+#define WM97XX_AUX_ID4         0x8004
+
+
+/* WM9712 Bits */
+#define WM9712_45W             0x1000  /* set for 5-wire touchscreen */
+#define WM9712_PDEN            0x0800  /* measure only when pen down */
+#define WM9712_WAIT            0x0200  /* wait until adc is read before next sample */
+#define WM9712_PIL             0x0100  /* current used for pressure measurement. set 400uA else 200uA */
+#define WM9712_MASK_HI         0x0040  /* hi on mask pin (47) stops conversions */
+#define WM9712_MASK_EDGE       0x0080  /* rising/falling edge on pin delays sample */
+#define        WM9712_MASK_SYNC        0x00c0  /* rising/falling edge on mask initiates sample */
+#define WM9712_RPU(i)          (i&0x3f)        /* internal pull up on pen detect (64k / rpu) */
+#define WM9712_PD(i)           (0x1 << i)      /* power management */
+
+/* WM9712 Registers */
+#define AC97_WM9712_POWER      0x24
+#define AC97_WM9712_REV                0x58
+
+/* WM9705 Bits */
+#define WM9705_PDEN            0x1000  /* measure only when pen is down */
+#define WM9705_PINV            0x0800  /* inverts sense of pen down output */
+#define WM9705_BSEN            0x0400  /* BUSY flag enable, pin47 is 1 when busy */
+#define WM9705_BINV            0x0200  /* invert BUSY (pin47) output */
+#define WM9705_WAIT            0x0100  /* wait until adc is read before next sample */
+#define WM9705_PIL             0x0080  /* current used for pressure measurement. set 400uA else 200uA */
+#define WM9705_PHIZ            0x0040  /* set PHONE and PCBEEP inputs to high impedance */
+#define WM9705_MASK_HI         0x0010  /* hi on mask stops conversions */
+#define WM9705_MASK_EDGE       0x0020  /* rising/falling edge on pin delays sample */
+#define        WM9705_MASK_SYNC        0x0030  /* rising/falling edge on mask initiates sample */
+#define WM9705_PDD(i)          (i & 0x000f)    /* pen detect comparator threshold */
+
+
+/* WM9713 Bits */
+#define WM9713_PDPOL           0x0400  /* Pen down polarity */
+#define WM9713_POLL            0x0200  /* initiate a polling measurement */
+#define WM9713_CTC             0x0100  /* enable continuous mode */
+#define WM9713_ADCSEL_X                0x0002  /* X measurement */
+#define WM9713_ADCSEL_Y                0x0004  /* Y measurement */
+#define WM9713_ADCSEL_PRES     0x0008  /* Pressure measurement */
+#define WM9713_COO             0x0001  /* enable coordinate mode */
+#define WM9713_PDEN            0x0800  /* measure only when pen down */
+#define WM9713_ADCSEL_MASK     0x00fe  /* ADC selection mask */
+#define WM9713_WAIT            0x0200  /* coordinate wait */
+
+/* AUX ADC ID's */
+#define TS_COMP1               0x0
+#define TS_COMP2               0x1
+#define TS_BMON                        0x2
+#define TS_WIPER               0x3
+
+/* ID numbers */
+#define WM97XX_ID1             0x574d
+#define WM9712_ID2             0x4c12
+#define WM9705_ID2             0x4c05
+#define WM9713_ID2             0x4c13
+
+/* Codec GPIO's */
+#define WM97XX_MAX_GPIO                16
+#define WM97XX_GPIO_1          (1 << 1)
+#define WM97XX_GPIO_2          (1 << 2)
+#define WM97XX_GPIO_3          (1 << 3)
+#define WM97XX_GPIO_4          (1 << 4)
+#define WM97XX_GPIO_5          (1 << 5)
+#define WM97XX_GPIO_6          (1 << 6)
+#define WM97XX_GPIO_7          (1 << 7)
+#define WM97XX_GPIO_8          (1 << 8)
+#define WM97XX_GPIO_9          (1 << 9)
+#define WM97XX_GPIO_10         (1 << 10)
+#define WM97XX_GPIO_11         (1 << 11)
+#define WM97XX_GPIO_12         (1 << 12)
+#define WM97XX_GPIO_13         (1 << 13)
+#define WM97XX_GPIO_14         (1 << 14)
+#define WM97XX_GPIO_15         (1 << 15)
+
+
+#define AC97_LINK_FRAME                21      /* time in uS for AC97 link frame */
+
+
+/*---------------- Return codes from sample reading functions ---------------*/
+
+/* More data is available; call the sample gathering function again */
+#define RC_AGAIN                       0x00000001
+/* The returned sample is valid */
+#define RC_VALID                       0x00000002
+/* The pen is up (the first RC_VALID without RC_PENUP means pen is down) */
+#define RC_PENUP                       0x00000004
+/* The pen is down (RC_VALID implies RC_PENDOWN, but sometimes it is helpful
+   to tell the handler that the pen is down but we don't know yet his coords,
+   so the handler should not sleep or wait for pendown irq) */
+#define RC_PENDOWN                     0x00000008
+
+/*
+ * The wm97xx driver provides a private API for writing platform-specific
+ * drivers.
+ */
+
+/* The structure used to return arch specific sampled data into */
+struct wm97xx_data {
+    int x;
+    int y;
+    int p;
+};
+
+/*
+ * Codec GPIO status
+ */
+enum wm97xx_gpio_status {
+    WM97XX_GPIO_HIGH,
+    WM97XX_GPIO_LOW
+};
+
+/*
+ * Codec GPIO direction
+ */
+enum wm97xx_gpio_dir {
+    WM97XX_GPIO_IN,
+    WM97XX_GPIO_OUT
+};
+
+/*
+ * Codec GPIO polarity
+ */
+enum wm97xx_gpio_pol {
+    WM97XX_GPIO_POL_HIGH,
+    WM97XX_GPIO_POL_LOW
+};
+
+/*
+ * Codec GPIO sticky
+ */
+enum wm97xx_gpio_sticky {
+    WM97XX_GPIO_STICKY,
+    WM97XX_GPIO_NOTSTICKY
+};
+
+/*
+ * Codec GPIO wake
+ */
+enum wm97xx_gpio_wake {
+    WM97XX_GPIO_WAKE,
+    WM97XX_GPIO_NOWAKE
+};
+
+/*
+ * Digitiser ioctl commands
+ */
+#define WM97XX_DIG_START       0x1
+#define WM97XX_DIG_STOP                0x2
+#define WM97XX_PHY_INIT                0x3
+#define WM97XX_AUX_PREPARE     0x4
+#define WM97XX_DIG_RESTORE     0x5
+
+struct wm97xx;
+
+extern struct wm97xx_codec_drv wm9705_codec;
+extern struct wm97xx_codec_drv wm9712_codec;
+extern struct wm97xx_codec_drv wm9713_codec;
+
+/*
+ * Codec driver interface - allows mapping to WM9705/12/13 and newer codecs
+ */
+struct wm97xx_codec_drv {
+       u16 id;
+       char *name;
+
+       /* read 1 sample */
+       int (*poll_sample) (struct wm97xx *, int adcsel, int *sample);
+
+       /* read X,Y,[P] in poll */
+       int (*poll_touch) (struct wm97xx *, struct wm97xx_data *);
+
+       int (*acc_enable) (struct wm97xx *, int enable);
+       void (*phy_init) (struct wm97xx *);
+       void (*dig_enable) (struct wm97xx *, int enable);
+       void (*dig_restore) (struct wm97xx *);
+       void (*aux_prepare) (struct wm97xx *);
+};
+
+
+/* Machine specific and accelerated touch operations */
+struct wm97xx_mach_ops {
+
+       /* accelerated touch readback - coords are transmited on AC97 link */
+       int acc_enabled;
+       void (*acc_pen_up) (struct wm97xx *);
+       int (*acc_pen_down) (struct wm97xx *);
+       int (*acc_startup) (struct wm97xx *);
+       void (*acc_shutdown) (struct wm97xx *);
+
+       /* interrupt mask control - required for accelerated operation */
+       void (*irq_enable) (struct wm97xx *, int enable);
+
+       /* GPIO pin used for accelerated operation */
+       int irq_gpio;
+
+       /* pre and post sample - can be used to minimise any analog noise */
+       void (*pre_sample) (int);  /* function to run before sampling */
+       void (*post_sample) (int);  /* function to run after sampling */
+};
+
+struct wm97xx {
+       u16 dig[3], id, gpio[6], misc;  /* Cached codec registers */
+       u16 dig_save[3];                /* saved during aux reading */
+       struct wm97xx_codec_drv *codec; /* attached codec driver*/
+       struct input_dev *input_dev;    /* touchscreen input device */
+       struct snd_ac97 *ac97;          /* ALSA codec access */
+       struct device *dev;             /* ALSA device */
+       struct platform_device *battery_dev;
+       struct platform_device *touch_dev;
+       struct wm97xx_mach_ops *mach_ops;
+       struct mutex codec_mutex;
+       struct delayed_work ts_reader;  /* Used to poll touchscreen */
+       unsigned long ts_reader_interval; /* Current interval for timer */
+       unsigned long ts_reader_min_interval; /* Minimum interval */
+       unsigned int pen_irq;           /* Pen IRQ number in use */
+       struct workqueue_struct *ts_workq;
+       struct work_struct pen_event_work;
+       u16 acc_slot;                   /* AC97 slot used for acc touch data */
+       u16 acc_rate;                   /* acc touch data rate */
+       unsigned pen_is_down:1;         /* Pen is down */
+       unsigned aux_waiting:1;         /* aux measurement waiting */
+       unsigned pen_probably_down:1;   /* used in polling mode */
+       u16 suspend_mode;               /* PRP in suspend mode */
+};
+
+/*
+ * Codec GPIO access (not supported on WM9705)
+ * This can be used to set/get codec GPIO and Virtual GPIO status.
+ */
+enum wm97xx_gpio_status wm97xx_get_gpio(struct wm97xx *wm, u32 gpio);
+void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio,
+                         enum wm97xx_gpio_status status);
+void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio,
+                                    enum wm97xx_gpio_dir dir,
+                                    enum wm97xx_gpio_pol pol,
+                                    enum wm97xx_gpio_sticky sticky,
+                                    enum wm97xx_gpio_wake wake);
+
+void wm97xx_set_suspend_mode(struct wm97xx *wm, u16 mode);
+
+/* codec AC97 IO access */
+int wm97xx_reg_read(struct wm97xx *wm, u16 reg);
+void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val);
+
+/* aux adc readback */
+int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel);
+
+/* machine ops */
+int wm97xx_register_mach_ops(struct wm97xx *, struct wm97xx_mach_ops *);
+void wm97xx_unregister_mach_ops(struct wm97xx *);
+
+#endif
index 0c82c80b277f935f25e43c2a83ea348b1481153a..2ca6bae88721920215a649bc437393733452aae9 100644 (file)
@@ -97,10 +97,10 @@ struct xfrm_algo {
 };
 
 struct xfrm_algo_aead {
-       char    alg_name[64];
-       int     alg_key_len;    /* in bits */
-       int     alg_icv_len;    /* in bits */
-       char    alg_key[0];
+       char            alg_name[64];
+       unsigned int    alg_key_len;    /* in bits */
+       unsigned int    alg_icv_len;    /* in bits */
+       char            alg_key[0];
 };
 
 struct xfrm_stats {
index 4d46b3bdebd86ce579c0c057e53f28be412651af..8eb018f96002d84f7ae3a0810023cffc65333f04 100644 (file)
@@ -3,5 +3,4 @@ header-y += jffs2-user.h
 header-y += mtd-abi.h
 header-y += mtd-user.h
 header-y += nftl-user.h
-header-y += ubi-header.h
 header-y += ubi-user.h
index b8b19e2f57bbece76e739752961ce91979512f23..f6a9fe0ef09c62cf38b28f6cdd9bfd9bad06121a 100644 (file)
@@ -181,7 +181,8 @@ struct scsi_device {
        sdev_printk(prefix, (scmd)->device, fmt, ##a)
 
 enum scsi_target_state {
-       STARGET_RUNNING = 1,
+       STARGET_CREATED = 1,
+       STARGET_RUNNING,
        STARGET_DEL,
 };
 
diff --git a/include/xen/balloon.h b/include/xen/balloon.h
new file mode 100644 (file)
index 0000000..fe43b0f
--- /dev/null
@@ -0,0 +1,61 @@
+/******************************************************************************
+ * balloon.h
+ *
+ * Xen balloon driver - enables returning/claiming memory to/from Xen.
+ *
+ * Copyright (c) 2003, B Dragovic
+ * Copyright (c) 2003-2004, M Williamson, K Fraser
+ *
+ * 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; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_BALLOON_H__
+#define __XEN_BALLOON_H__
+
+#include <linux/spinlock.h>
+
+#if 0
+/*
+ * Inform the balloon driver that it should allow some slop for device-driver
+ * memory activities.
+ */
+void balloon_update_driver_allowance(long delta);
+
+/* Allocate/free a set of empty pages in low memory (i.e., no RAM mapped). */
+struct page **alloc_empty_pages_and_pagevec(int nr_pages);
+void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages);
+
+void balloon_release_driver_page(struct page *page);
+
+/*
+ * Prevent the balloon driver from changing the memory reservation during
+ * a driver critical region.
+ */
+extern spinlock_t balloon_lock;
+#define balloon_lock(__flags)   spin_lock_irqsave(&balloon_lock, __flags)
+#define balloon_unlock(__flags) spin_unlock_irqrestore(&balloon_lock, __flags)
+#endif
+
+#endif /* __XEN_BALLOON_H__ */
index 2bde54d29be52f3b8ffc9558590cff65d4cacd31..acd8e062c85f381b5520c2ac27f13681053bedd0 100644 (file)
@@ -5,13 +5,7 @@
 
 #include <xen/interface/event_channel.h>
 #include <asm/xen/hypercall.h>
-
-enum ipi_vector {
-       XEN_RESCHEDULE_VECTOR,
-       XEN_CALL_FUNCTION_VECTOR,
-
-       XEN_NR_IPIS,
-};
+#include <asm/xen/events.h>
 
 int bind_evtchn_to_irq(unsigned int evtchn);
 int bind_evtchn_to_irqhandler(unsigned int evtchn,
@@ -37,6 +31,7 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi,
 void unbind_from_irqhandler(unsigned int irq, void *dev_id);
 
 void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector);
+int resend_irq_on_evtchn(unsigned int irq);
 
 static inline void notify_remote_via_evtchn(int port)
 {
index 761c83498e032f2a78e7972305bed0f421446e99..466204846121541fe4192131cf4142c315c8f19a 100644 (file)
@@ -39,6 +39,7 @@
 
 #include <asm/xen/hypervisor.h>
 #include <xen/interface/grant_table.h>
+#include <asm/xen/grant_table.h>
 
 /* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
 #define NR_GRANT_FRAMES 4
@@ -102,6 +103,12 @@ void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
 void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid,
                                       unsigned long pfn);
 
+int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
+                          unsigned long max_nr_gframes,
+                          struct grant_entry **__shared);
+void arch_gnttab_unmap_shared(struct grant_entry *shared,
+                             unsigned long nr_gframes);
+
 #define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr))
 
 #endif /* __ASM_GNTTAB_H__ */
diff --git a/include/xen/interface/callback.h b/include/xen/interface/callback.h
new file mode 100644 (file)
index 0000000..4aadcba
--- /dev/null
@@ -0,0 +1,102 @@
+/******************************************************************************
+ * callback.h
+ *
+ * Register guest OS callbacks with Xen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2006, Ian Campbell
+ */
+
+#ifndef __XEN_PUBLIC_CALLBACK_H__
+#define __XEN_PUBLIC_CALLBACK_H__
+
+#include "xen.h"
+
+/*
+ * Prototype for this hypercall is:
+ *   long callback_op(int cmd, void *extra_args)
+ * @cmd        == CALLBACKOP_??? (callback operation).
+ * @extra_args == Operation-specific extra arguments (NULL if none).
+ */
+
+/* ia64, x86: Callback for event delivery. */
+#define CALLBACKTYPE_event                 0
+
+/* x86: Failsafe callback when guest state cannot be restored by Xen. */
+#define CALLBACKTYPE_failsafe              1
+
+/* x86/64 hypervisor: Syscall by 64-bit guest app ('64-on-64-on-64'). */
+#define CALLBACKTYPE_syscall               2
+
+/*
+ * x86/32 hypervisor: Only available on x86/32 when supervisor_mode_kernel
+ *     feature is enabled. Do not use this callback type in new code.
+ */
+#define CALLBACKTYPE_sysenter_deprecated   3
+
+/* x86: Callback for NMI delivery. */
+#define CALLBACKTYPE_nmi                   4
+
+/*
+ * x86: sysenter is only available as follows:
+ * - 32-bit hypervisor: with the supervisor_mode_kernel feature enabled
+ * - 64-bit hypervisor: 32-bit guest applications on Intel CPUs
+ *                      ('32-on-32-on-64', '32-on-64-on-64')
+ *                      [nb. also 64-bit guest applications on Intel CPUs
+ *                           ('64-on-64-on-64'), but syscall is preferred]
+ */
+#define CALLBACKTYPE_sysenter              5
+
+/*
+ * x86/64 hypervisor: Syscall by 32-bit guest app on AMD CPUs
+ *                    ('32-on-32-on-64', '32-on-64-on-64')
+ */
+#define CALLBACKTYPE_syscall32             7
+
+/*
+ * Disable event deliver during callback? This flag is ignored for event and
+ * NMI callbacks: event delivery is unconditionally disabled.
+ */
+#define _CALLBACKF_mask_events             0
+#define CALLBACKF_mask_events              (1U << _CALLBACKF_mask_events)
+
+/*
+ * Register a callback.
+ */
+#define CALLBACKOP_register                0
+struct callback_register {
+    uint16_t type;
+    uint16_t flags;
+    struct xen_callback address;
+};
+
+/*
+ * Unregister a callback.
+ *
+ * Not all callbacks can be unregistered. -EINVAL will be returned if
+ * you attempt to unregister such a callback.
+ */
+#define CALLBACKOP_unregister              1
+struct callback_unregister {
+    uint16_t type;
+    uint16_t _unused;
+};
+
+#endif /* __XEN_PUBLIC_CALLBACK_H__ */
index 219049802cf25d28da2847fff536245925509954..39da93c21de05b3503c0b7e98c6bfefebee42b12 100644 (file)
@@ -185,6 +185,7 @@ struct gnttab_map_grant_ref {
     grant_handle_t handle;
     uint64_t dev_bus_addr;
 };
+DEFINE_GUEST_HANDLE_STRUCT(gnttab_map_grant_ref);
 
 /*
  * GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings
@@ -206,6 +207,7 @@ struct gnttab_unmap_grant_ref {
     /* OUT parameters. */
     int16_t  status;              /* GNTST_* */
 };
+DEFINE_GUEST_HANDLE_STRUCT(gnttab_unmap_grant_ref);
 
 /*
  * GNTTABOP_setup_table: Set up a grant table for <dom> comprising at least
@@ -223,8 +225,9 @@ struct gnttab_setup_table {
     uint32_t nr_frames;
     /* OUT parameters. */
     int16_t  status;              /* GNTST_* */
-    ulong *frame_list;
+    GUEST_HANDLE(ulong) frame_list;
 };
+DEFINE_GUEST_HANDLE_STRUCT(gnttab_setup_table);
 
 /*
  * GNTTABOP_dump_table: Dump the contents of the grant table to the
@@ -237,6 +240,7 @@ struct gnttab_dump_table {
     /* OUT parameters. */
     int16_t status;               /* GNTST_* */
 };
+DEFINE_GUEST_HANDLE_STRUCT(gnttab_dump_table);
 
 /*
  * GNTTABOP_transfer_grant_ref: Transfer <frame> to a foreign domain. The
@@ -255,7 +259,7 @@ struct gnttab_transfer {
     /* OUT parameters. */
     int16_t       status;
 };
-
+DEFINE_GUEST_HANDLE_STRUCT(gnttab_transfer);
 
 /*
  * GNTTABOP_copy: Hypervisor based copy
@@ -296,6 +300,7 @@ struct gnttab_copy {
        /* OUT parameters. */
        int16_t       status;
 };
+DEFINE_GUEST_HANDLE_STRUCT(gnttab_copy);
 
 /*
  * GNTTABOP_query_size: Query the current and maximum sizes of the shared
@@ -313,7 +318,7 @@ struct gnttab_query_size {
     uint32_t max_nr_frames;
     int16_t  status;              /* GNTST_* */
 };
-
+DEFINE_GUEST_HANDLE_STRUCT(gnttab_query_size);
 
 /*
  * Bitfield values for update_pin_status.flags.
diff --git a/include/xen/interface/io/fbif.h b/include/xen/interface/io/fbif.h
new file mode 100644 (file)
index 0000000..5a934dd
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * fbif.h -- Xen virtual frame buffer device
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
+ * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
+ */
+
+#ifndef __XEN_PUBLIC_IO_FBIF_H__
+#define __XEN_PUBLIC_IO_FBIF_H__
+
+/* Out events (frontend -> backend) */
+
+/*
+ * Out events may be sent only when requested by backend, and receipt
+ * of an unknown out event is an error.
+ */
+
+/* Event type 1 currently not used */
+/*
+ * Framebuffer update notification event
+ * Capable frontend sets feature-update in xenstore.
+ * Backend requests it by setting request-update in xenstore.
+ */
+#define XENFB_TYPE_UPDATE 2
+
+struct xenfb_update {
+       uint8_t type;           /* XENFB_TYPE_UPDATE */
+       int32_t x;              /* source x */
+       int32_t y;              /* source y */
+       int32_t width;          /* rect width */
+       int32_t height;         /* rect height */
+};
+
+#define XENFB_OUT_EVENT_SIZE 40
+
+union xenfb_out_event {
+       uint8_t type;
+       struct xenfb_update update;
+       char pad[XENFB_OUT_EVENT_SIZE];
+};
+
+/* In events (backend -> frontend) */
+
+/*
+ * Frontends should ignore unknown in events.
+ * No in events currently defined.
+ */
+
+#define XENFB_IN_EVENT_SIZE 40
+
+union xenfb_in_event {
+       uint8_t type;
+       char pad[XENFB_IN_EVENT_SIZE];
+};
+
+/* shared page */
+
+#define XENFB_IN_RING_SIZE 1024
+#define XENFB_IN_RING_LEN (XENFB_IN_RING_SIZE / XENFB_IN_EVENT_SIZE)
+#define XENFB_IN_RING_OFFS 1024
+#define XENFB_IN_RING(page) \
+       ((union xenfb_in_event *)((char *)(page) + XENFB_IN_RING_OFFS))
+#define XENFB_IN_RING_REF(page, idx) \
+       (XENFB_IN_RING((page))[(idx) % XENFB_IN_RING_LEN])
+
+#define XENFB_OUT_RING_SIZE 2048
+#define XENFB_OUT_RING_LEN (XENFB_OUT_RING_SIZE / XENFB_OUT_EVENT_SIZE)
+#define XENFB_OUT_RING_OFFS (XENFB_IN_RING_OFFS + XENFB_IN_RING_SIZE)
+#define XENFB_OUT_RING(page) \
+       ((union xenfb_out_event *)((char *)(page) + XENFB_OUT_RING_OFFS))
+#define XENFB_OUT_RING_REF(page, idx) \
+       (XENFB_OUT_RING((page))[(idx) % XENFB_OUT_RING_LEN])
+
+struct xenfb_page {
+       uint32_t in_cons, in_prod;
+       uint32_t out_cons, out_prod;
+
+       int32_t width;          /* width of the framebuffer (in pixels) */
+       int32_t height;         /* height of the framebuffer (in pixels) */
+       uint32_t line_length;   /* length of a row of pixels (in bytes) */
+       uint32_t mem_length;    /* length of the framebuffer (in bytes) */
+       uint8_t depth;          /* depth of a pixel (in bits) */
+
+       /*
+        * Framebuffer page directory
+        *
+        * Each directory page holds PAGE_SIZE / sizeof(*pd)
+        * framebuffer pages, and can thus map up to PAGE_SIZE *
+        * PAGE_SIZE / sizeof(*pd) bytes.  With PAGE_SIZE == 4096 and
+        * sizeof(unsigned long) == 4, that's 4 Megs.  Two directory
+        * pages should be enough for a while.
+        */
+       unsigned long pd[2];
+};
+
+/*
+ * Wart: xenkbd needs to know resolution.  Put it here until a better
+ * solution is found, but don't leak it to the backend.
+ */
+#ifdef __KERNEL__
+#define XENFB_WIDTH 800
+#define XENFB_HEIGHT 600
+#define XENFB_DEPTH 32
+#endif
+
+#endif
diff --git a/include/xen/interface/io/kbdif.h b/include/xen/interface/io/kbdif.h
new file mode 100644 (file)
index 0000000..fb97f42
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * kbdif.h -- Xen virtual keyboard/mouse
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
+ * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
+ */
+
+#ifndef __XEN_PUBLIC_IO_KBDIF_H__
+#define __XEN_PUBLIC_IO_KBDIF_H__
+
+/* In events (backend -> frontend) */
+
+/*
+ * Frontends should ignore unknown in events.
+ */
+
+/* Pointer movement event */
+#define XENKBD_TYPE_MOTION  1
+/* Event type 2 currently not used */
+/* Key event (includes pointer buttons) */
+#define XENKBD_TYPE_KEY     3
+/*
+ * Pointer position event
+ * Capable backend sets feature-abs-pointer in xenstore.
+ * Frontend requests ot instead of XENKBD_TYPE_MOTION by setting
+ * request-abs-update in xenstore.
+ */
+#define XENKBD_TYPE_POS     4
+
+struct xenkbd_motion {
+       uint8_t type;           /* XENKBD_TYPE_MOTION */
+       int32_t rel_x;          /* relative X motion */
+       int32_t rel_y;          /* relative Y motion */
+};
+
+struct xenkbd_key {
+       uint8_t type;           /* XENKBD_TYPE_KEY */
+       uint8_t pressed;        /* 1 if pressed; 0 otherwise */
+       uint32_t keycode;       /* KEY_* from linux/input.h */
+};
+
+struct xenkbd_position {
+       uint8_t type;           /* XENKBD_TYPE_POS */
+       int32_t abs_x;          /* absolute X position (in FB pixels) */
+       int32_t abs_y;          /* absolute Y position (in FB pixels) */
+};
+
+#define XENKBD_IN_EVENT_SIZE 40
+
+union xenkbd_in_event {
+       uint8_t type;
+       struct xenkbd_motion motion;
+       struct xenkbd_key key;
+       struct xenkbd_position pos;
+       char pad[XENKBD_IN_EVENT_SIZE];
+};
+
+/* Out events (frontend -> backend) */
+
+/*
+ * Out events may be sent only when requested by backend, and receipt
+ * of an unknown out event is an error.
+ * No out events currently defined.
+ */
+
+#define XENKBD_OUT_EVENT_SIZE 40
+
+union xenkbd_out_event {
+       uint8_t type;
+       char pad[XENKBD_OUT_EVENT_SIZE];
+};
+
+/* shared page */
+
+#define XENKBD_IN_RING_SIZE 2048
+#define XENKBD_IN_RING_LEN (XENKBD_IN_RING_SIZE / XENKBD_IN_EVENT_SIZE)
+#define XENKBD_IN_RING_OFFS 1024
+#define XENKBD_IN_RING(page) \
+       ((union xenkbd_in_event *)((char *)(page) + XENKBD_IN_RING_OFFS))
+#define XENKBD_IN_RING_REF(page, idx) \
+       (XENKBD_IN_RING((page))[(idx) % XENKBD_IN_RING_LEN])
+
+#define XENKBD_OUT_RING_SIZE 1024
+#define XENKBD_OUT_RING_LEN (XENKBD_OUT_RING_SIZE / XENKBD_OUT_EVENT_SIZE)
+#define XENKBD_OUT_RING_OFFS (XENKBD_IN_RING_OFFS + XENKBD_IN_RING_SIZE)
+#define XENKBD_OUT_RING(page) \
+       ((union xenkbd_out_event *)((char *)(page) + XENKBD_OUT_RING_OFFS))
+#define XENKBD_OUT_RING_REF(page, idx) \
+       (XENKBD_OUT_RING((page))[(idx) % XENKBD_OUT_RING_LEN])
+
+struct xenkbd_page {
+       uint32_t in_cons, in_prod;
+       uint32_t out_cons, out_prod;
+};
+
+#endif
diff --git a/include/xen/interface/io/protocols.h b/include/xen/interface/io/protocols.h
new file mode 100644 (file)
index 0000000..01fc8ae
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __XEN_PROTOCOLS_H__
+#define __XEN_PROTOCOLS_H__
+
+#define XEN_IO_PROTO_ABI_X86_32     "x86_32-abi"
+#define XEN_IO_PROTO_ABI_X86_64     "x86_64-abi"
+#define XEN_IO_PROTO_ABI_IA64       "ia64-abi"
+#define XEN_IO_PROTO_ABI_POWERPC64  "powerpc64-abi"
+
+#if defined(__i386__)
+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32
+#elif defined(__x86_64__)
+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_64
+#elif defined(__ia64__)
+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_IA64
+#elif defined(__powerpc64__)
+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_POWERPC64
+#else
+# error arch fixup needed here
+#endif
+
+#endif
index af36ead168170c1ded3819d523318490342d848e..da768469aa92b1a3cd948fc5f03f3cf0bd69751d 100644 (file)
@@ -29,7 +29,7 @@ struct xen_memory_reservation {
      *   OUT: GMFN bases of extents that were allocated
      *   (NB. This command also updates the mach_to_phys translation table)
      */
-    GUEST_HANDLE(ulong) extent_start;
+    ulong extent_start;
 
     /* Number of extents, and size/alignment of each (2^extent_order pages). */
     unsigned long  nr_extents;
@@ -50,7 +50,6 @@ struct xen_memory_reservation {
     domid_t        domid;
 
 };
-DEFINE_GUEST_HANDLE_STRUCT(xen_memory_reservation);
 
 /*
  * Returns the maximum machine frame number of mapped RAM in this system.
@@ -86,7 +85,7 @@ struct xen_machphys_mfn_list {
      * any large discontiguities in the machine address space, 2MB gaps in
      * the machphys table will be represented by an MFN base of zero.
      */
-    GUEST_HANDLE(ulong) extent_start;
+    ulong extent_start;
 
     /*
      * Number of extents written to the above array. This will be smaller
@@ -94,7 +93,6 @@ struct xen_machphys_mfn_list {
      */
     unsigned int nr_extents;
 };
-DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mfn_list);
 
 /*
  * Sets the GPFN at which a particular page appears in the specified guest's
@@ -117,7 +115,6 @@ struct xen_add_to_physmap {
     /* GPFN where the source mapping page should appear. */
     unsigned long gpfn;
 };
-DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap);
 
 /*
  * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error
@@ -132,14 +129,13 @@ struct xen_translate_gpfn_list {
     unsigned long nr_gpfns;
 
     /* List of GPFNs to translate. */
-    GUEST_HANDLE(ulong) gpfn_list;
+    ulong gpfn_list;
 
     /*
      * Output list to contain MFN translations. May be the same as the input
      * list (in which case each input GPFN is overwritten with the output MFN).
      */
-    GUEST_HANDLE(ulong) mfn_list;
+    ulong mfn_list;
 };
-DEFINE_GUEST_HANDLE_STRUCT(xen_translate_gpfn_list);
 
 #endif /* __XEN_PUBLIC_MEMORY_H__ */
index b05d8a6d91434f10b69b67e9c85d8835d92fda11..87e6f8a4866198d022930a2af17db0e23153a7b6 100644 (file)
@@ -85,6 +85,7 @@ struct vcpu_runstate_info {
                 */
                uint64_t time[4];
 };
+DEFINE_GUEST_HANDLE_STRUCT(vcpu_runstate_info);
 
 /* VCPU is currently running on a physical CPU. */
 #define RUNSTATE_running  0
@@ -119,6 +120,7 @@ struct vcpu_runstate_info {
 #define VCPUOP_register_runstate_memory_area 5
 struct vcpu_register_runstate_memory_area {
                union {
+                               GUEST_HANDLE(vcpu_runstate_info) h;
                                struct vcpu_runstate_info *v;
                                uint64_t p;
                } addr;
@@ -134,6 +136,7 @@ struct vcpu_register_runstate_memory_area {
 struct vcpu_set_periodic_timer {
                uint64_t period_ns;
 };
+DEFINE_GUEST_HANDLE_STRUCT(vcpu_set_periodic_timer);
 
 /*
  * Set or stop a VCPU's single-shot timer. Every VCPU has one single-shot
@@ -145,6 +148,7 @@ struct vcpu_set_singleshot_timer {
                uint64_t timeout_abs_ns;
                uint32_t flags;                    /* VCPU_SSHOTTMR_??? */
 };
+DEFINE_GUEST_HANDLE_STRUCT(vcpu_set_singleshot_timer);
 
 /* Flags to VCPUOP_set_singleshot_timer. */
  /* Require the timeout to be in the future (return -ETIME if it's passed). */
@@ -164,5 +168,6 @@ struct vcpu_register_vcpu_info {
     uint32_t offset; /* offset within page */
     uint32_t rsvd;   /* unused */
 };
+DEFINE_GUEST_HANDLE_STRUCT(vcpu_register_vcpu_info);
 
 #endif /* __XEN_PUBLIC_VCPU_H__ */
index 518a5bf79ed34becbf0b67e822421387124da534..9b018da48cf3145705af0a2f4f0b4228e8b1b889 100644 (file)
 #define __HYPERVISOR_physdev_op           33
 #define __HYPERVISOR_hvm_op               34
 
+/* Architecture-specific hypercall definitions. */
+#define __HYPERVISOR_arch_0               48
+#define __HYPERVISOR_arch_1               49
+#define __HYPERVISOR_arch_2               50
+#define __HYPERVISOR_arch_3               51
+#define __HYPERVISOR_arch_4               52
+#define __HYPERVISOR_arch_5               53
+#define __HYPERVISOR_arch_6               54
+#define __HYPERVISOR_arch_7               55
+
 /*
  * VIRTUAL INTERRUPTS
  *
 #define VIRQ_CONSOLE    2  /* (DOM0) Bytes received on emergency console. */
 #define VIRQ_DOM_EXC    3  /* (DOM0) Exceptional event for some domain.   */
 #define VIRQ_DEBUGGER   6  /* (DOM0) A domain has paused for debugging.   */
-#define NR_VIRQS        8
 
+/* Architecture-specific VIRQ definitions. */
+#define VIRQ_ARCH_0    16
+#define VIRQ_ARCH_1    17
+#define VIRQ_ARCH_2    18
+#define VIRQ_ARCH_3    19
+#define VIRQ_ARCH_4    20
+#define VIRQ_ARCH_5    21
+#define VIRQ_ARCH_6    22
+#define VIRQ_ARCH_7    23
+
+#define NR_VIRQS       24
 /*
  * MMU-UPDATE REQUESTS
  *
diff --git a/include/xen/interface/xencomm.h b/include/xen/interface/xencomm.h
new file mode 100644 (file)
index 0000000..ac45e07
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (C) IBM Corp. 2006
+ */
+
+#ifndef _XEN_XENCOMM_H_
+#define _XEN_XENCOMM_H_
+
+/* A xencomm descriptor is a scatter/gather list containing physical
+ * addresses corresponding to a virtually contiguous memory area. The
+ * hypervisor translates these physical addresses to machine addresses to copy
+ * to and from the virtually contiguous area.
+ */
+
+#define XENCOMM_MAGIC 0x58434F4D /* 'XCOM' */
+#define XENCOMM_INVALID (~0UL)
+
+struct xencomm_desc {
+    uint32_t magic;
+    uint32_t nr_addrs; /* the number of entries in address[] */
+    uint64_t address[0];
+};
+
+#endif /* _XEN_XENCOMM_H_ */
index 031ef22a971e551be070a15e61c4ad6f10ca225e..eaf85fab12632d45cc00d8976d9108a3eacc2850 100644 (file)
@@ -1,180 +1 @@
-#ifndef __XEN_PAGE_H
-#define __XEN_PAGE_H
-
-#include <linux/pfn.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-
-#include <xen/features.h>
-
-#ifdef CONFIG_X86_PAE
-/* Xen machine address */
-typedef struct xmaddr {
-       unsigned long long maddr;
-} xmaddr_t;
-
-/* Xen pseudo-physical address */
-typedef struct xpaddr {
-       unsigned long long paddr;
-} xpaddr_t;
-#else
-/* Xen machine address */
-typedef struct xmaddr {
-       unsigned long maddr;
-} xmaddr_t;
-
-/* Xen pseudo-physical address */
-typedef struct xpaddr {
-       unsigned long paddr;
-} xpaddr_t;
-#endif
-
-#define XMADDR(x)      ((xmaddr_t) { .maddr = (x) })
-#define XPADDR(x)      ((xpaddr_t) { .paddr = (x) })
-
-/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
-#define INVALID_P2M_ENTRY      (~0UL)
-#define FOREIGN_FRAME_BIT      (1UL<<31)
-#define FOREIGN_FRAME(m)       ((m) | FOREIGN_FRAME_BIT)
-
-extern unsigned long *phys_to_machine_mapping;
-
-static inline unsigned long pfn_to_mfn(unsigned long pfn)
-{
-       if (xen_feature(XENFEAT_auto_translated_physmap))
-               return pfn;
-
-       return phys_to_machine_mapping[(unsigned int)(pfn)] &
-               ~FOREIGN_FRAME_BIT;
-}
-
-static inline int phys_to_machine_mapping_valid(unsigned long pfn)
-{
-       if (xen_feature(XENFEAT_auto_translated_physmap))
-               return 1;
-
-       return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
-}
-
-static inline unsigned long mfn_to_pfn(unsigned long mfn)
-{
-       unsigned long pfn;
-
-       if (xen_feature(XENFEAT_auto_translated_physmap))
-               return mfn;
-
-#if 0
-       if (unlikely((mfn >> machine_to_phys_order) != 0))
-               return max_mapnr;
-#endif
-
-       pfn = 0;
-       /*
-        * The array access can fail (e.g., device space beyond end of RAM).
-        * In such cases it doesn't matter what we return (we return garbage),
-        * but we must handle the fault without crashing!
-        */
-       __get_user(pfn, &machine_to_phys_mapping[mfn]);
-
-       return pfn;
-}
-
-static inline xmaddr_t phys_to_machine(xpaddr_t phys)
-{
-       unsigned offset = phys.paddr & ~PAGE_MASK;
-       return XMADDR(PFN_PHYS((u64)pfn_to_mfn(PFN_DOWN(phys.paddr))) | offset);
-}
-
-static inline xpaddr_t machine_to_phys(xmaddr_t machine)
-{
-       unsigned offset = machine.maddr & ~PAGE_MASK;
-       return XPADDR(PFN_PHYS((u64)mfn_to_pfn(PFN_DOWN(machine.maddr))) | offset);
-}
-
-/*
- * We detect special mappings in one of two ways:
- *  1. If the MFN is an I/O page then Xen will set the m2p entry
- *     to be outside our maximum possible pseudophys range.
- *  2. If the MFN belongs to a different domain then we will certainly
- *     not have MFN in our p2m table. Conversely, if the page is ours,
- *     then we'll have p2m(m2p(MFN))==MFN.
- * If we detect a special mapping then it doesn't have a 'struct page'.
- * We force !pfn_valid() by returning an out-of-range pointer.
- *
- * NB. These checks require that, for any MFN that is not in our reservation,
- * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
- * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
- * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
- *
- * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
- *      use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
- *      require. In all the cases we care about, the FOREIGN_FRAME bit is
- *      masked (e.g., pfn_to_mfn()) so behaviour there is correct.
- */
-static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
-{
-       extern unsigned long max_mapnr;
-       unsigned long pfn = mfn_to_pfn(mfn);
-       if ((pfn < max_mapnr)
-           && !xen_feature(XENFEAT_auto_translated_physmap)
-           && (phys_to_machine_mapping[pfn] != mfn))
-               return max_mapnr; /* force !pfn_valid() */
-       return pfn;
-}
-
-static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
-{
-       if (xen_feature(XENFEAT_auto_translated_physmap)) {
-               BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
-               return;
-       }
-       phys_to_machine_mapping[pfn] = mfn;
-}
-
-/* VIRT <-> MACHINE conversion */
-#define virt_to_machine(v)     (phys_to_machine(XPADDR(__pa(v))))
-#define virt_to_mfn(v)         (pfn_to_mfn(PFN_DOWN(__pa(v))))
-#define mfn_to_virt(m)         (__va(mfn_to_pfn(m) << PAGE_SHIFT))
-
-#ifdef CONFIG_X86_PAE
-#define pte_mfn(_pte) (((_pte).pte_low >> PAGE_SHIFT) |                        \
-                      (((_pte).pte_high & 0xfff) << (32-PAGE_SHIFT)))
-
-static inline pte_t mfn_pte(unsigned long page_nr, pgprot_t pgprot)
-{
-       pte_t pte;
-
-       pte.pte_high = (page_nr >> (32 - PAGE_SHIFT)) |
-               (pgprot_val(pgprot) >> 32);
-       pte.pte_high &= (__supported_pte_mask >> 32);
-       pte.pte_low = ((page_nr << PAGE_SHIFT) | pgprot_val(pgprot));
-       pte.pte_low &= __supported_pte_mask;
-
-       return pte;
-}
-
-static inline unsigned long long pte_val_ma(pte_t x)
-{
-       return x.pte;
-}
-#define pmd_val_ma(v) ((v).pmd)
-#define pud_val_ma(v) ((v).pgd.pgd)
-#define __pte_ma(x)    ((pte_t) { .pte = (x) })
-#define __pmd_ma(x)    ((pmd_t) { (x) } )
-#else  /* !X86_PAE */
-#define pte_mfn(_pte) ((_pte).pte_low >> PAGE_SHIFT)
-#define mfn_pte(pfn, prot)     __pte_ma(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
-#define pte_val_ma(x)  ((x).pte)
-#define pmd_val_ma(v)  ((v).pud.pgd.pgd)
-#define __pte_ma(x)    ((pte_t) { (x) } )
-#endif /* CONFIG_X86_PAE */
-
-#define pgd_val_ma(x)  ((x).pgd)
-
-
-xmaddr_t arbitrary_virt_to_machine(unsigned long address);
-void make_lowmem_page_readonly(void *vaddr);
-void make_lowmem_page_readwrite(void *vaddr);
-
-#endif /* __XEN_PAGE_H */
+#include <asm/xen/page.h>
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
new file mode 100644 (file)
index 0000000..10ddfe0
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef INCLUDE_XEN_OPS_H
+#define INCLUDE_XEN_OPS_H
+
+#include <linux/percpu.h>
+
+DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
+
+#endif /* INCLUDE_XEN_OPS_H */
index 6f7c290651ae49d752b9c01f2178875c742f5ab2..6369d89c25d5346a6e8dcc4948218c883d900f37 100644 (file)
@@ -97,6 +97,7 @@ struct xenbus_driver {
        int (*uevent)(struct xenbus_device *, char **, int, char *, int);
        struct device_driver driver;
        int (*read_otherend_details)(struct xenbus_device *dev);
+       int (*is_ready)(struct xenbus_device *dev);
 };
 
 static inline struct xenbus_driver *to_xenbus_driver(struct device_driver *drv)
diff --git a/include/xen/xencomm.h b/include/xen/xencomm.h
new file mode 100644 (file)
index 0000000..e43b039
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ *          Jerone Young <jyoung5@us.ibm.com>
+ */
+
+#ifndef _LINUX_XENCOMM_H_
+#define _LINUX_XENCOMM_H_
+
+#include <xen/interface/xencomm.h>
+
+#define XENCOMM_MINI_ADDRS 3
+struct xencomm_mini {
+       struct xencomm_desc _desc;
+       uint64_t address[XENCOMM_MINI_ADDRS];
+};
+
+/* To avoid additionnal virt to phys conversion, an opaque structure is
+   presented.  */
+struct xencomm_handle;
+
+extern void xencomm_free(struct xencomm_handle *desc);
+extern struct xencomm_handle *xencomm_map(void *ptr, unsigned long bytes);
+extern struct xencomm_handle *__xencomm_map_no_alloc(void *ptr,
+                       unsigned long bytes,  struct xencomm_mini *xc_area);
+
+#if 0
+#define XENCOMM_MINI_ALIGNED(xc_desc, n)                               \
+       struct xencomm_mini xc_desc ## _base[(n)]                       \
+       __attribute__((__aligned__(sizeof(struct xencomm_mini))));      \
+       struct xencomm_mini *xc_desc = &xc_desc ## _base[0];
+#else
+/*
+ * gcc bug workaround:
+ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16660
+ * gcc doesn't handle properly stack variable with
+ * __attribute__((__align__(sizeof(struct xencomm_mini))))
+ */
+#define XENCOMM_MINI_ALIGNED(xc_desc, n)                               \
+       unsigned char xc_desc ## _base[((n) + 1 ) *                     \
+                                      sizeof(struct xencomm_mini)];    \
+       struct xencomm_mini *xc_desc = (struct xencomm_mini *)          \
+               ((unsigned long)xc_desc ## _base +                      \
+                (sizeof(struct xencomm_mini) -                         \
+                 ((unsigned long)xc_desc ## _base) %                   \
+                 sizeof(struct xencomm_mini)));
+#endif
+#define xencomm_map_no_alloc(ptr, bytes)                       \
+       ({ XENCOMM_MINI_ALIGNED(xc_desc, 1);                    \
+               __xencomm_map_no_alloc(ptr, bytes, xc_desc); })
+
+/* provided by architecture code: */
+extern unsigned long xencomm_vtop(unsigned long vaddr);
+
+static inline void *xencomm_pa(void *ptr)
+{
+       return (void *)xencomm_vtop((unsigned long)ptr);
+}
+
+#define xen_guest_handle(hnd)  ((hnd).p)
+
+#endif /* _LINUX_XENCOMM_H_ */
index 833a67df1f7e06c121c4b9b982893592ca7219df..1687b0167c4a4c458c0b7956a106fc678813c431 100644 (file)
@@ -521,7 +521,11 @@ static void __init boot_cpu_init(void)
        cpu_set(cpu, cpu_possible_map);
 }
 
-void __init __attribute__((weak)) smp_setup_processor_id(void)
+void __init __weak smp_setup_processor_id(void)
+{
+}
+
+void __init __weak thread_info_cache_init(void)
 {
 }
 
@@ -645,6 +649,7 @@ asmlinkage void __init start_kernel(void)
        if (efi_enabled)
                efi_enter_virtual_mode();
 #endif
+       thread_info_cache_init();
        fork_init(num_physpages);
        proc_caches_init();
        buffer_init();
index cece89f80ab4e0ed78d5c687a78b0ab1ced426b8..97f609f574b1843556a6a07fc4c6c50180725b31 100644 (file)
@@ -507,10 +507,9 @@ void put_files_struct(struct files_struct *files)
        }
 }
 
-EXPORT_SYMBOL(put_files_struct);
-
-void reset_files_struct(struct task_struct *tsk, struct files_struct *files)
+void reset_files_struct(struct files_struct *files)
 {
+       struct task_struct *tsk = current;
        struct files_struct *old;
 
        old = tsk->files;
@@ -519,7 +518,6 @@ void reset_files_struct(struct task_struct *tsk, struct files_struct *files)
        task_unlock(tsk);
        put_files_struct(old);
 }
-EXPORT_SYMBOL(reset_files_struct);
 
 void exit_files(struct task_struct *tsk)
 {
index 89fe414645e9b76aa777a0de7b5e9d6777814a0f..c674aa8d3c31e4af9a59abac87b2425faab135ff 100644 (file)
@@ -521,7 +521,7 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm)
  * Allocate a new mm structure and copy contents from the
  * mm structure of the passed in task structure.
  */
-static struct mm_struct *dup_mm(struct task_struct *tsk)
+struct mm_struct *dup_mm(struct task_struct *tsk)
 {
        struct mm_struct *mm, *oldmm = current->mm;
        int err;
@@ -805,12 +805,6 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
                goto out;
        }
 
-       /*
-        * Note: we may be using current for both targets (See exec.c)
-        * This works because we cache current->files (old) as oldf. Don't
-        * break this.
-        */
-       tsk->files = NULL;
        newf = dup_fd(oldf, &error);
        if (!newf)
                goto out;
@@ -846,34 +840,6 @@ static int copy_io(unsigned long clone_flags, struct task_struct *tsk)
        return 0;
 }
 
-/*
- *     Helper to unshare the files of the current task.
- *     We don't want to expose copy_files internals to
- *     the exec layer of the kernel.
- */
-
-int unshare_files(void)
-{
-       struct files_struct *files  = current->files;
-       int rc;
-
-       BUG_ON(!files);
-
-       /* This can race but the race causes us to copy when we don't
-          need to and drop the copy */
-       if(atomic_read(&files->count) == 1)
-       {
-               atomic_inc(&files->count);
-               return 0;
-       }
-       rc = copy_files(0, current);
-       if(rc)
-               current->files = files;
-       return rc;
-}
-
-EXPORT_SYMBOL(unshare_files);
-
 static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
 {
        struct sighand_struct *sig;
@@ -1811,3 +1777,27 @@ bad_unshare_cleanup_thread:
 bad_unshare_out:
        return err;
 }
+
+/*
+ *     Helper to unshare the files of the current task.
+ *     We don't want to expose copy_files internals to
+ *     the exec layer of the kernel.
+ */
+
+int unshare_files(struct files_struct **displaced)
+{
+       struct task_struct *task = current;
+       struct files_struct *copy = NULL;
+       int error;
+
+       error = unshare_fd(CLONE_FILES, &copy);
+       if (error || !copy) {
+               *displaced = NULL;
+               return error;
+       }
+       *displaced = task->files;
+       task_lock(task);
+       task->files = copy;
+       task_unlock(task);
+       return 0;
+}
index 0014b03adaca0af7d09d25d3b5c0df3c007b2462..740fb409e5bb32854dc9cc9b753cb25d83cdb7d4 100644 (file)
@@ -1656,42 +1656,6 @@ void aggregate_group_weight(struct task_group *tg, struct sched_domain *sd)
        aggregate(tg, sd)->task_weight = task_weight;
 }
 
-/*
- * Redistribute tg->shares amongst all tg->cfs_rq[]s.
- */
-static void __aggregate_redistribute_shares(struct task_group *tg)
-{
-       int i, max_cpu = smp_processor_id();
-       unsigned long rq_weight = 0;
-       unsigned long shares, max_shares = 0, shares_rem = tg->shares;
-
-       for_each_possible_cpu(i)
-               rq_weight += tg->cfs_rq[i]->load.weight;
-
-       for_each_possible_cpu(i) {
-               /*
-                * divide shares proportional to the rq_weights.
-                */
-               shares = tg->shares * tg->cfs_rq[i]->load.weight;
-               shares /= rq_weight + 1;
-
-               tg->cfs_rq[i]->shares = shares;
-
-               if (shares > max_shares) {
-                       max_shares = shares;
-                       max_cpu = i;
-               }
-               shares_rem -= shares;
-       }
-
-       /*
-        * Ensure it all adds up to tg->shares; we can loose a few
-        * due to rounding down when computing the per-cpu shares.
-        */
-       if (shares_rem)
-               tg->cfs_rq[max_cpu]->shares += shares_rem;
-}
-
 /*
  * Compute the weight of this group on the given cpus.
  */
@@ -1701,18 +1665,11 @@ void aggregate_group_shares(struct task_group *tg, struct sched_domain *sd)
        unsigned long shares = 0;
        int i;
 
-again:
        for_each_cpu_mask(i, sd->span)
                shares += tg->cfs_rq[i]->shares;
 
-       /*
-        * When the span doesn't have any shares assigned, but does have
-        * tasks to run do a machine wide rebalance (should be rare).
-        */
-       if (unlikely(!shares && aggregate(tg, sd)->rq_weight)) {
-               __aggregate_redistribute_shares(tg);
-               goto again;
-       }
+       if ((!shares && aggregate(tg, sd)->rq_weight) || shares > tg->shares)
+               shares = tg->shares;
 
        aggregate(tg, sd)->shares = shares;
 }
@@ -7991,11 +7948,6 @@ void __init sched_init_smp(void)
 #else
 void __init sched_init_smp(void)
 {
-#if defined(CONFIG_NUMA)
-       sched_group_nodes_bycpu = kzalloc(nr_cpu_ids * sizeof(void **),
-                                                               GFP_KERNEL);
-       BUG_ON(sched_group_nodes_bycpu == NULL);
-#endif
        sched_init_granularity();
 }
 #endif /* CONFIG_SMP */
@@ -8128,7 +8080,7 @@ void __init sched_init(void)
         * we use alloc_bootmem().
         */
        if (alloc_size) {
-               ptr = (unsigned long)alloc_bootmem_low(alloc_size);
+               ptr = (unsigned long)alloc_bootmem(alloc_size);
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
                init_task_group.se = (struct sched_entity **)ptr;
index d358d4e3a95806c2ff71544947dee234809fdb88..b854a895591efe4f1d40f522d079fe1de0cf256e 100644 (file)
@@ -393,6 +393,7 @@ void tick_nohz_restart_sched_tick(void)
                sub_preempt_count(HARDIRQ_OFFSET);
        }
 
+       touch_softlockup_watchdog();
        /*
         * Cancel the scheduled timer and restore the tick
         */
index 2d53dc092e8b1670bd26e6e3c6210f01caa54a29..8cc8e8722a3fac4f363125f2009fbf65d50cca58 100644 (file)
@@ -7,6 +7,12 @@ menu "Library routines"
 config BITREVERSE
        tristate
 
+config GENERIC_FIND_FIRST_BIT
+       def_bool n
+
+config GENERIC_FIND_NEXT_BIT
+       def_bool n
+
 config CRC_CCITT
        tristate "CRC-CCITT functions"
        help
index 623ef24c23812894c1617f0db781fb3065d6bdf2..754cc0027f2a8acc6f8358dd6a1ae0b1346845ba 100644 (file)
@@ -25,6 +25,17 @@ config ENABLE_MUST_CHECK
          suppress the "warning: ignoring return value of 'foo', declared with
          attribute warn_unused_result" messages.
 
+config FRAME_WARN
+       int "Warn for stack frames larger than (needs gcc 4.4)"
+       range 0 8192
+       default 1024 if !64BIT
+       default 2048 if 64BIT
+       help
+         Tell gcc to warn at build time for stack frames larger than this.
+         Setting this too low will cause a lot of warnings.
+         Setting it to 0 disables the warning.
+         Requires gcc 4.4
+
 config MAGIC_SYSRQ
        bool "Magic SysRq key"
        depends on !UML
index bf8000fc7d48e771eb560f10fde894c64bffbb63..2d7001b7f5a4d641be0c618a6405d4c9863b41fb 100644 (file)
@@ -29,6 +29,7 @@ obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
 obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
 lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
+lib-$(CONFIG_GENERIC_FIND_FIRST_BIT) += find_next_bit.o
 lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
 obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
 obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
index 78ccd73a884188f9e9348df1e4ad6e0e527e24c0..d3f5784807b45a00fa2301727951f6fb3e325f35 100644 (file)
 
 #define BITOP_WORD(nr)         ((nr) / BITS_PER_LONG)
 
-/**
- * find_next_bit - find the next set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
+#ifdef CONFIG_GENERIC_FIND_NEXT_BIT
+/*
+ * Find the next set bit in a memory region.
  */
-unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
-               unsigned long offset)
+unsigned long __find_next_bit(const unsigned long *addr,
+               unsigned long size, unsigned long offset)
 {
        const unsigned long *p = addr + BITOP_WORD(offset);
        unsigned long result = offset & ~(BITS_PER_LONG-1);
@@ -60,15 +58,14 @@ found_first:
 found_middle:
        return result + __ffs(tmp);
 }
-
-EXPORT_SYMBOL(find_next_bit);
+EXPORT_SYMBOL(__find_next_bit);
 
 /*
  * This implementation of find_{first,next}_zero_bit was stolen from
  * Linus' asm-alpha/bitops.h.
  */
-unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
-               unsigned long offset)
+unsigned long __find_next_zero_bit(const unsigned long *addr,
+               unsigned long size, unsigned long offset)
 {
        const unsigned long *p = addr + BITOP_WORD(offset);
        unsigned long result = offset & ~(BITS_PER_LONG-1);
@@ -105,8 +102,64 @@ found_first:
 found_middle:
        return result + ffz(tmp);
 }
+EXPORT_SYMBOL(__find_next_zero_bit);
+#endif /* CONFIG_GENERIC_FIND_NEXT_BIT */
+
+#ifdef CONFIG_GENERIC_FIND_FIRST_BIT
+/*
+ * Find the first set bit in a memory region.
+ */
+unsigned long __find_first_bit(const unsigned long *addr,
+               unsigned long size)
+{
+       const unsigned long *p = addr;
+       unsigned long result = 0;
+       unsigned long tmp;
 
-EXPORT_SYMBOL(find_next_zero_bit);
+       while (size & ~(BITS_PER_LONG-1)) {
+               if ((tmp = *(p++)))
+                       goto found;
+               result += BITS_PER_LONG;
+               size -= BITS_PER_LONG;
+       }
+       if (!size)
+               return result;
+
+       tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
+       if (tmp == 0UL)         /* Are any bits set? */
+               return result + size;   /* Nope. */
+found:
+       return result + __ffs(tmp);
+}
+EXPORT_SYMBOL(__find_first_bit);
+
+/*
+ * Find the first cleared bit in a memory region.
+ */
+unsigned long __find_first_zero_bit(const unsigned long *addr,
+               unsigned long size)
+{
+       const unsigned long *p = addr;
+       unsigned long result = 0;
+       unsigned long tmp;
+
+       while (size & ~(BITS_PER_LONG-1)) {
+               if (~(tmp = *(p++)))
+                       goto found;
+               result += BITS_PER_LONG;
+               size -= BITS_PER_LONG;
+       }
+       if (!size)
+               return result;
+
+       tmp = (*p) | (~0UL << size);
+       if (tmp == ~0UL)        /* Are any bits zero? */
+               return result + size;   /* Nope. */
+found:
+       return result + ffz(tmp);
+}
+EXPORT_SYMBOL(__find_first_zero_bit);
+#endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
 
 #ifdef __BIG_ENDIAN
 
index 2ccea700968f7ecaaa265023e79e52d540a82871..b6791646143e9a24e7aeaacef415e572e619da45 100644 (file)
@@ -111,44 +111,74 @@ static unsigned long __init init_bootmem_core(pg_data_t *pgdat,
  * might be used for boot-time allocations - or it might get added
  * to the free page pool later on.
  */
-static int __init reserve_bootmem_core(bootmem_data_t *bdata,
+static int __init can_reserve_bootmem_core(bootmem_data_t *bdata,
                        unsigned long addr, unsigned long size, int flags)
 {
        unsigned long sidx, eidx;
        unsigned long i;
-       int ret;
+
+       BUG_ON(!size);
+
+       /* out of range, don't hold other */
+       if (addr + size < bdata->node_boot_start ||
+               PFN_DOWN(addr) > bdata->node_low_pfn)
+               return 0;
 
        /*
-        * round up, partially reserved pages are considered
-        * fully reserved.
+        * Round up to index to the range.
         */
+       if (addr > bdata->node_boot_start)
+               sidx= PFN_DOWN(addr - bdata->node_boot_start);
+       else
+               sidx = 0;
+
+       eidx = PFN_UP(addr + size - bdata->node_boot_start);
+       if (eidx > bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start))
+               eidx = bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start);
+
+       for (i = sidx; i < eidx; i++) {
+               if (test_bit(i, bdata->node_bootmem_map)) {
+                       if (flags & BOOTMEM_EXCLUSIVE)
+                               return -EBUSY;
+               }
+       }
+
+       return 0;
+
+}
+
+static void __init reserve_bootmem_core(bootmem_data_t *bdata,
+                       unsigned long addr, unsigned long size, int flags)
+{
+       unsigned long sidx, eidx;
+       unsigned long i;
+
        BUG_ON(!size);
-       BUG_ON(PFN_DOWN(addr) >= bdata->node_low_pfn);
-       BUG_ON(PFN_UP(addr + size) > bdata->node_low_pfn);
-       BUG_ON(addr < bdata->node_boot_start);
 
-       sidx = PFN_DOWN(addr - bdata->node_boot_start);
+       /* out of range */
+       if (addr + size < bdata->node_boot_start ||
+               PFN_DOWN(addr) > bdata->node_low_pfn)
+               return;
+
+       /*
+        * Round up to index to the range.
+        */
+       if (addr > bdata->node_boot_start)
+               sidx= PFN_DOWN(addr - bdata->node_boot_start);
+       else
+               sidx = 0;
+
        eidx = PFN_UP(addr + size - bdata->node_boot_start);
+       if (eidx > bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start))
+               eidx = bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start);
 
-       for (i = sidx; i < eidx; i++)
+       for (i = sidx; i < eidx; i++) {
                if (test_and_set_bit(i, bdata->node_bootmem_map)) {
 #ifdef CONFIG_DEBUG_BOOTMEM
                        printk("hm, page %08lx reserved twice.\n", i*PAGE_SIZE);
 #endif
-                       if (flags & BOOTMEM_EXCLUSIVE) {
-                               ret = -EBUSY;
-                               goto err;
-                       }
                }
-
-       return 0;
-
-err:
-       /* unreserve memory we accidentally reserved */
-       for (i--; i >= sidx; i--)
-               clear_bit(i, bdata->node_bootmem_map);
-
-       return ret;
+       }
 }
 
 static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr,
@@ -206,9 +236,11 @@ void * __init
 __alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
              unsigned long align, unsigned long goal, unsigned long limit)
 {
-       unsigned long offset, remaining_size, areasize, preferred;
+       unsigned long areasize, preferred;
        unsigned long i, start = 0, incr, eidx, end_pfn;
        void *ret;
+       unsigned long node_boot_start;
+       void *node_bootmem_map;
 
        if (!size) {
                printk("__alloc_bootmem_core(): zero-sized request\n");
@@ -216,70 +248,83 @@ __alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
        }
        BUG_ON(align & (align-1));
 
-       if (limit && bdata->node_boot_start >= limit)
-               return NULL;
-
        /* on nodes without memory - bootmem_map is NULL */
        if (!bdata->node_bootmem_map)
                return NULL;
 
+       /* bdata->node_boot_start is supposed to be (12+6)bits alignment on x86_64 ? */
+       node_boot_start = bdata->node_boot_start;
+       node_bootmem_map = bdata->node_bootmem_map;
+       if (align) {
+               node_boot_start = ALIGN(bdata->node_boot_start, align);
+               if (node_boot_start > bdata->node_boot_start)
+                       node_bootmem_map = (unsigned long *)bdata->node_bootmem_map +
+                           PFN_DOWN(node_boot_start - bdata->node_boot_start)/BITS_PER_LONG;
+       }
+
+       if (limit && node_boot_start >= limit)
+               return NULL;
+
        end_pfn = bdata->node_low_pfn;
        limit = PFN_DOWN(limit);
        if (limit && end_pfn > limit)
                end_pfn = limit;
 
-       eidx = end_pfn - PFN_DOWN(bdata->node_boot_start);
-       offset = 0;
-       if (align && (bdata->node_boot_start & (align - 1UL)) != 0)
-               offset = align - (bdata->node_boot_start & (align - 1UL));
-       offset = PFN_DOWN(offset);
+       eidx = end_pfn - PFN_DOWN(node_boot_start);
 
        /*
         * We try to allocate bootmem pages above 'goal'
         * first, then we try to allocate lower pages.
         */
-       if (goal && goal >= bdata->node_boot_start && PFN_DOWN(goal) < end_pfn) {
-               preferred = goal - bdata->node_boot_start;
+       preferred = 0;
+       if (goal && PFN_DOWN(goal) < end_pfn) {
+               if (goal > node_boot_start)
+                       preferred = goal - node_boot_start;
 
-               if (bdata->last_success >= preferred)
+               if (bdata->last_success > node_boot_start &&
+                       bdata->last_success - node_boot_start >= preferred)
                        if (!limit || (limit && limit > bdata->last_success))
-                               preferred = bdata->last_success;
-       } else
-               preferred = 0;
+                               preferred = bdata->last_success - node_boot_start;
+       }
 
-       preferred = PFN_DOWN(ALIGN(preferred, align)) + offset;
+       preferred = PFN_DOWN(ALIGN(preferred, align));
        areasize = (size + PAGE_SIZE-1) / PAGE_SIZE;
        incr = align >> PAGE_SHIFT ? : 1;
 
 restart_scan:
-       for (i = preferred; i < eidx; i += incr) {
+       for (i = preferred; i < eidx;) {
                unsigned long j;
-               i = find_next_zero_bit(bdata->node_bootmem_map, eidx, i);
+
+               i = find_next_zero_bit(node_bootmem_map, eidx, i);
                i = ALIGN(i, incr);
                if (i >= eidx)
                        break;
-               if (test_bit(i, bdata->node_bootmem_map))
+               if (test_bit(i, node_bootmem_map)) {
+                       i += incr;
                        continue;
+               }
                for (j = i + 1; j < i + areasize; ++j) {
                        if (j >= eidx)
                                goto fail_block;
-                       if (test_bit(j, bdata->node_bootmem_map))
+                       if (test_bit(j, node_bootmem_map))
                                goto fail_block;
                }
                start = i;
                goto found;
        fail_block:
                i = ALIGN(j, incr);
+               if (i == j)
+                       i += incr;
        }
 
-       if (preferred > offset) {
-               preferred = offset;
+       if (preferred > 0) {
+               preferred = 0;
                goto restart_scan;
        }
        return NULL;
 
 found:
-       bdata->last_success = PFN_PHYS(start);
+       bdata->last_success = PFN_PHYS(start) + node_boot_start;
        BUG_ON(start >= eidx);
 
        /*
@@ -289,6 +334,7 @@ found:
         */
        if (align < PAGE_SIZE &&
            bdata->last_offset && bdata->last_pos+1 == start) {
+               unsigned long offset, remaining_size;
                offset = ALIGN(bdata->last_offset, align);
                BUG_ON(offset > PAGE_SIZE);
                remaining_size = PAGE_SIZE - offset;
@@ -297,14 +343,12 @@ found:
                        /* last_pos unchanged */
                        bdata->last_offset = offset + size;
                        ret = phys_to_virt(bdata->last_pos * PAGE_SIZE +
-                                          offset +
-                                          bdata->node_boot_start);
+                                          offset + node_boot_start);
                } else {
                        remaining_size = size - remaining_size;
                        areasize = (remaining_size + PAGE_SIZE-1) / PAGE_SIZE;
                        ret = phys_to_virt(bdata->last_pos * PAGE_SIZE +
-                                          offset +
-                                          bdata->node_boot_start);
+                                          offset + node_boot_start);
                        bdata->last_pos = start + areasize - 1;
                        bdata->last_offset = remaining_size;
                }
@@ -312,14 +356,14 @@ found:
        } else {
                bdata->last_pos = start + areasize - 1;
                bdata->last_offset = size & ~PAGE_MASK;
-               ret = phys_to_virt(start * PAGE_SIZE + bdata->node_boot_start);
+               ret = phys_to_virt(start * PAGE_SIZE + node_boot_start);
        }
 
        /*
         * Reserve the area now:
         */
        for (i = start; i < start + areasize; i++)
-               if (unlikely(test_and_set_bit(i, bdata->node_bootmem_map)))
+               if (unlikely(test_and_set_bit(i, node_bootmem_map)))
                        BUG();
        memset(ret, 0, size);
        return ret;
@@ -401,6 +445,11 @@ unsigned long __init init_bootmem_node(pg_data_t *pgdat, unsigned long freepfn,
 void __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
                                 unsigned long size, int flags)
 {
+       int ret;
+
+       ret = can_reserve_bootmem_core(pgdat->bdata, physaddr, size, flags);
+       if (ret < 0)
+               return;
        reserve_bootmem_core(pgdat->bdata, physaddr, size, flags);
 }
 
@@ -426,7 +475,18 @@ unsigned long __init init_bootmem(unsigned long start, unsigned long pages)
 int __init reserve_bootmem(unsigned long addr, unsigned long size,
                            int flags)
 {
-       return reserve_bootmem_core(NODE_DATA(0)->bdata, addr, size, flags);
+       bootmem_data_t *bdata;
+       int ret;
+
+       list_for_each_entry(bdata, &bdata_list, list) {
+               ret = can_reserve_bootmem_core(bdata, addr, size, flags);
+               if (ret < 0)
+                       return ret;
+       }
+       list_for_each_entry(bdata, &bdata_list, list)
+               reserve_bootmem_core(bdata, addr, size, flags);
+
+       return 0;
 }
 #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
 
index 997f06907b6da787798e71f515f44cd51495b771..e9bb6b1093f6a8c5cea56c88ed0e00304a92317c 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -413,9 +413,6 @@ int page_referenced(struct page *page, int is_locked,
 {
        int referenced = 0;
 
-       if (page_test_and_clear_young(page))
-               referenced++;
-
        if (TestClearPageReferenced(page))
                referenced++;
 
@@ -433,6 +430,10 @@ int page_referenced(struct page *page, int is_locked,
                        unlock_page(page);
                }
        }
+
+       if (page_test_and_clear_young(page))
+               referenced++;
+
        return referenced;
 }
 
index 98d6b39c34722c1734bee587a612ce0f74d7fbfa..7e9191381f86d0635e9ec68cda34cff6313ea859 100644 (file)
@@ -295,6 +295,9 @@ struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
        return NULL;
 }
 
+void __attribute__((weak)) __meminit vmemmap_populate_print_last(void)
+{
+}
 /*
  * Allocate the accumulated non-linear sections, allocate a mem_map
  * for each and record the physical to section mapping.
@@ -304,22 +307,50 @@ void __init sparse_init(void)
        unsigned long pnum;
        struct page *map;
        unsigned long *usemap;
+       unsigned long **usemap_map;
+       int size;
+
+       /*
+        * map is using big page (aka 2M in x86 64 bit)
+        * usemap is less one page (aka 24 bytes)
+        * so alloc 2M (with 2M align) and 24 bytes in turn will
+        * make next 2M slip to one more 2M later.
+        * then in big system, the memory will have a lot of holes...
+        * here try to allocate 2M pages continously.
+        *
+        * powerpc need to call sparse_init_one_section right after each
+        * sparse_early_mem_map_alloc, so allocate usemap_map at first.
+        */
+       size = sizeof(unsigned long *) * NR_MEM_SECTIONS;
+       usemap_map = alloc_bootmem(size);
+       if (!usemap_map)
+               panic("can not allocate usemap_map\n");
 
        for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
                if (!present_section_nr(pnum))
                        continue;
+               usemap_map[pnum] = sparse_early_usemap_alloc(pnum);
+       }
 
-               map = sparse_early_mem_map_alloc(pnum);
-               if (!map)
+       for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
+               if (!present_section_nr(pnum))
                        continue;
 
-               usemap = sparse_early_usemap_alloc(pnum);
+               usemap = usemap_map[pnum];
                if (!usemap)
                        continue;
 
+               map = sparse_early_mem_map_alloc(pnum);
+               if (!map)
+                       continue;
+
                sparse_init_one_section(__nr_to_section(pnum), pnum, map,
                                                                usemap);
        }
+
+       vmemmap_populate_print_last();
+
+       free_bootmem(__pa(usemap_map), size);
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
index ead50c7c0d40f54e8b05d7b1c9e04cdef5b92fb2..201cbfc6b9ece724b3cda9427f27d976534567c7 100644 (file)
@@ -573,7 +573,8 @@ static int raw_getsockopt(struct socket *sock, int level, int optname,
                        int fsize = ro->count * sizeof(struct can_filter);
                        if (len > fsize)
                                len = fsize;
-                       err = copy_to_user(optval, ro->filter, len);
+                       if (copy_to_user(optval, ro->filter, len))
+                               err = -EFAULT;
                } else
                        len = 0;
                release_sock(sk);
index a29b43d0b450a5e1a265375bd4f77797f0b23d79..0133b5ebd545287be9a2ee19d8fbf75db8e9ca59 100644 (file)
@@ -323,6 +323,11 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
                bytes_remaining -= eeprom.len;
        }
 
+       eeprom.len = userbuf - (useraddr + sizeof(eeprom));
+       eeprom.offset -= eeprom.len;
+       if (copy_to_user(useraddr, &eeprom, sizeof(eeprom)))
+               ret = -EFAULT;
+
        kfree(data);
        return ret;
 }
index 6e1df62bd7c9167dc6e123b20c5af79ce30537c3..0bcdc92502794867b7254bc338044555b6493245 100644 (file)
@@ -140,7 +140,7 @@ static ssize_t dccpprobe_read(struct file *file, char __user *buf,
                goto out_free;
 
        cnt = kfifo_get(dccpw.fifo, tbuf, len);
-       error = copy_to_user(buf, tbuf, cnt);
+       error = copy_to_user(buf, tbuf, cnt) ? -EFAULT : 0;
 
 out_free:
        vfree(tbuf);
index 1c509592574a79d6ee53a6104e8cfe6466058a5c..5ff0ce6e9d39d25538f5c98dff986231fbaebcc9 100644 (file)
@@ -190,19 +190,18 @@ static ssize_t tcpprobe_read(struct file *file, char __user *buf,
 
                width = tcpprobe_sprint(tbuf, sizeof(tbuf));
 
-               if (width < len)
+               if (cnt + width < len)
                        tcp_probe.tail = (tcp_probe.tail + 1) % bufsize;
 
                spin_unlock_bh(&tcp_probe.lock);
 
                /* if record greater than space available
                   return partial buffer (so far) */
-               if (width >= len)
+               if (cnt + width >= len)
                        break;
 
-               error = copy_to_user(buf + cnt, tbuf, width);
-               if (error)
-                       break;
+               if (copy_to_user(buf + cnt, tbuf, width))
+                       return -EFAULT;
                cnt += width;
        }
 
index 42814a2ec9d73f0249b53386e997104cde4dee64..b2c9becc02e8cad4e6453578587cabc6a7701c52 100644 (file)
@@ -167,7 +167,7 @@ config IPV6_SIT
          Tunneling means encapsulating data of one protocol type within
          another protocol and sending it over a channel that understands the
          encapsulating protocol. This driver implements encapsulation of IPv6
-         into IPv4 packets. This is useful if you want to connect two IPv6
+         into IPv4 packets. This is useful if you want to connect to IPv6
          networks over an IPv4-only path.
 
          Saying M here will produce a module called sit.ko. If unsure, say Y.
index 6193b124cbc764bd367df15addead75c07ae0322..396f0ea11090a98d6a07898d0e79d58fb7652313 100644 (file)
@@ -971,6 +971,19 @@ static int do_rawv6_setsockopt(struct sock *sk, int level, int optname,
 
        switch (optname) {
                case IPV6_CHECKSUM:
+                       if (inet_sk(sk)->num == IPPROTO_ICMPV6 &&
+                           level == IPPROTO_IPV6) {
+                               /*
+                                * RFC3542 tells that IPV6_CHECKSUM socket
+                                * option in the IPPROTO_IPV6 level is not
+                                * allowed on ICMPv6 sockets.
+                                * If you want to set it, use IPPROTO_RAW
+                                * level IPV6_CHECKSUM socket option
+                                * (Linux extension).
+                                */
+                               return -EINVAL;
+                       }
+
                        /* You may get strange result with a positive odd offset;
                           RFC2292bis agrees with me. */
                        if (val > 0 && (val&1))
@@ -1046,6 +1059,11 @@ static int do_rawv6_getsockopt(struct sock *sk, int level, int optname,
 
        switch (optname) {
        case IPV6_CHECKSUM:
+               /*
+                * We allow getsockopt() for IPPROTO_IPV6-level
+                * IPV6_CHECKSUM socket option on ICMPv6 sockets
+                * since RFC3542 is silent about it.
+                */
                if (rp->checksum == 0)
                        val = -1;
                else
index 81a8e5297ad113be9d1c09de897df283532c9632..2403a31fe0f64ea6de774982e2ba3c6b7ea36a35 100644 (file)
@@ -2356,7 +2356,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
        struct xfrm_selector sel;
        struct km_event c;
        struct sadb_x_sec_ctx *sec_ctx;
-       struct xfrm_sec_ctx *pol_ctx;
+       struct xfrm_sec_ctx *pol_ctx = NULL;
 
        if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
                                     ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -2396,8 +2396,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
                kfree(uctx);
                if (err)
                        return err;
-       } else
-               pol_ctx = NULL;
+       }
 
        xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN,
                                   pol->sadb_x_policy_dir - 1, &sel, pol_ctx,
index 742003d3a84112b91640b76f255ccb88d303ea44..9ee3affab346a548bc4f046afac9c7fc07134b11 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/types.h>
 #include <linux/jhash.h>
+#include <asm/unaligned.h>
 #include "ieee80211_i.h"
 
 
index 02de8f1522a3492edf8904942980564031f2cacf..3df809222d1cbcfc1c88605d0406303ed1d25098 100644 (file)
@@ -7,7 +7,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <asm/unaligned.h>
 #include "mesh.h"
 
 #define TEST_FRAME_LEN 8192
index 6d38a81b336d50e89942637f8ad8b715c2a0ae7f..ba3f6e49fddc59164fed12773b483ee699aa1a3d 100644 (file)
@@ -493,8 +493,8 @@ static int rxkad_verify_packet(const struct rxrpc_call *call,
                __be32 x[2];
        } tmpbuf __attribute__((aligned(8))); /* must all be in same page */
        __be32 x;
-       u16 y;
        __be16 cksum;
+       u32 y;
        int ret;
 
        sp = rxrpc_skb(skb);
index 05853159536a03b984708c400808dcf6e26fcb77..230f9ca2ad6b361dd4e78e6a2f1247334e9b9d22 100644 (file)
@@ -1756,8 +1756,8 @@ static int getsockopt(struct socket *sock,
        else if (len < sizeof(value)) {
                res = -EINVAL;
        }
-       else if ((res = copy_to_user(ov, &value, sizeof(value)))) {
-               /* couldn't return value */
+       else if (copy_to_user(ov, &value, sizeof(value))) {
+               res = -EFAULT;
        }
        else {
                res = put_user(sizeof(value), ol);
index 67fb4530a6ff88afb7e3a86945dc2837c87c72f5..277cfe0b71001e69bc67d3eda6407250d07d7ab8 100644 (file)
@@ -27,12 +27,12 @@ ccflags-y  :=
 cppflags-y :=
 ldflags-y  :=
 
-# Read .config if it exist, otherwise ignore
+# Read auto.conf if it exists, otherwise ignore
 -include include/config/auto.conf
 
 include scripts/Kbuild.include
 
-# For backward compatibility check that these variables does not change
+# For backward compatibility check that these variables do not change
 save-cflags := $(CFLAGS)
 
 # The filename Kbuild has precedence over Makefile
@@ -55,7 +55,7 @@ hostprogs-y += $(host-progs)
 endif
 endif
 
-# Do not include host rules unles needed
+# Do not include host rules unless needed
 ifneq ($(hostprogs-y)$(hostprogs-m),)
 include scripts/Makefile.host
 endif
index 2c647107c9ccadef446364a70dc16af552d3b237..6f89fbb56256987bf0c002683f85941ccddc861a 100644 (file)
@@ -37,7 +37,7 @@ subdir-ymn      := $(sort $(subdir-ym) $(subdir-n) $(subdir-))
 
 subdir-ymn     := $(addprefix $(obj)/,$(subdir-ymn))
 
-# build a list of files to remove, usually releative to the current
+# build a list of files to remove, usually relative to the current
 # directory
 
 __clean-files  := $(extra-y) $(always)                  \
index 6943a7a5bb989a9b9c3728fa267c818ab4e52a15..1ac414fd50300384663248c0ac651c9887bfe45d 100644 (file)
@@ -3,9 +3,9 @@
 # Binaries are used during the compilation of the kernel, for example
 # to preprocess a data file.
 #
-# Both C and C++ is supported, but preferred language is C for such utilities.
+# Both C and C++ are supported, but preferred language is C for such utilities.
 #
-# Samle syntax (see Documentation/kbuild/makefile.txt for reference)
+# Sample syntax (see Documentation/kbuild/makefiles.txt for reference)
 # hostprogs-y := bin2hex
 # Will compile bin2hex.c and create an executable named bin2hex
 #
 # hostprogs-y := conf
 # conf-objs  := conf.o libkconfig.so
 # libkconfig-objs := expr.o type.o
-# Will create a shared library named libkconfig.so that consist of
-# expr.o and type.o (they are both compiled as C code and the object file
+# Will create a shared library named libkconfig.so that consists of
+# expr.o and type.o (they are both compiled as C code and the object files
 # are made as position independent code).
-# conf.c is compiled as a c program, and conf.o is linked together with
+# conf.c is compiled as a C program, and conf.o is linked together with
 # libkconfig.so as the executable conf.
 # Note: Shared libraries consisting of C++ files are not supported
 
@@ -61,7 +61,7 @@ host-cobjs    := $(filter-out %.so,$(host-cobjs))
 host-cshobjs   := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs))))
 
 # output directory for programs/.o files
-# hostprogs-y := tools/build may have been specified. Retreive directory
+# hostprogs-y := tools/build may have been specified. Retrieve directory
 host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f))))
 # directory of .o files from prog-objs notation
 host-objdirs += $(foreach f,$(host-cmulti),                  \
index 2d20640854b7412bd46156f568a9a29443b6c0aa..a098a0454dc8ba50e9fcce958976f9f93aefa1ae 100644 (file)
@@ -42,6 +42,13 @@ _modpost: __modpost
 
 include include/config/auto.conf
 include scripts/Kbuild.include
+
+ifneq ($(KBUILD_EXTMOD),)
+# Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS
+include $(if $(wildcard $(KBUILD_EXTMOD)/Kbuild), \
+             $(KBUILD_EXTMOD)/Kbuild, $(KBUILD_EXTMOD)/Makefile)
+endif
+
 include scripts/Makefile.lib
 
 kernelsymfile := $(objtree)/Module.symvers
@@ -69,6 +76,7 @@ modpost = scripts/mod/modpost                    \
  $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,)       \
  $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile)   \
  $(if $(KBUILD_EXTMOD),-I $(modulesymfile))      \
+ $(if $(KBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(EXTRA_SYMBOLS))) \
  $(if $(KBUILD_EXTMOD),-o $(modulesymfile))      \
  $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S)      \
  $(if $(CONFIG_MARKERS),-K $(kernelmarkersfile)) \
index 58a94947d6557e0783ef1043b77cb7e8a57bc30d..64ec4b8a51b502cca0b37638f4443813d65d35ae 100755 (executable)
@@ -1889,6 +1889,13 @@ sub process {
                                WARN("kfree(NULL) is safe this check is probabally not required\n" . $hereprev);
                        }
                }
+# check for needless usb_free_urb() checks
+               if ($prevline =~ /\bif\s*\(([^\)]*)\)/) {
+                       my $expr = $1;
+                       if ($line =~ /\busb_free_urb\(\Q$expr\E\);/) {
+                               WARN("usb_free_urb(NULL) is safe this check is probabally not required\n" . $hereprev);
+                       }
+               }
 
 # warn about #ifdefs in C files
 #              if ($line =~ /^.#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
index 32e8c5a227c3a28bab34514da98e1491d057bef4..fa1a7d565903075ef39d12ba69ecf580b3c37de9 100644 (file)
@@ -36,10 +36,10 @@ update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h
            --output $(obj)/config.pot
        $(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot
        $(Q)ln -fs Kconfig.i386 arch/um/Kconfig.arch
-       $(Q)(for i in `ls arch/`;                        \
+       $(Q)(for i in `ls arch/*/Kconfig`;               \
            do                                           \
                echo "  GEN $$i";                        \
-               $(obj)/kxgettext arch/$$i/Kconfig        \
+               $(obj)/kxgettext $$i                     \
                     >> $(obj)/config.pot;               \
            done )
        $(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \
index 110cf243fa4e56d3749781c7b4703bf4c62ae9b7..757294b4f3222d28dfeef6415f9784a497b23c84 100644 (file)
@@ -1552,6 +1552,10 @@ static void read_symbols(char *modname)
        }
 
        license = get_modinfo(info.modinfo, info.modinfo_len, "license");
+       if (info.modinfo && !license && !is_vmlinux(modname))
+               warn("modpost: missing MODULE_LICENSE() in %s\n"
+                    "see include/linux/module.h for "
+                    "more information\n", modname);
        while (license) {
                if (license_is_gpl_compatible(license))
                        mod->gpl_compatible = 1;
@@ -2015,6 +2019,11 @@ static void write_markers(const char *fname)
        write_if_changed(&buf, fname);
 }
 
+struct ext_sym_list {
+       struct ext_sym_list *next;
+       const char *file;
+};
+
 int main(int argc, char **argv)
 {
        struct module *mod;
@@ -2025,8 +2034,10 @@ int main(int argc, char **argv)
        char *markers_write = NULL;
        int opt;
        int err;
+       struct ext_sym_list *extsym_iter;
+       struct ext_sym_list *extsym_start = NULL;
 
-       while ((opt = getopt(argc, argv, "i:I:cmsSo:awM:K:")) != -1) {
+       while ((opt = getopt(argc, argv, "i:I:e:cmsSo:awM:K:")) != -1) {
                switch (opt) {
                case 'i':
                        kernel_read = optarg;
@@ -2038,6 +2049,14 @@ int main(int argc, char **argv)
                case 'c':
                        cross_build = 1;
                        break;
+               case 'e':
+                       external_module = 1;
+                       extsym_iter =
+                          NOFAIL(malloc(sizeof(*extsym_iter)));
+                       extsym_iter->next = extsym_start;
+                       extsym_iter->file = optarg;
+                       extsym_start = extsym_iter;
+                       break;
                case 'm':
                        modversions = 1;
                        break;
@@ -2071,6 +2090,12 @@ int main(int argc, char **argv)
                read_dump(kernel_read, 1);
        if (module_read)
                read_dump(module_read, 0);
+       while (extsym_start) {
+               read_dump(extsym_start->file, 0);
+               extsym_iter = extsym_start->next;
+               free(extsym_start);
+               extsym_start = extsym_iter;
+       }
 
        while (optind < argc)
                read_symbols(argv[optind++]);
index b2e12893e3f4d4b0f39d64ff733333171e3a0dfb..c82cf15730a1e85c751483f75944e8905c0baa10 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/kvm_para.h>
 #include <linux/pagemap.h>
 #include <linux/mman.h>
+#include <linux/swap.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
@@ -59,7 +60,7 @@ EXPORT_SYMBOL_GPL(kvm_vcpu_cache);
 
 static __read_mostly struct preempt_ops kvm_preempt_ops;
 
-static struct dentry *debugfs_dir;
+struct dentry *kvm_debugfs_dir;
 
 static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
                           unsigned long arg);
@@ -119,6 +120,29 @@ void kvm_flush_remote_tlbs(struct kvm *kvm)
        smp_call_function_mask(cpus, ack_flush, NULL, 1);
 }
 
+void kvm_reload_remote_mmus(struct kvm *kvm)
+{
+       int i, cpu;
+       cpumask_t cpus;
+       struct kvm_vcpu *vcpu;
+
+       cpus_clear(cpus);
+       for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+               vcpu = kvm->vcpus[i];
+               if (!vcpu)
+                       continue;
+               if (test_and_set_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
+                       continue;
+               cpu = vcpu->cpu;
+               if (cpu != -1 && cpu != raw_smp_processor_id())
+                       cpu_set(cpu, cpus);
+       }
+       if (cpus_empty(cpus))
+               return;
+       smp_call_function_mask(cpus, ack_flush, NULL, 1);
+}
+
+
 int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
 {
        struct page *page;
@@ -170,6 +194,7 @@ static struct kvm *kvm_create_vm(void)
        mutex_init(&kvm->lock);
        kvm_io_bus_init(&kvm->mmio_bus);
        init_rwsem(&kvm->slots_lock);
+       atomic_set(&kvm->users_count, 1);
        spin_lock(&kvm_lock);
        list_add(&kvm->vm_list, &vm_list);
        spin_unlock(&kvm_lock);
@@ -189,9 +214,13 @@ static void kvm_free_physmem_slot(struct kvm_memory_slot *free,
        if (!dont || free->dirty_bitmap != dont->dirty_bitmap)
                vfree(free->dirty_bitmap);
 
+       if (!dont || free->lpage_info != dont->lpage_info)
+               vfree(free->lpage_info);
+
        free->npages = 0;
        free->dirty_bitmap = NULL;
        free->rmap = NULL;
+       free->lpage_info = NULL;
 }
 
 void kvm_free_physmem(struct kvm *kvm)
@@ -215,11 +244,25 @@ static void kvm_destroy_vm(struct kvm *kvm)
        mmdrop(mm);
 }
 
+void kvm_get_kvm(struct kvm *kvm)
+{
+       atomic_inc(&kvm->users_count);
+}
+EXPORT_SYMBOL_GPL(kvm_get_kvm);
+
+void kvm_put_kvm(struct kvm *kvm)
+{
+       if (atomic_dec_and_test(&kvm->users_count))
+               kvm_destroy_vm(kvm);
+}
+EXPORT_SYMBOL_GPL(kvm_put_kvm);
+
+
 static int kvm_vm_release(struct inode *inode, struct file *filp)
 {
        struct kvm *kvm = filp->private_data;
 
-       kvm_destroy_vm(kvm);
+       kvm_put_kvm(kvm);
        return 0;
 }
 
@@ -301,6 +344,25 @@ int __kvm_set_memory_region(struct kvm *kvm,
                new.user_alloc = user_alloc;
                new.userspace_addr = mem->userspace_addr;
        }
+       if (npages && !new.lpage_info) {
+               int largepages = npages / KVM_PAGES_PER_HPAGE;
+               if (npages % KVM_PAGES_PER_HPAGE)
+                       largepages++;
+               if (base_gfn % KVM_PAGES_PER_HPAGE)
+                       largepages++;
+
+               new.lpage_info = vmalloc(largepages * sizeof(*new.lpage_info));
+
+               if (!new.lpage_info)
+                       goto out_free;
+
+               memset(new.lpage_info, 0, largepages * sizeof(*new.lpage_info));
+
+               if (base_gfn % KVM_PAGES_PER_HPAGE)
+                       new.lpage_info[0].write_count = 1;
+               if ((base_gfn+npages) % KVM_PAGES_PER_HPAGE)
+                       new.lpage_info[largepages-1].write_count = 1;
+       }
 
        /* Allocate page dirty bitmap if needed */
        if ((new.flags & KVM_MEM_LOG_DIRTY_PAGES) && !new.dirty_bitmap) {
@@ -397,6 +459,12 @@ int is_error_page(struct page *page)
 }
 EXPORT_SYMBOL_GPL(is_error_page);
 
+int is_error_pfn(pfn_t pfn)
+{
+       return pfn == bad_pfn;
+}
+EXPORT_SYMBOL_GPL(is_error_pfn);
+
 static inline unsigned long bad_hva(void)
 {
        return PAGE_OFFSET;
@@ -444,7 +512,7 @@ int kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn)
 }
 EXPORT_SYMBOL_GPL(kvm_is_visible_gfn);
 
-static unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn)
+unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn)
 {
        struct kvm_memory_slot *slot;
 
@@ -458,7 +526,7 @@ static unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn)
 /*
  * Requires current->mm->mmap_sem to be held
  */
-struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
+pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn)
 {
        struct page *page[1];
        unsigned long addr;
@@ -469,7 +537,7 @@ struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
        addr = gfn_to_hva(kvm, gfn);
        if (kvm_is_error_hva(addr)) {
                get_page(bad_page);
-               return bad_page;
+               return page_to_pfn(bad_page);
        }
 
        npages = get_user_pages(current, current->mm, addr, 1, 1, 1, page,
@@ -477,27 +545,71 @@ struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
 
        if (npages != 1) {
                get_page(bad_page);
-               return bad_page;
+               return page_to_pfn(bad_page);
        }
 
-       return page[0];
+       return page_to_pfn(page[0]);
+}
+
+EXPORT_SYMBOL_GPL(gfn_to_pfn);
+
+struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
+{
+       return pfn_to_page(gfn_to_pfn(kvm, gfn));
 }
 
 EXPORT_SYMBOL_GPL(gfn_to_page);
 
 void kvm_release_page_clean(struct page *page)
 {
-       put_page(page);
+       kvm_release_pfn_clean(page_to_pfn(page));
 }
 EXPORT_SYMBOL_GPL(kvm_release_page_clean);
 
+void kvm_release_pfn_clean(pfn_t pfn)
+{
+       put_page(pfn_to_page(pfn));
+}
+EXPORT_SYMBOL_GPL(kvm_release_pfn_clean);
+
 void kvm_release_page_dirty(struct page *page)
 {
+       kvm_release_pfn_dirty(page_to_pfn(page));
+}
+EXPORT_SYMBOL_GPL(kvm_release_page_dirty);
+
+void kvm_release_pfn_dirty(pfn_t pfn)
+{
+       kvm_set_pfn_dirty(pfn);
+       kvm_release_pfn_clean(pfn);
+}
+EXPORT_SYMBOL_GPL(kvm_release_pfn_dirty);
+
+void kvm_set_page_dirty(struct page *page)
+{
+       kvm_set_pfn_dirty(page_to_pfn(page));
+}
+EXPORT_SYMBOL_GPL(kvm_set_page_dirty);
+
+void kvm_set_pfn_dirty(pfn_t pfn)
+{
+       struct page *page = pfn_to_page(pfn);
        if (!PageReserved(page))
                SetPageDirty(page);
-       put_page(page);
 }
-EXPORT_SYMBOL_GPL(kvm_release_page_dirty);
+EXPORT_SYMBOL_GPL(kvm_set_pfn_dirty);
+
+void kvm_set_pfn_accessed(pfn_t pfn)
+{
+       mark_page_accessed(pfn_to_page(pfn));
+}
+EXPORT_SYMBOL_GPL(kvm_set_pfn_accessed);
+
+void kvm_get_pfn(pfn_t pfn)
+{
+       get_page(pfn_to_page(pfn));
+}
+EXPORT_SYMBOL_GPL(kvm_get_pfn);
 
 static int next_segment(unsigned long len, int offset)
 {
@@ -554,7 +666,9 @@ int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data,
        addr = gfn_to_hva(kvm, gfn);
        if (kvm_is_error_hva(addr))
                return -EFAULT;
+       pagefault_disable();
        r = __copy_from_user_inatomic(data, (void __user *)addr + offset, len);
+       pagefault_enable();
        if (r)
                return -EFAULT;
        return 0;
@@ -651,6 +765,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
         * We will block until either an interrupt or a signal wakes us up
         */
        while (!kvm_cpu_has_interrupt(vcpu)
+              && !kvm_cpu_has_pending_timer(vcpu)
               && !signal_pending(current)
               && !kvm_arch_vcpu_runnable(vcpu)) {
                set_current_state(TASK_INTERRUPTIBLE);
@@ -678,8 +793,10 @@ static int kvm_vcpu_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 
        if (vmf->pgoff == 0)
                page = virt_to_page(vcpu->run);
+#ifdef CONFIG_X86
        else if (vmf->pgoff == KVM_PIO_PAGE_OFFSET)
                page = virt_to_page(vcpu->arch.pio_data);
+#endif
        else
                return VM_FAULT_SIGBUS;
        get_page(page);
@@ -701,11 +818,11 @@ static int kvm_vcpu_release(struct inode *inode, struct file *filp)
 {
        struct kvm_vcpu *vcpu = filp->private_data;
 
-       fput(vcpu->kvm->filp);
+       kvm_put_kvm(vcpu->kvm);
        return 0;
 }
 
-static struct file_operations kvm_vcpu_fops = {
+static const struct file_operations kvm_vcpu_fops = {
        .release        = kvm_vcpu_release,
        .unlocked_ioctl = kvm_vcpu_ioctl,
        .compat_ioctl   = kvm_vcpu_ioctl,
@@ -723,9 +840,10 @@ static int create_vcpu_fd(struct kvm_vcpu *vcpu)
 
        r = anon_inode_getfd(&fd, &inode, &file,
                             "kvm-vcpu", &kvm_vcpu_fops, vcpu);
-       if (r)
+       if (r) {
+               kvm_put_kvm(vcpu->kvm);
                return r;
-       atomic_inc(&vcpu->kvm->filp->f_count);
+       }
        return fd;
 }
 
@@ -760,6 +878,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n)
        mutex_unlock(&kvm->lock);
 
        /* Now it's all set up, let userspace reach it */
+       kvm_get_kvm(kvm);
        r = create_vcpu_fd(vcpu);
        if (r < 0)
                goto unlink;
@@ -802,28 +921,39 @@ static long kvm_vcpu_ioctl(struct file *filp,
                r = kvm_arch_vcpu_ioctl_run(vcpu, vcpu->run);
                break;
        case KVM_GET_REGS: {
-               struct kvm_regs kvm_regs;
+               struct kvm_regs *kvm_regs;
 
-               memset(&kvm_regs, 0, sizeof kvm_regs);
-               r = kvm_arch_vcpu_ioctl_get_regs(vcpu, &kvm_regs);
-               if (r)
+               r = -ENOMEM;
+               kvm_regs = kzalloc(sizeof(struct kvm_regs), GFP_KERNEL);
+               if (!kvm_regs)
                        goto out;
+               r = kvm_arch_vcpu_ioctl_get_regs(vcpu, kvm_regs);
+               if (r)
+                       goto out_free1;
                r = -EFAULT;
-               if (copy_to_user(argp, &kvm_regs, sizeof kvm_regs))
-                       goto out;
+               if (copy_to_user(argp, kvm_regs, sizeof(struct kvm_regs)))
+                       goto out_free1;
                r = 0;
+out_free1:
+               kfree(kvm_regs);
                break;
        }
        case KVM_SET_REGS: {
-               struct kvm_regs kvm_regs;
+               struct kvm_regs *kvm_regs;
 
-               r = -EFAULT;
-               if (copy_from_user(&kvm_regs, argp, sizeof kvm_regs))
+               r = -ENOMEM;
+               kvm_regs = kzalloc(sizeof(struct kvm_regs), GFP_KERNEL);
+               if (!kvm_regs)
                        goto out;
-               r = kvm_arch_vcpu_ioctl_set_regs(vcpu, &kvm_regs);
+               r = -EFAULT;
+               if (copy_from_user(kvm_regs, argp, sizeof(struct kvm_regs)))
+                       goto out_free2;
+               r = kvm_arch_vcpu_ioctl_set_regs(vcpu, kvm_regs);
                if (r)
-                       goto out;
+                       goto out_free2;
                r = 0;
+out_free2:
+               kfree(kvm_regs);
                break;
        }
        case KVM_GET_SREGS: {
@@ -851,6 +981,30 @@ static long kvm_vcpu_ioctl(struct file *filp,
                r = 0;
                break;
        }
+       case KVM_GET_MP_STATE: {
+               struct kvm_mp_state mp_state;
+
+               r = kvm_arch_vcpu_ioctl_get_mpstate(vcpu, &mp_state);
+               if (r)
+                       goto out;
+               r = -EFAULT;
+               if (copy_to_user(argp, &mp_state, sizeof mp_state))
+                       goto out;
+               r = 0;
+               break;
+       }
+       case KVM_SET_MP_STATE: {
+               struct kvm_mp_state mp_state;
+
+               r = -EFAULT;
+               if (copy_from_user(&mp_state, argp, sizeof mp_state))
+                       goto out;
+               r = kvm_arch_vcpu_ioctl_set_mpstate(vcpu, &mp_state);
+               if (r)
+                       goto out;
+               r = 0;
+               break;
+       }
        case KVM_TRANSLATE: {
                struct kvm_translation tr;
 
@@ -1005,7 +1159,7 @@ static int kvm_vm_mmap(struct file *file, struct vm_area_struct *vma)
        return 0;
 }
 
-static struct file_operations kvm_vm_fops = {
+static const struct file_operations kvm_vm_fops = {
        .release        = kvm_vm_release,
        .unlocked_ioctl = kvm_vm_ioctl,
        .compat_ioctl   = kvm_vm_ioctl,
@@ -1024,12 +1178,10 @@ static int kvm_dev_ioctl_create_vm(void)
                return PTR_ERR(kvm);
        r = anon_inode_getfd(&fd, &inode, &file, "kvm-vm", &kvm_vm_fops, kvm);
        if (r) {
-               kvm_destroy_vm(kvm);
+               kvm_put_kvm(kvm);
                return r;
        }
 
-       kvm->filp = file;
-
        return fd;
 }
 
@@ -1059,7 +1211,15 @@ static long kvm_dev_ioctl(struct file *filp,
                r = -EINVAL;
                if (arg)
                        goto out;
-               r = 2 * PAGE_SIZE;
+               r = PAGE_SIZE;     /* struct kvm_run */
+#ifdef CONFIG_X86
+               r += PAGE_SIZE;    /* pio data page */
+#endif
+               break;
+       case KVM_TRACE_ENABLE:
+       case KVM_TRACE_PAUSE:
+       case KVM_TRACE_DISABLE:
+               r = kvm_trace_ioctl(ioctl, arg);
                break;
        default:
                return kvm_arch_dev_ioctl(filp, ioctl, arg);
@@ -1232,9 +1392,9 @@ static void kvm_init_debug(void)
 {
        struct kvm_stats_debugfs_item *p;
 
-       debugfs_dir = debugfs_create_dir("kvm", NULL);
+       kvm_debugfs_dir = debugfs_create_dir("kvm", NULL);
        for (p = debugfs_entries; p->name; ++p)
-               p->dentry = debugfs_create_file(p->name, 0444, debugfs_dir,
+               p->dentry = debugfs_create_file(p->name, 0444, kvm_debugfs_dir,
                                                (void *)(long)p->offset,
                                                stat_fops[p->kind]);
 }
@@ -1245,7 +1405,7 @@ static void kvm_exit_debug(void)
 
        for (p = debugfs_entries; p->name; ++p)
                debugfs_remove(p->dentry);
-       debugfs_remove(debugfs_dir);
+       debugfs_remove(kvm_debugfs_dir);
 }
 
 static int kvm_suspend(struct sys_device *dev, pm_message_t state)
@@ -1272,6 +1432,7 @@ static struct sys_device kvm_sysdev = {
 };
 
 struct page *bad_page;
+pfn_t bad_pfn;
 
 static inline
 struct kvm_vcpu *preempt_notifier_to_vcpu(struct preempt_notifier *pn)
@@ -1313,6 +1474,8 @@ int kvm_init(void *opaque, unsigned int vcpu_size,
                goto out;
        }
 
+       bad_pfn = page_to_pfn(bad_page);
+
        r = kvm_arch_hardware_setup();
        if (r < 0)
                goto out_free_0;
@@ -1386,6 +1549,7 @@ EXPORT_SYMBOL_GPL(kvm_init);
 
 void kvm_exit(void)
 {
+       kvm_trace_cleanup();
        misc_deregister(&kvm_dev);
        kmem_cache_destroy(kvm_vcpu_cache);
        sysdev_unregister(&kvm_sysdev);
diff --git a/virt/kvm/kvm_trace.c b/virt/kvm/kvm_trace.c
new file mode 100644 (file)
index 0000000..0e49547
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * kvm trace
+ *
+ * It is designed to allow debugging traces of kvm to be generated
+ * on UP / SMP machines.  Each trace entry can be timestamped so that
+ * it's possible to reconstruct a chronological record of trace events.
+ * The implementation refers to blktrace kernel support.
+ *
+ * Copyright (c) 2008 Intel Corporation
+ * Copyright (C) 2006 Jens Axboe <axboe@kernel.dk>
+ *
+ * Authors: Feng(Eric) Liu, eric.e.liu@intel.com
+ *
+ * Date:    Feb 2008
+ */
+
+#include <linux/module.h>
+#include <linux/relay.h>
+#include <linux/debugfs.h>
+
+#include <linux/kvm_host.h>
+
+#define KVM_TRACE_STATE_RUNNING        (1 << 0)
+#define KVM_TRACE_STATE_PAUSE          (1 << 1)
+#define KVM_TRACE_STATE_CLEARUP        (1 << 2)
+
+struct kvm_trace {
+       int trace_state;
+       struct rchan *rchan;
+       struct dentry *lost_file;
+       atomic_t lost_records;
+};
+static struct kvm_trace *kvm_trace;
+
+struct kvm_trace_probe {
+       const char *name;
+       const char *format;
+       u32 cycle_in;
+       marker_probe_func *probe_func;
+};
+
+static inline int calc_rec_size(int cycle, int extra)
+{
+       int rec_size = KVM_TRC_HEAD_SIZE;
+
+       rec_size += extra;
+       return cycle ? rec_size += KVM_TRC_CYCLE_SIZE : rec_size;
+}
+
+static void kvm_add_trace(void *probe_private, void *call_data,
+                         const char *format, va_list *args)
+{
+       struct kvm_trace_probe *p = probe_private;
+       struct kvm_trace *kt = kvm_trace;
+       struct kvm_trace_rec rec;
+       struct kvm_vcpu *vcpu;
+       int    i, extra, size;
+
+       if (unlikely(kt->trace_state != KVM_TRACE_STATE_RUNNING))
+               return;
+
+       rec.event       = va_arg(*args, u32);
+       vcpu            = va_arg(*args, struct kvm_vcpu *);
+       rec.pid         = current->tgid;
+       rec.vcpu_id     = vcpu->vcpu_id;
+
+       extra           = va_arg(*args, u32);
+       WARN_ON(!(extra <= KVM_TRC_EXTRA_MAX));
+       extra           = min_t(u32, extra, KVM_TRC_EXTRA_MAX);
+       rec.extra_u32   = extra;
+
+       rec.cycle_in    = p->cycle_in;
+
+       if (rec.cycle_in) {
+               u64 cycle = 0;
+
+               cycle = get_cycles();
+               rec.u.cycle.cycle_lo = (u32)cycle;
+               rec.u.cycle.cycle_hi = (u32)(cycle >> 32);
+
+               for (i = 0; i < rec.extra_u32; i++)
+                       rec.u.cycle.extra_u32[i] = va_arg(*args, u32);
+       } else {
+               for (i = 0; i < rec.extra_u32; i++)
+                       rec.u.nocycle.extra_u32[i] = va_arg(*args, u32);
+       }
+
+       size = calc_rec_size(rec.cycle_in, rec.extra_u32 * sizeof(u32));
+       relay_write(kt->rchan, &rec, size);
+}
+
+static struct kvm_trace_probe kvm_trace_probes[] = {
+       { "kvm_trace_entryexit", "%u %p %u %u %u %u %u %u", 1, kvm_add_trace },
+       { "kvm_trace_handler", "%u %p %u %u %u %u %u %u", 0, kvm_add_trace },
+};
+
+static int lost_records_get(void *data, u64 *val)
+{
+       struct kvm_trace *kt = data;
+
+       *val = atomic_read(&kt->lost_records);
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(kvm_trace_lost_ops, lost_records_get, NULL, "%llu\n");
+
+/*
+ *  The relay channel is used in "no-overwrite" mode, it keeps trace of how
+ *  many times we encountered a full subbuffer, to tell user space app the
+ *  lost records there were.
+ */
+static int kvm_subbuf_start_callback(struct rchan_buf *buf, void *subbuf,
+                                    void *prev_subbuf, size_t prev_padding)
+{
+       struct kvm_trace *kt;
+
+       if (!relay_buf_full(buf))
+               return 1;
+
+       kt = buf->chan->private_data;
+       atomic_inc(&kt->lost_records);
+
+       return 0;
+}
+
+static struct dentry *kvm_create_buf_file_callack(const char *filename,
+                                                struct dentry *parent,
+                                                int mode,
+                                                struct rchan_buf *buf,
+                                                int *is_global)
+{
+       return debugfs_create_file(filename, mode, parent, buf,
+                                  &relay_file_operations);
+}
+
+static int kvm_remove_buf_file_callback(struct dentry *dentry)
+{
+       debugfs_remove(dentry);
+       return 0;
+}
+
+static struct rchan_callbacks kvm_relay_callbacks = {
+       .subbuf_start           = kvm_subbuf_start_callback,
+       .create_buf_file        = kvm_create_buf_file_callack,
+       .remove_buf_file        = kvm_remove_buf_file_callback,
+};
+
+static int do_kvm_trace_enable(struct kvm_user_trace_setup *kuts)
+{
+       struct kvm_trace *kt;
+       int i, r = -ENOMEM;
+
+       if (!kuts->buf_size || !kuts->buf_nr)
+               return -EINVAL;
+
+       kt = kzalloc(sizeof(*kt), GFP_KERNEL);
+       if (!kt)
+               goto err;
+
+       r = -EIO;
+       atomic_set(&kt->lost_records, 0);
+       kt->lost_file = debugfs_create_file("lost_records", 0444, kvm_debugfs_dir,
+                                           kt, &kvm_trace_lost_ops);
+       if (!kt->lost_file)
+               goto err;
+
+       kt->rchan = relay_open("trace", kvm_debugfs_dir, kuts->buf_size,
+                               kuts->buf_nr, &kvm_relay_callbacks, kt);
+       if (!kt->rchan)
+               goto err;
+
+       kvm_trace = kt;
+
+       for (i = 0; i < ARRAY_SIZE(kvm_trace_probes); i++) {
+               struct kvm_trace_probe *p = &kvm_trace_probes[i];
+
+               r = marker_probe_register(p->name, p->format, p->probe_func, p);
+               if (r)
+                       printk(KERN_INFO "Unable to register probe %s\n",
+                              p->name);
+       }
+
+       kvm_trace->trace_state = KVM_TRACE_STATE_RUNNING;
+
+       return 0;
+err:
+       if (kt) {
+               if (kt->lost_file)
+                       debugfs_remove(kt->lost_file);
+               if (kt->rchan)
+                       relay_close(kt->rchan);
+               kfree(kt);
+       }
+       return r;
+}
+
+static int kvm_trace_enable(char __user *arg)
+{
+       struct kvm_user_trace_setup kuts;
+       int ret;
+
+       ret = copy_from_user(&kuts, arg, sizeof(kuts));
+       if (ret)
+               return -EFAULT;
+
+       ret = do_kvm_trace_enable(&kuts);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int kvm_trace_pause(void)
+{
+       struct kvm_trace *kt = kvm_trace;
+       int r = -EINVAL;
+
+       if (kt == NULL)
+               return r;
+
+       if (kt->trace_state == KVM_TRACE_STATE_RUNNING) {
+               kt->trace_state = KVM_TRACE_STATE_PAUSE;
+               relay_flush(kt->rchan);
+               r = 0;
+       }
+
+       return r;
+}
+
+void kvm_trace_cleanup(void)
+{
+       struct kvm_trace *kt = kvm_trace;
+       int i;
+
+       if (kt == NULL)
+               return;
+
+       if (kt->trace_state == KVM_TRACE_STATE_RUNNING ||
+           kt->trace_state == KVM_TRACE_STATE_PAUSE) {
+
+               kt->trace_state = KVM_TRACE_STATE_CLEARUP;
+
+               for (i = 0; i < ARRAY_SIZE(kvm_trace_probes); i++) {
+                       struct kvm_trace_probe *p = &kvm_trace_probes[i];
+                       marker_probe_unregister(p->name, p->probe_func, p);
+               }
+
+               relay_close(kt->rchan);
+               debugfs_remove(kt->lost_file);
+               kfree(kt);
+       }
+}
+
+int kvm_trace_ioctl(unsigned int ioctl, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       long r = -EINVAL;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       switch (ioctl) {
+       case KVM_TRACE_ENABLE:
+               r = kvm_trace_enable(argp);
+               break;
+       case KVM_TRACE_PAUSE:
+               r = kvm_trace_pause();
+               break;
+       case KVM_TRACE_DISABLE:
+               r = 0;
+               kvm_trace_cleanup();
+               break;
+       }
+
+       return r;
+}